@sayren/store-sdk 0.40.0 → 0.42.0

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.mjs CHANGED
@@ -1,337 +1,5 @@
1
- import { a as WEBHOOK_HEADERS, i as WEBHOOK_EVENT_TYPE_HEADER, n as WEBHOOK_DELIVERY_ID_HEADER, o as WEBHOOK_SIGNATURE_HEADER, r as WEBHOOK_EVENT_ID_HEADER, s as WEBHOOK_USER_AGENT, t as WEBHOOK_DEFAULT_TOLERANCE_SEC } from "./webhook-headers-ap_exsb9.mjs";
1
+ import { A as auditLogPageSchema, C as approvalPageSchema, D as auditActorTypeSchema, E as auditActorSchema, F as strictRequest, M as auditLogSourceSchema, N as writeDryRunResultSchema, O as auditLogListQuerySchema, P as writePreviewSchema, S as approvalListQuerySchema, T as approvalStatusSchema, _ as resolveToken, a as WEBHOOK_HEADERS, b as agentPolicyDecisionSchema, c as APPROVAL_ALREADY_DECIDED_CODE, d as ApprovalPendingError, f as SAYREN_API_BASE_URL, g as path, h as createHttp, i as WEBHOOK_EVENT_TYPE_HEADER, j as auditLogSchema, k as auditLogOutcomeSchema, l as APPROVAL_REQUIRED_CODE, m as buildQuery, n as WEBHOOK_DELIVERY_ID_HEADER, o as WEBHOOK_SIGNATURE_HEADER, p as SAYREN_API_ORIGIN, r as WEBHOOK_EVENT_ID_HEADER, s as WEBHOOK_USER_AGENT, t as WEBHOOK_DEFAULT_TOLERANCE_SEC, u as ApiError, v as toApiError, w as approvalRequestSchema, x as approvalDecisionRequestSchema, y as unwrapData } from "./webhook-headers-D0E3wPpS.mjs";
2
2
  import { z } from "zod";
3
- //#region src/schemas/audit.ts
4
- /**
5
- * 감사 로그와 승인 요청 — `/v1/audit-logs`, `/v1/approval-requests` (이슈 #36).
6
- *
7
- * 관리 API 쓰기(`/v1/**`의 GET 외 요청)는 모두 요청 단위 기록(`source: REQUEST`) 한 줄을 남긴다. 환불·직권취소 같은
8
- * 도메인 동작은 그 안에서 변경 전후를 담은 기록(`source: DOMAIN`)을 따로 남기고 `requestId`로 요청 기록과 이어진다.
9
- */
10
- const auditActorTypeSchema = z.enum([
11
- "USER",
12
- "AGENT",
13
- "APP",
14
- "TOKEN",
15
- "SYSTEM"
16
- ]).describe("행위자 유형. `USER`=상점 플랫폼 사용자, `AGENT`=AI 에이전트(MCP·에이전트용 API 토큰), `APP`=앱(OAuth 클라이언트·M2M), `TOKEN`=API 토큰, `SYSTEM`=자동화(주기 잡)");
17
- const auditActorSchema = z.object({
18
- type: auditActorTypeSchema,
19
- id: z.string().describe("행위자 ID. `USER`=userId, `TOKEN`·`AGENT`(API 토큰)=`pat:{tokenId}`, `APP`=`client:{clientId}`, `SYSTEM`=`system`. 사람이 앱에 위임한 호출은 `APP`이고 위임한 사람은 `metadata.onBehalfOf`에 있다"),
20
- name: z.string().nullable().describe("기록 시점의 표시 이름. 알 수 없으면 null")
21
- });
22
- const auditLogSourceSchema = z.enum(["REQUEST", "DOMAIN"]).describe("기록 단위. `REQUEST`=관리 API 쓰기 요청 한 건, `DOMAIN`=환불·취소 같은 도메인 동작의 상세");
23
- const auditLogOutcomeSchema = z.enum([
24
- "SUCCEEDED",
25
- "FAILED",
26
- "PENDING_APPROVAL",
27
- "DENIED",
28
- "DRY_RUN"
29
- ]).describe("요청 결과. `PENDING_APPROVAL`=승인 대기로 보류(202), `DENIED`=에이전트 정책으로 거부(403 `AGENT_OPERATION_DENIED`), `DRY_RUN`=드라이런(`x-sayren-dry-run: 1`)이라 실행하지 않음");
30
- const auditLogSchema = z.object({
31
- auditId: z.string().describe("감사 로그 ID"),
32
- occurredAt: z.string().describe("기록 일시 (ISO 8601)"),
33
- source: auditLogSourceSchema,
34
- action: z.string().describe("동작. `REQUEST`는 오퍼레이션 ID(OpenAPI `operationId`, 예: `ProductsController_patch`), `DOMAIN`은 도메인 코드(예: `ORDER_ITEM_CANCELED_BY_SELLER`)"),
35
- actor: auditActorSchema,
36
- actorRole: z.string().nullable().describe("요청 시점의 상점 역할. 역할이 없는 토큰·자동화는 null"),
37
- target: z.object({
38
- type: z.string().describe("대상 리소스 유형 (예: `products`, `order-items`, `claim`)"),
39
- id: z.string().nullable().describe("대상 리소스 ID. 목록 대상 요청처럼 하나로 정할 수 없으면 null")
40
- }),
41
- requestId: z.string().nullable().describe("요청 ID. 같은 요청에서 나온 `REQUEST`·`DOMAIN` 기록이 같은 값을 가진다. 자동화는 null"),
42
- method: z.string().nullable().describe("HTTP 메서드 (`REQUEST`만)"),
43
- path: z.string().nullable().describe("요청 경로와 쿼리 (`REQUEST`만). 민감한 쿼리 값은 `***`로 가린다"),
44
- statusCode: z.number().int().nullable().describe("응답 HTTP 상태 코드 (`REQUEST`만)"),
45
- outcome: auditLogOutcomeSchema.nullable().describe("요청 결과 (`REQUEST`만)"),
46
- errorCode: z.string().nullable().describe("에러 응답의 `error.code` (실패한 요청만)"),
47
- traceId: z.string().nullable().describe("추적 ID. 에러 응답의 `error.traceId`와 같다"),
48
- idempotencyKey: z.string().nullable().describe("요청의 멱등키"),
49
- approvalId: z.string().nullable().describe("승인 요청 ID. 승인 대기로 보류된 요청과 승인 뒤 실행된 요청에 실린다"),
50
- metadata: z.record(z.string(), z.unknown()).describe("부가 정보. 도메인 기록은 변경 전후 값·사유를, 승인 실행 기록은 승인자(`approvedBy`)를 싣는다")
51
- });
52
- /** 쉼표 구분 목록 쿼리 → 배열 */
53
- function commaList(item) {
54
- return z.union([z.string(), z.array(z.string())]).transform((value) => (Array.isArray(value) ? value : [value]).flatMap((part) => part.split(",")).map((part) => part.trim()).filter((part) => part.length > 0)).pipe(z.array(item).min(1));
55
- }
56
- /** 감사 로그 조회 쿼리 — `GET /audit-logs` */
57
- const auditLogListQuerySchema = z.object({
58
- from: z.string().optional().describe("조회 시작 일시 (ISO 8601, 포함)"),
59
- to: z.string().optional().describe("조회 종료 일시 (ISO 8601, 미포함)"),
60
- actorType: commaList(auditActorTypeSchema).optional().describe("행위자 유형 필터. 여러 개는 쉼표로 구분한다 (예: `AGENT,APP`)"),
61
- actorId: z.string().optional().describe("행위자 ID 필터 (정확히 일치)"),
62
- action: z.string().optional().describe("동작 필터 (정확히 일치)"),
63
- targetType: z.string().optional().describe("대상 유형 필터 (정확히 일치)"),
64
- targetId: z.string().optional().describe("대상 ID 필터 (정확히 일치)"),
65
- source: auditLogSourceSchema.optional(),
66
- outcome: auditLogOutcomeSchema.optional(),
67
- requestId: z.string().optional().describe("요청 ID 필터 — 한 요청의 요청·도메인 기록을 함께 본다"),
68
- approvalId: z.string().optional().describe("승인 요청 ID 필터"),
69
- cursor: z.string().optional().describe("이전 응답의 `nextCursor`. 생략하면 가장 최신부터"),
70
- limit: z.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50)")
71
- });
72
- const auditLogPageSchema = z.object({
73
- items: z.array(auditLogSchema),
74
- nextCursor: z.string().nullable().describe("다음 페이지 커서. 마지막 페이지면 null")
75
- });
76
- const agentPolicyDecisionSchema = z.enum([
77
- "ALLOW",
78
- "APPROVAL_REQUIRED",
79
- "DENIED"
80
- ]).describe("에이전트 쓰기 판정. `ALLOW`=바로 실행, `APPROVAL_REQUIRED`=상점 플랫폼 승인 뒤 실행, `DENIED`=에이전트는 실행할 수 없음");
81
- const previewValueSchema = z.union([
82
- z.string(),
83
- z.number(),
84
- z.boolean(),
85
- z.null()
86
- ]);
87
- const writePreviewSchema = z.object({
88
- operationId: z.string().describe("오퍼레이션 ID"),
89
- method: z.string(),
90
- path: z.string(),
91
- target: z.object({
92
- type: z.string(),
93
- id: z.string().nullable()
94
- }),
95
- targetName: z.string().nullable().optional().describe("대상 이름(상품명·쿠폰명·흐름 이름·구매자 이름 등). 읽을 수 없으면 null"),
96
- changes: z.array(z.object({
97
- field: z.string().describe("바뀌는 필드"),
98
- before: z.unknown().describe("현재 값. 새로 만드는 요청이거나 읽을 수 없으면 null"),
99
- after: z.unknown().describe("요청이 넣을 값")
100
- })).describe("값이 달라지는 필드. 서버가 현재 값과 비교할 수 있는 오퍼레이션만 채운다"),
101
- facts: z.record(z.string(), previewValueSchema).describe("영향 요약 (예: 취소 수량·주문상품 금액·예상 환불액). 오퍼레이션마다 다르다")
102
- });
103
- /** `x-sayren-dry-run: 1`을 실은 쓰기 요청의 응답(200) — 실행하지 않고 판정과 영향만 돌려준다 */
104
- const writeDryRunResultSchema = z.object({
105
- dryRun: z.literal(true),
106
- decision: agentPolicyDecisionSchema,
107
- reason: z.string().nullable().describe("승인 필요·거부 사유. `ALLOW`면 null"),
108
- preview: writePreviewSchema
109
- });
110
- const approvalStatusSchema = z.enum([
111
- "PENDING",
112
- "EXECUTING",
113
- "SUCCEEDED",
114
- "FAILED",
115
- "UNKNOWN",
116
- "REJECTED",
117
- "EXPIRED"
118
- ]).describe("승인 요청 상태. `PENDING` 승인 대기 → 승인하면 `EXECUTING`(원 요청 실행 중) → `SUCCEEDED`·`FAILED`(원 요청의 응답 기준), 거절하면 `REJECTED`, 기한이 지나면 `EXPIRED`. 실행 응답을 받지 못했으면(타임아웃·서버 종료) `UNKNOWN`이다 — 서버가 감사 로그로 결과를 확정하면 `SUCCEEDED`·`FAILED`로 바뀌고, 확정하지 못하면 `UNKNOWN`에 남는다. `UNKNOWN`은 다시 실행하지 않는다(이미 실행됐을 수 있다)");
119
- const approvalRequestSchema = z.object({
120
- approvalId: z.string().describe("승인 요청 ID"),
121
- status: approvalStatusSchema,
122
- operationId: z.string().describe("보류된 오퍼레이션 ID"),
123
- operationName: z.string().nullable().optional().describe("작업 이름(예: 흐름 게시, 구매자 적립금 지급·차감). API 문서의 요약과 같다. 모르면 null"),
124
- method: z.string().describe("HTTP 메서드"),
125
- path: z.string().describe("요청 경로와 쿼리"),
126
- body: z.unknown().describe("요청 본문. 승인하면 이 본문 그대로 실행한다. 없으면 null"),
127
- idempotencyKey: z.string().nullable().describe("원 요청의 멱등키"),
128
- reason: z.string().describe("승인이 필요한 이유"),
129
- actor: auditActorSchema.describe("요청한 행위자"),
130
- preview: writePreviewSchema.nullable().describe("요청 시점에 서버가 계산한 영향 미리보기"),
131
- createdAt: z.string().describe("요청 일시 (ISO 8601)"),
132
- expiresAt: z.string().describe("승인 기한 (ISO 8601). 지나면 `EXPIRED`가 된다"),
133
- decidedAt: z.string().nullable().describe("승인·거절 일시"),
134
- decidedBy: z.object({
135
- id: z.string(),
136
- name: z.string().nullable()
137
- }).nullable().describe("승인·거절한 상점 플랫폼 사용자"),
138
- decisionNote: z.string().nullable().describe("승인·거절 메모"),
139
- executedAt: z.string().nullable().describe("원 요청 실행을 마친 일시"),
140
- result: z.object({
141
- statusCode: z.number().int().describe("원 요청의 응답 상태 코드"),
142
- data: z.unknown().describe("성공 응답의 `data` (큰 응답은 잘린다)"),
143
- error: z.object({
144
- code: z.string(),
145
- message: z.string()
146
- }).nullable().describe("실패 응답의 `error` 요약")
147
- }).nullable().describe("실행 결과. `SUCCEEDED`·`FAILED`·`UNKNOWN`에서 값이 있다. 감사 로그로 확정한 결과는 `data`가 null이다"),
148
- approvalUrl: z.string().nullable().describe("상점 플랫폼의 승인 화면 주소. 이 배포의 상점 플랫폼 주소를 알 수 없으면 null")
149
- });
150
- const approvalListQuerySchema = z.object({
151
- status: commaList(approvalStatusSchema).optional().describe("상태 필터. 여러 개는 쉼표로 구분한다 (예: `PENDING,EXECUTING`)"),
152
- cursor: z.string().optional().describe("이전 응답의 `nextCursor`. 생략하면 가장 최신부터"),
153
- limit: z.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50)")
154
- });
155
- const approvalPageSchema = z.object({
156
- items: z.array(approvalRequestSchema),
157
- nextCursor: z.string().nullable().describe("다음 페이지 커서. 마지막 페이지면 null")
158
- });
159
- const approvalDecisionRequestSchema = z.object({ note: z.string().trim().max(500).optional().describe("승인·거절 메모 (최대 500자)") });
160
- //#endregion
161
- //#region src/http.ts
162
- /** 표준 엔벨로프의 $.error 상세 */
163
- const errorDetailSchema = z.object({
164
- code: z.string(),
165
- message: z.string(),
166
- traceId: z.string().optional(),
167
- /**
168
- * 이 에러 코드를 설명하는 문서 URL(선택). 서버가 코드별 매핑을 가진 코드에만 실린다 —
169
- * 없으면 필드가 아예 없으므로 소비측은 있을 때만 쓴다
170
- */
171
- docs: z.url().optional().catch(void 0),
172
- /**
173
- * 에러 코드별 보조 데이터(선택). 예: 관리 API `LIVE_GATE_NOT_MET`의
174
- * `{ conditions: LiveGateCondition[] }`. 형태는 에러 코드마다 다르므로 소비측이 코드별 스키마로 다시 파싱한다
175
- */
176
- details: z.record(z.string(), z.unknown()).optional().catch(void 0)
177
- });
178
- /** 표준 응답 엔벨로프 — $.meta / $.data / $.error */
179
- const envelopeSchema = z.object({
180
- meta: z.object({
181
- status: z.number(),
182
- code: z.string(),
183
- message: z.string(),
184
- isSuccess: z.boolean()
185
- }),
186
- data: z.unknown().optional(),
187
- /** 구형 필드 — data로 개명되기 전 응답과의 전환기 호환 */
188
- content: z.unknown().optional(),
189
- error: errorDetailSchema.nullable()
190
- });
191
- /** OAuth 프로토콜 표면의 평면 에러 (RFC 6749 §5.2, RFC 7591 §3.2.2) */
192
- const oauthErrorSchema = z.object({
193
- error: z.string(),
194
- error_description: z.string().optional()
195
- });
196
- /** 표준 엔벨로프면 $.data(구형 $.content)를, 아니면(평면 응답) 본문 전체를 반환 */
197
- function unwrapData(json) {
198
- const envelope = envelopeSchema.safeParse(json);
199
- if (!envelope.success) return json;
200
- return envelope.data.data ?? envelope.data.content ?? null;
201
- }
202
- var ApiError = class extends Error {
203
- status;
204
- code;
205
- traceId;
206
- body;
207
- details;
208
- docs;
209
- constructor(status, code, message, traceId, body, details, docs) {
210
- super(message);
211
- this.status = status;
212
- this.code = code;
213
- this.traceId = traceId;
214
- this.body = body;
215
- this.details = details;
216
- this.docs = docs;
217
- this.name = "ApiError";
218
- }
219
- };
220
- /** 에이전트 쓰기가 승인 대기로 보류됐다(202) */
221
- const APPROVAL_REQUIRED_CODE = "APPROVAL_REQUIRED";
222
- /** 같은 멱등키의 승인 요청이 이미 끝났다(200) — 결과는 승인 요청의 `status`·`result`다 */
223
- const APPROVAL_ALREADY_DECIDED_CODE = "APPROVAL_ALREADY_DECIDED";
224
- /**
225
- * 쓰기 요청이 실행되지 않고 승인 흐름에 걸렸다 (이슈 #36). 응답 `data`가 요청한 리소스가 아니라 승인 요청이라
226
- * 성공 값으로 돌려주지 않는다 — 돌려주면 호출부가 승인 요청을 상품·주문으로 읽는다.
227
- *
228
- * - `code = APPROVAL_REQUIRED`(202): 에이전트의 고위험 쓰기가 보류됐다. 아직 아무것도 바뀌지 않았다.
229
- * 셀러가 상점 플랫폼(`approval.approvalUrl`)에서 승인하면 서버가 원 요청을 실행한다. 같은 요청을 다시 보내지 말고
230
- * `approvalRequests.get(approvalId)`로 결과를 확인한다.
231
- * - `code = APPROVAL_ALREADY_DECIDED`(200): 같은 멱등키로 보낸 요청의 승인이 이미 끝났다. `status`가
232
- * `SUCCEEDED`·`FAILED`·`UNKNOWN`이면 실행 결과(`approval.result`)를 보고, `REJECTED`·`EXPIRED`면 새 멱등키로 다시 요청한다.
233
- */
234
- var ApprovalPendingError = class extends Error {
235
- code;
236
- httpStatus;
237
- approval;
238
- approvalId;
239
- /** 승인 요청 상태 */
240
- status;
241
- constructor(code, httpStatus, approval, message) {
242
- super(message);
243
- this.code = code;
244
- this.httpStatus = httpStatus;
245
- this.approval = approval;
246
- this.name = "ApprovalPendingError";
247
- this.approvalId = approval.approvalId;
248
- this.status = approval.status;
249
- }
250
- };
251
- /** 성공 엔벨로프가 승인 흐름 응답이면 ApprovalPendingError. 그 밖(다른 202 등)은 null */
252
- function approvalErrorOf(status, json) {
253
- const envelope = envelopeSchema.safeParse(json);
254
- if (!envelope.success) return null;
255
- const { code, message } = envelope.data.meta;
256
- if (code !== "APPROVAL_REQUIRED" && code !== "APPROVAL_ALREADY_DECIDED") return null;
257
- const approval = approvalRequestSchema.safeParse(envelope.data.data);
258
- if (!approval.success) return null;
259
- return new ApprovalPendingError(code, status, approval.data, message);
260
- }
261
- /**
262
- * 에러 응답 본문 → ApiError 구성 (에러 형태의 단일 원천).
263
- * 표준 엔벨로프($.error) 우선, 구형 평면 에러({ code, message }), OAuth 평면 에러
264
- * ({ error, error_description } → code=error, message=error_description) 순으로 폴백하고,
265
- * 모두 아니면 UNKNOWN. createHttp의 send와 세션(userinfo 등 raw fetch 경로)이 동일한 에러 모양을 내도록 공유한다.
266
- */
267
- function toApiError(status, raw) {
268
- const envelope = envelopeSchema.safeParse(raw);
269
- const detail = envelope.success ? envelope.data.error : errorDetailSchema.safeParse(raw).data ?? null;
270
- if (detail) return new ApiError(status, detail.code, detail.message, detail.traceId, raw, detail.details, detail.docs);
271
- const oauth = envelope.success ? null : oauthErrorSchema.safeParse(raw).data;
272
- if (oauth) return new ApiError(status, oauth.error, oauth.error_description ?? oauth.error, void 0, raw);
273
- return new ApiError(status, "UNKNOWN", `HTTP ${status}`, void 0, raw);
274
- }
275
- /**
276
- * 경로 템플릿 태그 — 보간 값(경로 파라미터)마다 encodeURIComponent를 적용한다.
277
- * `/`·`?`·`#` 등이 섞인 id가 다른 경로·쿼리로 해석되지 않게 한다. 예: path`/products/${id}`
278
- */
279
- function path(strings, ...params) {
280
- return strings.reduce((acc, part, i) => acc + part + (i < params.length ? encodeURIComponent(String(params[i])) : ""), "");
281
- }
282
- function resolveToken(source) {
283
- return (typeof source === "function" ? source() : source) ?? null;
284
- }
285
- function buildQuery(query) {
286
- if (!query) return "";
287
- const params = new URLSearchParams();
288
- for (const [key, value] of Object.entries(query)) if (value !== void 0) params.set(key, String(value));
289
- const qs = params.toString();
290
- return qs ? `?${qs}` : "";
291
- }
292
- function createHttp(options) {
293
- const fetchFn = options.fetch ?? globalThis.fetch;
294
- async function send(method, path, request, retried = false) {
295
- const url = `${options.baseUrl}${path}${buildQuery(request?.query)}`;
296
- const headers = {
297
- ...request?.body !== void 0 ? { "content-type": "application/json" } : {},
298
- ...options.headers?.(),
299
- ...request?.headers
300
- };
301
- const response = await fetchFn(url, {
302
- method,
303
- headers,
304
- body: request?.body !== void 0 ? JSON.stringify(request.body) : void 0
305
- });
306
- options.onResponse?.(response);
307
- if (response.status === 401 && !retried && options.refresh) {
308
- if (await options.refresh()) return send(method, path, request, true);
309
- }
310
- if (!response.ok) {
311
- if (response.status === 401) options.onUnauthorized?.();
312
- const raw = await response.json().catch(() => null);
313
- throw toApiError(response.status, raw);
314
- }
315
- return response;
316
- }
317
- return {
318
- async request(method, path, schema, request) {
319
- const response = await send(method, path, request);
320
- const json = await response.json();
321
- const pending = approvalErrorOf(response.status, json);
322
- if (pending) throw pending;
323
- return schema.parse(unwrapData(json));
324
- },
325
- async requestVoid(method, path, request) {
326
- const response = await send(method, path, request);
327
- if (response.status === 204) return;
328
- const json = await response.json().catch(() => null);
329
- const pending = approvalErrorOf(response.status, json);
330
- if (pending) throw pending;
331
- }
332
- };
333
- }
334
- //#endregion
335
3
  //#region src/schemas/auth.ts
336
4
  const storeRoleSchema = z.enum([
337
5
  "OWNER",
@@ -1693,7 +1361,7 @@ const businessInfoResponseShape = {
1693
1361
  const autoDeliverDaysDescription = "발송 후 자동 배송완료까지의 일수(0~30, 기본 7). 발송(`DISPATCHED`)·배송중(`DELIVERING`) 주문상품을 이 기간이 지나면 배송완료(`DELIVERED`)로 바꾼다. `0`이면 자동 배송완료를 하지 않는다";
1694
1362
  const autoConfirmDaysDescription = "배송완료 후 자동 구매확정까지의 일수(0~30, 기본 7). 배송완료 시점에 구매확정 예정일(`autoDecisionDate`)을 이 값으로 잡고, 그 날짜가 지나면 구매확정(`PURCHASE_DECIDED`)으로 바꾼다. 진행 중인 클레임이 있으면 건너뛴다. `0`이면 자동 구매확정을 하지 않는다";
1695
1363
  /** `PATCH /v1/store` 본문 — 바꿀 필드만 보낸다 */
1696
- const updateStoreRequestSchema = z.object({
1364
+ const updateStoreRequestSchema = strictRequest(z.object({
1697
1365
  name: z.string().min(2).max(50).optional(),
1698
1366
  logoUrl: z.url().optional(),
1699
1367
  customerCenterPhone: z.string().nullable().optional().describe("고객센터 전화번호. `null`을 주면 지운다"),
@@ -1712,7 +1380,7 @@ const updateStoreRequestSchema = z.object({
1712
1380
  termsUrl: policyDocumentUrlSchema.optional().describe("이용약관 문서 주소(https). 동의 시점의 값이 동의 이력에 복사된다. `null`을 주면 지운다"),
1713
1381
  privacyUrl: policyDocumentUrlSchema.optional().describe("개인정보 수집이용 동의 문서 주소(https). `null`을 주면 지운다"),
1714
1382
  defaultLocale: localeCodeSchema.optional().describe("상점 기본 언어(이슈 #134). 상품·카테고리 필드가 이 언어 값이고 번역이 없는 칸은 이 값으로 보인다. 바꿔도 저장된 값은 그대로다")
1715
- }).refine((value) => Object.values(value).some((v) => v !== void 0), { message: "최소 1개 필드가 필요합니다" });
1383
+ }).refine((value) => Object.values(value).some((v) => v !== void 0), { message: "최소 1개 필드가 필요합니다" }));
1716
1384
  const storeSchema = z.object({
1717
1385
  storeId: z.string(),
1718
1386
  name: z.string(),
@@ -1789,12 +1457,12 @@ const invitationSchema = z.object({
1789
1457
  acceptedAt: z.string().nullable().default(null)
1790
1458
  });
1791
1459
  /** `POST /v1/store/invitations` 요청 — ADMIN 초대는 OWNER만 할 수 있다 */
1792
- const inviteMemberRequestSchema = z.object({
1460
+ const inviteMemberRequestSchema = strictRequest(z.object({
1793
1461
  email: z.email(),
1794
1462
  role: z.enum(["ADMIN", "STAFF"])
1795
- });
1463
+ }));
1796
1464
  /** `PATCH /v1/store/members/{userId}` 요청 */
1797
- const updateMemberRoleRequestSchema = z.object({ role: z.enum(["ADMIN", "STAFF"]) });
1465
+ const updateMemberRoleRequestSchema = strictRequest(z.object({ role: z.enum(["ADMIN", "STAFF"]) }));
1798
1466
  /** `GET /v1/store/invitations` 쿼리 — OpenAPI 문서용 형태 */
1799
1467
  const invitationListQuerySchema = z.object({ status: invitationSchema.shape.status.optional().describe("초대 상태 필터") });
1800
1468
  /** `PATCH /v1/store/members/{userId}` 응답 — 바뀐 역할 */
@@ -1821,7 +1489,7 @@ const sellerAddressSchema = z.object({
1821
1489
  inventoryLocationId: z.string().nullable().optional().describe("이 주소의 재고 위치 ID — 출고지면 배송 주문을 이 위치 재고로 팔고, 반품지면 반품을 이 위치로 들인다. 위치를 하나만 쓰는 상점은 기본 위치다"),
1822
1490
  createdAt: z.string()
1823
1491
  });
1824
- const sellerAddressRequestSchema = z.object({
1492
+ const sellerAddressRequestSchema = strictRequest(z.object({
1825
1493
  type: addressTypeSchema,
1826
1494
  name: z.string().min(1).max(50),
1827
1495
  contactName: z.string().min(1),
@@ -1830,7 +1498,7 @@ const sellerAddressRequestSchema = z.object({
1830
1498
  address1: z.string().min(1),
1831
1499
  address2: z.string().optional(),
1832
1500
  inventoryLocationId: z.string().min(1).optional().describe("재고 위치 ID. 등록에서 생략하면 기본 위치, 수정에서 생략하면 지금 연결을 유지한다")
1833
- });
1501
+ }));
1834
1502
  //#endregion
1835
1503
  //#region src/schemas/storefront-hosting.ts
1836
1504
  /**
@@ -1994,11 +1662,11 @@ const TEMPLATE_STORE_LOCKED_BUSINESS_FIELDS = [
1994
1662
  "customerCenterPhone",
1995
1663
  "customerCenterEmail"
1996
1664
  ];
1997
- const updateStoreTemplateRequestSchema = z.object({
1665
+ const updateStoreTemplateRequestSchema = strictRequest(z.object({
1998
1666
  name: z.string().trim().min(1).max(40).describe("템플릿 이름(1~40자)"),
1999
1667
  description: z.string().trim().max(200).describe("템플릿 소개(200자까지)"),
2000
1668
  thumbnailUrl: z.url({ protocol: /^https$/ }).max(2048).nullable().describe("썸네일 이미지 주소(https). 이미지 업로드(`POST /v1/uploads`)로 받은 주소를 쓴다. 없으면 null")
2001
- });
1669
+ }));
2002
1670
  /**
2003
1671
  * 버전 상태 — 템플릿 버전(`source: TEMPLATE`)은 템플릿 산출물을 그대로 쓰므로 만들 때 곧바로 `READY`다. 편집 버전
2004
1672
  * (`source: EDIT`, M2b)은 작업 트리 스냅샷을 빌드하는 동안 `BUILDING`이고, 빌드·규칙 검증을 통과하면 `READY`, 실패하면
@@ -2159,11 +1827,11 @@ const storefrontDeploymentSchema = z.object({
2159
1827
  attempts: z.number().int().describe("연속 실패 횟수"),
2160
1828
  nextAttemptAt: z.string().nullable().describe("다음 자동 시도 시각 (ISO 8601)")
2161
1829
  });
2162
- const createStorefrontSiteRequestSchema = z.object({
1830
+ const createStorefrontSiteRequestSchema = strictRequest(z.object({
2163
1831
  templateId: z.string().min(1).max(64).describe("템플릿 id"),
2164
1832
  slug: storefrontSlugSchema.optional().describe("주소 슬러그. 생략하면 상점 코드"),
2165
1833
  copyContent: z.boolean().optional().describe("템플릿 상점의 템플릿일 때만 — true면 템플릿 상점의 콘텐츠(레이아웃, 상품·카테고리·컬렉션·주문 흐름·배송·환불 정책)를 이 상점으로 복사한다. 쿠폰·적립금·리뷰는 복사하지 않는다. 생략하거나 false면 레이아웃 콘텐츠를 비우고 빌드한다")
2166
- });
1834
+ }));
2167
1835
  /** @deprecated 템플릿 변경은 지원하지 않는다(항상 409 `TEMPLATE_CHANGE_NOT_SUPPORTED`). 호환을 위해 스키마만 남겼다 */
2168
1836
  const changeStorefrontTemplateRequestSchema = z.object({
2169
1837
  templateId: z.string().min(1).max(64).describe("바꿀 템플릿 id"),
@@ -2175,28 +1843,28 @@ const changeStorefrontTemplateRequestSchema = z.object({
2175
1843
  * 지금 발행 버전이 그 값일 때만 바꾼다(화면을 본 뒤 다른 사람이 바꿨으면 409 `STOREFRONT_SITE_CHANGED`).
2176
1844
  * 이미 그 버전이 발행돼 있으면 아무것도 바꾸지 않고 200이다(같은 요청의 재실행이 안전하다).
2177
1845
  */
2178
- const publishStorefrontVersionRequestSchema = z.object({ expectedPublishedVersionId: z.string().nullable().optional().describe("화면에서 본 발행 버전 id (발행 전이었으면 null). 생략하면 확인하지 않는다") });
2179
- const rollbackStorefrontRequestSchema = z.object({
1846
+ const publishStorefrontVersionRequestSchema = strictRequest(z.object({ expectedPublishedVersionId: z.string().nullable().optional().describe("화면에서 본 발행 버전 id (발행 전이었으면 null). 생략하면 확인하지 않는다") }));
1847
+ const rollbackStorefrontRequestSchema = strictRequest(z.object({
2180
1848
  versionId: z.string().optional().describe("되돌릴 버전. 생략하면 지금 버전 직전에 발행했던 버전"),
2181
1849
  expectedPublishedVersionId: z.string().nullable().optional()
2182
- });
2183
- const changeStorefrontSlugRequestSchema = z.object({ slug: storefrontSlugSchema });
2184
- const setStorefrontVisibilityRequestSchema = z.object({
1850
+ }));
1851
+ const changeStorefrontSlugRequestSchema = strictRequest(z.object({ slug: storefrontSlugSchema }));
1852
+ const setStorefrontVisibilityRequestSchema = strictRequest(z.object({
2185
1853
  visibility: storefrontVisibilitySchema,
2186
1854
  expectedVisibility: storefrontVisibilitySchema.optional().describe("화면에서 본 공개 상태. 주면 지금 값이 같을 때만 바꾼다")
2187
- });
1855
+ }));
2188
1856
  /** 호스팅 끄기 — 사이트를 닫고(`CLOSED`) 슬러그를 보류한다. 확인 입력은 받지 않는다(2026-10-22) */
2189
- const disableStorefrontHostingRequestSchema = z.object({ confirmSlug: z.string().max(200).optional().describe("쓰지 않는다 — 보내도 무시한다(옛 확인 입력)") });
1857
+ const disableStorefrontHostingRequestSchema = strictRequest(z.object({ confirmSlug: z.string().max(200).optional().describe("쓰지 않는다 — 보내도 무시한다(옛 확인 입력)") }));
2190
1858
  const storefrontSlugAvailabilityQuerySchema = z.object({ slug: z.string().describe("확인할 슬러그") });
2191
1859
  /**
2192
1860
  * 버전 미리보기 링크 — 상점 플랫폼에서 로그인한 OWNER·ADMIN만 받는다(PAT·에이전트 불가). 버전마다 미리보기 전용 주소가 있고
2193
1861
  * (오픈 준비 중이어도 실제 화면), 링크를 5분 안에 열면 그 브라우저에 그 주소 전용 12시간 쿠키가 생긴다. 사이트 주소는 오픈 전이면
2194
1862
  * 누구에게나 「오픈 준비 중」이다. 미리보기 주소에 쿠키 없이 들어오면 상점 플랫폼 로그인과 OWNER·ADMIN 확인을 거친다.
2195
1863
  */
2196
- const createStorefrontPreviewLinkRequestSchema = z.object({
1864
+ const createStorefrontPreviewLinkRequestSchema = strictRequest(z.object({
2197
1865
  path: z.string().max(512).optional().describe("열 경로 (`/`로 시작). 생략하면 `/`"),
2198
1866
  versionId: z.string().max(64).optional().describe("볼 버전. 생략하면 발행 버전이다. 보관 기간이 지난 버전(`previewable: false`)은 409 `STOREFRONT_VERSION_NOT_PREVIEWABLE`")
2199
- });
1867
+ }));
2200
1868
  const storefrontPreviewLinkSchema = z.object({
2201
1869
  url: z.string().describe("미리보기 링크 — 5분 안에 연다"),
2202
1870
  editorUrl: z.string().optional().describe("편집 미리보기만: AI 편집 패널이 있는 미리보기 화면 링크(5분). 사이트는 그 안에 따로 뜨고 AI 자격은 사이트 코드에 닿지 않는다"),
@@ -2382,7 +2050,7 @@ const storefrontSiteDomainsSchema = z.object({
2382
2050
  target: z.string().describe("CNAME 대상 (예: `sites.sayren.co`)"),
2383
2051
  domains: z.array(storefrontSiteDomainSchema).describe("대표 주소 먼저, 그다음 추가한 순서")
2384
2052
  });
2385
- const addStorefrontDomainRequestSchema = z.object({ hostname: z.string().min(1).max(300).describe("연결할 도메인 (예: `shop.brand.com`). 서버가 소문자·punycode로 정규화한다") });
2053
+ const addStorefrontDomainRequestSchema = strictRequest(z.object({ hostname: z.string().min(1).max(300).describe("연결할 도메인 (예: `shop.brand.com`). 서버가 소문자·punycode로 정규화한다") }));
2386
2054
  /** 플랫폼 전체 동시 편집 환경 상한 */
2387
2055
  const STOREFRONT_EDIT_CAPACITY = 20;
2388
2056
  /** 활동이 없으면 편집 환경이 잠드는 시간(분). 작업 트리는 보존된다 */
@@ -2475,11 +2143,11 @@ const storefrontEditSessionSchema = z.object({
2475
2143
  * 편집 환경이 켜져 있지 않으면 409 `EDIT_SESSION_REQUIRED`
2476
2144
  */
2477
2145
  /** `POST /v1/storefront/site/editing/git/merge` — 켜진 편집 환경 작업 트리에 운영 브랜치 최신 커밋을 합친다(#138, Git 원천 사이트) */
2478
- const storefrontGitMergeRequestSchema = z.object({ action: z.enum([
2146
+ const storefrontGitMergeRequestSchema = strictRequest(z.object({ action: z.enum([
2479
2147
  "merge",
2480
2148
  "continue",
2481
2149
  "abort"
2482
- ]).default("merge").describe("`merge` 최신 운영 브랜치를 합친다 · `continue` 충돌 표시를 고친 뒤 합치기를 끝낸다 · `abort` 합치기를 취소하고 합치기 전으로 돌린다") });
2150
+ ]).default("merge").describe("`merge` 최신 운영 브랜치를 합친다 · `continue` 충돌 표시를 고친 뒤 합치기를 끝낸다 · `abort` 합치기를 취소하고 합치기 전으로 돌린다") }));
2483
2151
  const storefrontGitMergeSchema = z.object({
2484
2152
  status: z.enum([
2485
2153
  "MERGED",
@@ -2554,12 +2222,12 @@ const storefrontFileContentSchema = z.object({
2554
2222
  * 해시가 같아야 한다. 조건을 **모두** 확인한 뒤 쓰고, 하나라도 어긋나면 아무것도 쓰지 않는다(409 `FILE_CHANGED`,
2555
2223
  * `error.details.conflicts`).
2556
2224
  */
2557
- const writeStorefrontFilesRequestSchema = z.object({ files: z.array(z.object({
2225
+ const writeStorefrontFilesRequestSchema = strictRequest(z.object({ files: z.array(z.object({
2558
2226
  path: storefrontFilePathSchema,
2559
2227
  content: z.string().describe("내용 (`encoding`에 따라 텍스트 또는 base64)"),
2560
2228
  encoding: storefrontFileEncodingSchema.optional().describe("기본 `utf8`"),
2561
2229
  expectedHash: storefrontFileHashSchema.nullable().optional().describe("쓰기 조건. 생략 = 조건 없음 · null = 새 파일 · 값 = 지금 해시가 같을 때만")
2562
- })).min(1).max(50).refine((files) => new Set(files.map((file) => file.path)).size === files.length, { message: "같은 경로를 두 번 실을 수 없습니다" }) });
2230
+ })).min(1).max(50).refine((files) => new Set(files.map((file) => file.path)).size === files.length, { message: "같은 경로를 두 번 실을 수 없습니다" }) }));
2563
2231
  const storefrontFileWriteResultSchema = z.object({ files: z.array(storefrontFileEntrySchema).describe("쓴 파일의 새 해시·크기 (요청 순서)") });
2564
2232
  /** 409 `FILE_CHANGED`의 `error.details` */
2565
2233
  const storefrontFileConflictDetailsSchema = z.object({ conflicts: z.array(z.object({
@@ -2567,21 +2235,21 @@ const storefrontFileConflictDetailsSchema = z.object({ conflicts: z.array(z.obje
2567
2235
  currentHash: storefrontFileHashSchema.nullable().describe("지금 해시. 파일이 없으면 null")
2568
2236
  })) });
2569
2237
  /** `POST /v1/storefront/site/files/delete` — 없는 파일이면 `deleted: false`(조건을 주면 409 `FILE_CHANGED`) */
2570
- const deleteStorefrontFileRequestSchema = z.object({
2238
+ const deleteStorefrontFileRequestSchema = strictRequest(z.object({
2571
2239
  path: storefrontFilePathSchema,
2572
2240
  expectedHash: storefrontFileHashSchema.optional().describe("주면 지금 해시가 같을 때만 지운다")
2573
- });
2241
+ }));
2574
2242
  const storefrontFileDeleteResultSchema = z.object({
2575
2243
  path: z.string(),
2576
2244
  deleted: z.boolean()
2577
2245
  });
2578
2246
  /** `POST /v1/storefront/site/files/move` — 이름 바꾸기·옮기기 */
2579
- const moveStorefrontFileRequestSchema = z.object({
2247
+ const moveStorefrontFileRequestSchema = strictRequest(z.object({
2580
2248
  from: storefrontFilePathSchema,
2581
2249
  to: storefrontFilePathSchema,
2582
2250
  expectedHash: storefrontFileHashSchema.optional().describe("주면 `from`의 지금 해시가 같을 때만"),
2583
2251
  overwrite: z.boolean().optional().describe("`to`에 파일이 있으면 덮는가 (기본 false → 409 `FILE_EXISTS`)")
2584
- });
2252
+ }));
2585
2253
  const storefrontFileMoveResultSchema = z.object({
2586
2254
  from: z.string(),
2587
2255
  to: z.string(),
@@ -2591,7 +2259,7 @@ const storefrontFileMoveResultSchema = z.object({
2591
2259
  /** `POST /v1/storefront/site/files/search` — 텍스트 파일 내용 검색(편집 환경이 없어도 된다) */
2592
2260
  /** 정규식 검색의 패턴 길이 상한 — 편집 Sandbox가 실행 비용을 막으려고 더 좁게 받는다(sandbox-api §4.6) */
2593
2261
  const STOREFRONT_SEARCH_REGEX_MAX_LENGTH = 100;
2594
- const searchStorefrontFilesRequestSchema = z.object({
2262
+ const searchStorefrontFilesRequestSchema = strictRequest(z.object({
2595
2263
  query: z.string().min(1).max(200),
2596
2264
  regex: z.boolean().optional().describe("`query`를 정규식으로 본다 (기본 false = 글자 그대로). 정규식은 100자까지이고 중첩 수량자(`(a+)+`)·반복되는 선택(`(a|b)+`)·역참조·뒤 보기, 가변 수량자(`*`·`+`·`?`·`{n,m}`, 넓은 범위는 2로 센다) 차수 4 초과는 400 `INVALID_REQUEST`다. 차수가 클수록 긴 줄은 건너뛰고 비용이 크면 `truncated`로 끊는다"),
2597
2265
  caseSensitive: z.boolean().optional().describe("대소문자를 가리는가 (기본 false)"),
@@ -2600,7 +2268,7 @@ const searchStorefrontFilesRequestSchema = z.object({
2600
2268
  }).refine((body) => !body.regex || body.query.length <= 100, {
2601
2269
  message: `정규식은 100자까지입니다`,
2602
2270
  path: ["query"]
2603
- });
2271
+ }));
2604
2272
  const storefrontFileSearchResultSchema = z.object({
2605
2273
  matches: z.array(z.object({
2606
2274
  path: z.string(),
@@ -2616,11 +2284,11 @@ const storefrontFileSearchResultSchema = z.object({
2616
2284
  * `GET /v1/storefront/site/checks/{checkId}`로 조회한다(권장 2~3초 간격). 사이트당 끝나지 않은 검사는 하나다 — 같은 종류가 돌고
2617
2285
  * 있으면 그 검사를 다시 돌려주고, 다른 종류면 409 `CHECK_RUNNING`(`error.details.checkId`)이다. 출력은 꼬리만 준다.
2618
2286
  */
2619
- const runStorefrontCheckRequestSchema = z.object({ check: z.enum([
2287
+ const runStorefrontCheckRequestSchema = strictRequest(z.object({ check: z.enum([
2620
2288
  "typecheck",
2621
2289
  "lint",
2622
2290
  "test"
2623
- ]) });
2291
+ ]) }));
2624
2292
  const storefrontCheckStatusSchema = z.enum([
2625
2293
  "QUEUED",
2626
2294
  "RUNNING",
@@ -2768,10 +2436,10 @@ const storefrontBuildListQuerySchema = z.object({ limit: z.coerce.number().int()
2768
2436
  * `POST /v1/storefront/site/versions` — 지금 작업 트리를 고정해 버전을 만든다(빌드 시작). 사이트당 끝나지 않은 빌드는
2769
2437
  * 하나다(409 `STOREFRONT_BUILD_IN_PROGRESS`). 편집 환경이 없어도 된다.
2770
2438
  */
2771
- const createStorefrontVersionRequestSchema = z.object({
2439
+ const createStorefrontVersionRequestSchema = strictRequest(z.object({
2772
2440
  message: z.string().max(200).optional().describe("버전 메모 (에이전트는 바꾼 내용 요약)"),
2773
2441
  expectedSourceRef: z.string().max(200).optional().describe("고정할 작업 트리 (`PUT /v1/storefront/site/source`의 `sourceRef`). 주면 지금 작업 트리가 이 값일 때만 버전을 만든다(다르면 409 `SOURCE_CHANGED`)")
2774
- });
2442
+ }));
2775
2443
  /** 버전 만들기 응답 (201) — 버전은 `BUILDING`, 빌드는 `QUEUED`로 시작한다. 결과는 `GET builds/{buildId}`로 본다 */
2776
2444
  const storefrontVersionCreatedSchema = z.object({
2777
2445
  version: storefrontVersionSchema,
@@ -2782,7 +2450,7 @@ const storefrontVersionCreatedSchema = z.object({
2782
2450
  * 받는다(PAT·에이전트 불가). 5분 안에 열면 그 브라우저에 미리보기 호스트 전용 쿠키(12시간)가 생긴다. 편집 환경이
2783
2451
  * 없으면 409 `EDIT_SESSION_REQUIRED`다(편집 환경이 `STARTING`이면 링크는 주고, 미리보기 화면이 기동 대기를 보여 준다).
2784
2452
  */
2785
- const createStorefrontEditPreviewLinkRequestSchema = z.object({ path: z.string().max(512).optional().describe("열 경로 (`/`로 시작). 생략하면 `/`") });
2453
+ const createStorefrontEditPreviewLinkRequestSchema = strictRequest(z.object({ path: z.string().max(512).optional().describe("열 경로 (`/`로 시작). 생략하면 `/`") }));
2786
2454
  /** 압축 파일 조각 하나의 최대 크기(바이트) */
2787
2455
  const STOREFRONT_SOURCE_PART_BYTES = 4194304;
2788
2456
  /** 내용 올리기 한 번의 최대 파일 수 */
@@ -2824,10 +2492,10 @@ const storefrontSourceArchivePartSchema = z.object({
2824
2492
  content: z.string().describe("조각 내용 (base64)")
2825
2493
  });
2826
2494
  /** `POST /v1/storefront/site/source/blobs` — 파일 내용 올리기(해시 키, 다시 올려도 안전하다). 작업 트리는 바뀌지 않는다 */
2827
- const uploadStorefrontSourceBlobsRequestSchema = z.object({ blobs: z.array(z.object({
2495
+ const uploadStorefrontSourceBlobsRequestSchema = strictRequest(z.object({ blobs: z.array(z.object({
2828
2496
  hash: storefrontFileHashSchema,
2829
2497
  content: z.string().describe("파일 내용 (base64, 1MiB까지)")
2830
- })).min(1).max(200) });
2498
+ })).min(1).max(200) }));
2831
2499
  const storefrontSourceBlobsResultSchema = z.object({
2832
2500
  stored: z.number().int().min(0).describe("새로 올린 수"),
2833
2501
  existing: z.number().int().min(0).describe("이미 있던 수")
@@ -2836,7 +2504,7 @@ const storefrontSourceBlobsResultSchema = z.object({
2836
2504
  * `PUT /v1/storefront/site/source` — 작업 트리 전체를 이 목록으로 바꾼다(없는 경로는 지운다). 전부 아니면 전무다.
2837
2505
  * `package.json`·`pnpm-lock.yaml`도 바꿀 수 있고 의존성은 허용 목록 안이어야 한다. `.env*`·작업 트리 밖 경로는 받지 않는다.
2838
2506
  */
2839
- const replaceStorefrontSourceRequestSchema = z.object({
2507
+ const replaceStorefrontSourceRequestSchema = strictRequest(z.object({
2840
2508
  expectedBaseRef: storefrontSourceRefSchema.optional().describe("내려받은 작업 트리. 그 뒤 작업 트리가 바뀌었으면 이 트리를 기준으로 3-way 병합하고, 같은 곳을 고쳤으면 409 `SOURCE_CHANGED`다. 생략하면 조건 없이 덮어쓴다"),
2841
2509
  files: z.array(z.object({
2842
2510
  path: storefrontFilePathSchema,
@@ -2846,7 +2514,7 @@ const replaceStorefrontSourceRequestSchema = z.object({
2846
2514
  endEditSession: z.boolean().optional().describe("열린 편집 환경을 끄고 진행한다 (기본 false — 열려 있으면 409 `EDIT_SESSION_OPEN`)"),
2847
2515
  packageJson: z.string().max(STOREFRONT_FILE_MAX_BYTES).optional().describe("`files`에 `package.json`이 있으면 그 내용(utf8). 서버가 의존성을 판정한다. 해시가 목록과 다르면 400 `DEPENDENCY_FILES_MISMATCH`"),
2848
2516
  lockfile: z.string().max(STOREFRONT_FILE_MAX_BYTES).optional().describe("`files`에 `pnpm-lock.yaml`이 있으면 그 내용(utf8)")
2849
- });
2517
+ }));
2850
2518
  const storefrontSourceReplacedSchema = z.object({
2851
2519
  sourceRef: storefrontSourceRefSchema.describe("새 작업 트리(버전 만들기의 `expectedSourceRef`). 다음 올리기의 기준은 `uploadedRef`다"),
2852
2520
  previousRef: z.string().describe("바꾸기 전 작업 트리"),
@@ -2888,25 +2556,25 @@ const storefrontGitRepositorySchema = z.object({
2888
2556
  defaultBranch: z.string()
2889
2557
  });
2890
2558
  /** `POST /v1/storefront/site/git/installations` — GitHub App 설치 화면에서 돌아온 값(`installation_id`·`code`) */
2891
- const linkStorefrontGitInstallationRequestSchema = z.object({
2559
+ const linkStorefrontGitInstallationRequestSchema = strictRequest(z.object({
2892
2560
  installationId: z.number().int().positive(),
2893
2561
  code: z.string().min(1).max(200).describe("설치 화면이 돌려준 GitHub 사용자 인증 코드(한 번만 쓴다)"),
2894
2562
  state: z.string().min(1).max(200).describe("설치 화면으로 보내기 전에 받은 연결 state(`POST …/git/installations/state`, 한 번만 쓴다)")
2895
- });
2563
+ }));
2896
2564
  /** `POST /v1/storefront/site/git/installations/state` — GitHub 설치 화면에 싣는 1회용 state(이 상점·사용자, 10분) */
2897
2565
  const storefrontGitConnectStateSchema = z.object({
2898
2566
  state: z.string(),
2899
2567
  expiresAt: z.string()
2900
2568
  });
2901
2569
  /** `POST /v1/storefront/site/git/connect` */
2902
- const connectStorefrontGitRequestSchema = z.object({
2570
+ const connectStorefrontGitRequestSchema = strictRequest(z.object({
2903
2571
  installationId: z.number().int().positive(),
2904
2572
  repoId: z.number().int().positive(),
2905
2573
  productionBranch: z.string().min(1).max(200).regex(/^[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/).optional().describe("운영 배포 브랜치(생략하면 저장소 기본 브랜치)"),
2906
2574
  rootDirectory: z.string().max(200).regex(/^$|^[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*$/).refine((v) => !v.split("/").some((seg) => seg === "." || seg === ".."), "상대 경로만").optional().describe("저장소 안 사이트 루트(생략하면 저장소 루트)")
2907
- });
2575
+ }));
2908
2576
  /** `PUT /v1/storefront/site/deploy-approval` — 승인 없이 배포(#138) */
2909
- const setStorefrontDeployApprovalRequestSchema = z.object({ deployWithoutApproval: z.boolean() });
2577
+ const setStorefrontDeployApprovalRequestSchema = strictRequest(z.object({ deployWithoutApproval: z.boolean() }));
2910
2578
  //#endregion
2911
2579
  //#region src/schemas/ai.ts
2912
2580
  /**
@@ -2987,9 +2655,14 @@ const aiActivitySchema = z.enum([
2987
2655
  "version",
2988
2656
  "preview"
2989
2657
  ]);
2658
+ /** 바뀐 줄 미리보기 한 줄의 최대 길이 — 서버가 이 길이로 자르고 화면은 이보다 긴 줄을 앞부분으로 비교한다 */
2659
+ const AI_TOOL_CHANGE_LINE_MAX = 300;
2660
+ /** 바뀐 줄 범위(`lines`) 개수 상한 */
2661
+ const AI_TOOL_CHANGE_RANGES_MAX = 200;
2990
2662
  /**
2991
2663
  * 도구가 바꾼 파일 하나(2026-10-13, AI 상점 도우미 작업 공간의 수정 중인 코드) — 서버가 도구 입력으로 계산한다.
2992
- * `edit`는 바꾼 부분의 줄 비교, `write`는 새로 쓴 내용(이전 내용을 모르므로 모두 추가로 센다). `preview`는 바뀐 줄 앞부분 12줄까지다
2664
+ * `edit`는 바꾼 부분의 줄 비교, `write`는 새로 쓴 내용(이전 내용을 모르므로 모두 추가로 센다). `preview`는 바뀐 줄 앞부분 12줄까지다.
2665
+ * `lines`는 바꾼 뒤 파일에서 추가된 줄의 범위(1부터, 양끝 포함)다 — `edit`가 성공한 뒤에만 실행기가 채운다(옛 기록·`write`에는 없다)
2993
2666
  */
2994
2667
  const aiToolChangeSchema = z.object({
2995
2668
  path: z.string().max(300),
@@ -2999,7 +2672,8 @@ const aiToolChangeSchema = z.object({
2999
2672
  preview: z.array(z.object({
3000
2673
  kind: z.enum(["added", "removed"]),
3001
2674
  text: z.string().max(300)
3002
- })).max(12)
2675
+ })).max(12),
2676
+ lines: z.array(z.tuple([z.number().int().min(1), z.number().int().min(1)])).max(200).optional()
3003
2677
  });
3004
2678
  /**
3005
2679
  * 에이전트 작업 단계(2026-10-13, AI 상점 도우미 작업 공간) — 에이전트가 패널 도구로 알린다.
@@ -3015,29 +2689,49 @@ const AI_AGENT_PHASES = [
3015
2689
  ];
3016
2690
  const aiAgentPhaseSchema = z.enum(AI_AGENT_PHASES);
3017
2691
  /**
3018
- * AI 상점 도우미의 작업 메모 폴더(2026-10-14) — 회차마다 읽는 숨은 규칙(`rules.md`)과 디자인 계획(`design.md`). 셀러 화면(타임라인·코드 탭·변경 기록)에
3019
- * 보이지 않는다. 편집 Sandbox가 점(.)으로 시작하는 경로를 받지 않아 작업 트리의 `src` 아래에 둔다(앱이 import하지 않는 문서라 빌드에 들어가지 않는다)
2692
+ * AI 상점 도우미의 작업 메모 폴더(2026-10-14) — 회차마다 읽는 숨은 규칙(`rules.md`)과 디자인 계획(`design.md`). 편집 Sandbox가 점(.)으로 시작하는
2693
+ * 경로를 받지 않아 작업 트리의 `src` 아래에 둔다(앱이 import하지 않는 문서라 빌드에 들어가지 않는다). 숨은 규칙은 셀러 화면(타임라인·코드 탭·변경 기록)에
2694
+ * 보이지 않는다. 디자인 계획은 2026-10-24부터 셀러 문서(작업 공간 문서 탭의 「디자인 가이드라인」)라 숨기지 않는다(`AI_DESIGN_GUIDE_PATH`)
3020
2695
  */
3021
2696
  const AI_AGENT_NOTES_DIR = "src/site/agent";
2697
+ /** 디자인 가이드라인(디자인 계획) — 작업 메모 폴더에 있지만 셀러가 읽는 문서다 */
2698
+ const AI_DESIGN_GUIDE_PATH = `${AI_AGENT_NOTES_DIR}/design.md`;
2699
+ /** 사이트맵 — 에이전트가 쓰는 화면 구성 문서(`{version:1,pages:[…]}`) */
2700
+ const AI_SITEMAP_PATH = "src/site/sitemap.json";
2701
+ /** 작업 공간 문서 탭의 문서 파일인가(사이트맵·디자인 가이드라인) — 앱 코드가 아니라서 코드 탭·미리보기 점검·코드 변경 판정에서 뺀다 */
2702
+ function isAiWorkspaceDocPath(path) {
2703
+ return path === "src/site/sitemap.json" || path === AI_DESIGN_GUIDE_PATH;
2704
+ }
2705
+ /** 「이어서 진행」 버튼(실패한 실행 잇기)이 보내는 선택 값 — 선택지 답처럼 같은 할 일 목록을 잇는다 */
2706
+ const AI_RUN_RESUME_CHOICE = "run:resume";
3022
2707
  /**
3023
2708
  * 에이전트의 할 일 목록(2026-10-14, Claude Code의 TaskCreate·TaskUpdate·TaskList와 같다) — 에이전트가 패널 도구로 할 일을 만들고 상태를 바꾼다.
3024
- * 이벤트·조각은 그 시점의 목록 전체이고 작업 공간 왼쪽 패널이 마지막 목록을 체크리스트로 그린다. 진행중은 한 번에 하나다
2709
+ * 이벤트·조각은 그 시점의 목록 전체이고 작업 공간 로드맵 탭이 마지막 목록을 칸반으로 그린다. 진행중은 한 번에 하나다.
2710
+ * 목록은 셀러 요청 하나(사이클)의 일이다 — 새 요청이면 빈 목록에서 시작하고 선택지 답이면 잇는다(2026-10-24). 개수 상한은 없다
2711
+ * (옛 30개 상한은 대화 전체에 할 일이 쌓여 넘쳤다 — 크기는 사이클 범위가, 폭주는 턴 예산이 막는다).
2712
+ * `blocked`는 같은 문제를 거듭 고쳐도 남아 멈춘 일이고 `note`가 그 사유다(이어 가기 리마인더가 남은 일로 세지 않는다)
3025
2713
  */
3026
2714
  const AI_TODO_STATUSES = [
3027
2715
  "pending",
3028
2716
  "in_progress",
3029
- "completed"
2717
+ "completed",
2718
+ "blocked"
3030
2719
  ];
3031
2720
  const aiTodoSchema = z.object({
3032
- /** 할 일 번호(대화 안에서 1부터) — 옛 조각에는 없다 */
2721
+ /** 할 일 번호(사이클 안에서 1부터) — 옛 조각에는 없다 */
3033
2722
  id: z.string().max(10).optional(),
3034
2723
  content: z.string().min(1).max(200),
3035
2724
  status: z.enum(AI_TODO_STATUSES),
3036
2725
  /** 이 할 일이 속한 작업 단계 — 진행중이 되면 실행기가 단계를 알린다(2026-10-14, 모델이 단계 알림을 빠뜨렸다) */
3037
- phase: aiAgentPhaseSchema.optional()
2726
+ phase: aiAgentPhaseSchema.optional(),
2727
+ /** 막힌 사유(`blocked`일 때만) */
2728
+ note: z.string().max(300).optional()
3038
2729
  });
2730
+ /** @deprecated 할 일 개수 상한은 없앴다(2026-10-24). 공개 export라 값만 남긴다 */
3039
2731
  const AI_TODOS_MAX = 30;
2732
+ /** 셀러에게 보이지 않는 작업 메모인가 — 작업 메모 폴더에서 디자인 가이드라인을 뺀 나머지다 */
3040
2733
  function isAiAgentNotesPath(path) {
2734
+ if (path === AI_DESIGN_GUIDE_PATH) return false;
3041
2735
  return path === "src/site/agent" || path.startsWith(`src/site/agent/`);
3042
2736
  }
3043
2737
  /**
@@ -3148,7 +2842,9 @@ const AI_DESIGN_CONFIRM_APPROVE = "design:approve";
3148
2842
  const aiMessagePartSchema = z.discriminatedUnion("type", [
3149
2843
  z.object({
3150
2844
  type: z.literal("text"),
3151
- text: z.string()
2845
+ text: z.string(),
2846
+ /** 셀러가 선택지 버튼으로 보낸 답의 값(사용자 메시지만) — 할 일 목록(사이클)을 잇는 기준(`isAiChoiceAnswer`) */
2847
+ choice: z.string().max(200).optional()
3152
2848
  }),
3153
2849
  z.object({
3154
2850
  type: z.literal("tool"),
@@ -3213,7 +2909,7 @@ const aiMessagePartSchema = z.discriminatedUnion("type", [
3213
2909
  }),
3214
2910
  z.object({
3215
2911
  type: z.literal("todos"),
3216
- todos: z.array(aiTodoSchema).max(30)
2912
+ todos: z.array(aiTodoSchema)
3217
2913
  })
3218
2914
  ]);
3219
2915
  const aiMessageSchema = z.object({
@@ -3249,18 +2945,18 @@ const storeSetupBriefSchema = z.object({
3249
2945
  heroProduct: z.string().trim().max(500).describe("첫 화면에 크게 걸 상품 (비우면 AI가 정한다)"),
3250
2946
  slug: storefrontSlugSchema.optional().describe("바라는 스토어프론트 주소")
3251
2947
  });
3252
- const createAiConversationRequestSchema = z.object({
2948
+ const createAiConversationRequestSchema = strictRequest(z.object({
3253
2949
  /** 웹사이트에서 남긴 초안(#124 M2) — 연결한 사용자만 쓴다. 주면 첫 메시지로 실행을 시작한다 */
3254
2950
  draftId: z.string().max(64).optional(),
3255
2951
  /** 질문 화면의 답 — `draftId`와 함께만 쓴다. 초안 앞에 붙어 첫 메시지가 된다 */
3256
2952
  brief: storeSetupBriefSchema.optional()
3257
- });
2953
+ }));
3258
2954
  const createAiConversationResponseSchema = z.object({
3259
2955
  conversation: aiConversationSummarySchema,
3260
2956
  /** `draftId`로 시작했으면 첫 실행 */
3261
2957
  run: aiStreamAccessSchema.nullable()
3262
2958
  });
3263
- const sendAiMessageRequestSchema = z.object({
2959
+ const sendAiMessageRequestSchema = strictRequest(z.object({
3264
2960
  text: z.string().trim().max(AI_MESSAGE_MAX_CHARS),
3265
2961
  attachments: z.array(aiAttachmentSchema).max(5).default([]),
3266
2962
  /** 선택지 버튼으로 보낸 답이면 그 값(화면 표시는 `text`) */
@@ -3269,7 +2965,7 @@ const sendAiMessageRequestSchema = z.object({
3269
2965
  selection: aiPreviewSelectionSchema.optional(),
3270
2966
  /** 디자인 탭에서 고른 아트보드(2026-10-14) — 모델은 그 아트보드를 기준으로 고친다 */
3271
2967
  designSelection: aiDesignSelectionSchema.optional()
3272
- }).refine((body) => body.text.length > 0 || body.attachments.length > 0, { message: "내용이나 첨부가 있어야 합니다" });
2968
+ }).refine((body) => body.text.length > 0 || body.attachments.length > 0, { message: "내용이나 첨부가 있어야 합니다" }));
3273
2969
  const sendAiMessageResponseSchema = aiStreamAccessSchema.extend({ messageId: z.string() });
3274
2970
  /**
3275
2971
  * AI가 바꾸는 화면 영역 — 쓰기 도구가 시작되면 이벤트에 싣고, 패널이 그 화면으로 옮겨 반영된 데이터를 다시 읽는다(셀러가 AI가 하는 일을 같이 본다).
@@ -3374,7 +3070,7 @@ const aiStreamEventSchema = z.discriminatedUnion("type", [
3374
3070
  z.object({
3375
3071
  type: z.literal("todos"),
3376
3072
  messageId: z.string(),
3377
- todos: z.array(aiTodoSchema).max(30)
3073
+ todos: z.array(aiTodoSchema)
3378
3074
  }),
3379
3075
  z.object({
3380
3076
  type: z.literal("tool_start"),
@@ -3398,7 +3094,9 @@ const aiStreamEventSchema = z.discriminatedUnion("type", [
3398
3094
  "error",
3399
3095
  "unknown"
3400
3096
  ]),
3401
- summary: z.string().nullable()
3097
+ summary: z.string().nullable(),
3098
+ /** 결과로 확정한 변경(바뀐 줄 범위 포함) — 있으면 `tool_start`의 `changes`를 바꾼다 */
3099
+ changes: z.array(aiToolChangeSchema).max(10).optional()
3402
3100
  }),
3403
3101
  z.object({
3404
3102
  type: z.literal("choices"),
@@ -3452,13 +3150,13 @@ const STORE_DRAFT_MAX_ATTACHMENTS = 5;
3452
3150
  const STORE_DRAFT_ATTACHMENT_MAX_BYTES = 10485760;
3453
3151
  /** 연결하지 않은 초안을 지우기까지 */
3454
3152
  const STORE_DRAFT_RETENTION_DAYS = 7;
3455
- const createStoreDraftRequestSchema = z.object({
3153
+ const createStoreDraftRequestSchema = strictRequest(z.object({
3456
3154
  text: z.string().trim().min(1).max(AI_MESSAGE_MAX_CHARS),
3457
3155
  attachments: z.array(z.object({
3458
3156
  filename: z.string().trim().min(1).max(200),
3459
3157
  size: z.number().int().positive().max(STORE_DRAFT_ATTACHMENT_MAX_BYTES)
3460
3158
  })).max(5).default([])
3461
- });
3159
+ }));
3462
3160
  const createStoreDraftResponseSchema = z.object({
3463
3161
  draftId: z.string(),
3464
3162
  /** 첨부마다 브라우저가 파일을 그대로 PUT할 자리(요청 순서와 같다) */
@@ -3489,6 +3187,14 @@ const storeDraftPreviewSchema = z.object({
3489
3187
  /** 이미 상점에서 쓴 초안이면 true(다시 시작할 수 없다) */
3490
3188
  used: z.boolean()
3491
3189
  });
3190
+ /**
3191
+ * 셀러 메시지가 선택지에서 고른 답인가(조각에 `choice`가 있다) — 할 일 목록은 셀러 요청 하나(사이클)의 일이고, 고른 답(선택지·만들기 확인·계획 승인·발행 확인·
3192
+ * 「이어서 진행」)은 같은 사이클을 잇고 새로 쓴 글은 새 사이클이다(2026-10-24). api(`currentCycleRows`)와 상점 플랫폼(로드맵)이 이 판정 하나를 쓴다.
3193
+ * 직전 답에 선택지가 있었는지로 가르면 선택지를 무시하고 새 요청을 쓴 경우도 옛 사이클에 묶였다
3194
+ */
3195
+ function isAiChoiceAnswer(parts) {
3196
+ return parts.some((part) => part.type === "text" && Boolean(part.choice));
3197
+ }
3492
3198
  //#endregion
3493
3199
  //#region src/schemas/analytics.ts
3494
3200
  /**
@@ -4135,7 +3841,7 @@ const claimHoldResultSchema = z.object({
4135
3841
  claimId: z.string(),
4136
3842
  holdExpiresAt: z.string()
4137
3843
  });
4138
- const rejectClaimRequestSchema = z.object({
3844
+ const rejectClaimRequestSchema = strictRequest(z.object({
4139
3845
  reason: z.enum([
4140
3846
  "USED_PRODUCT",
4141
3847
  "MISSING_COMPONENT",
@@ -4145,7 +3851,7 @@ const rejectClaimRequestSchema = z.object({
4145
3851
  ]),
4146
3852
  detail: z.string().min(10).max(1e3),
4147
3853
  evidenceImages: z.array(z.url()).max(5).optional()
4148
- });
3854
+ }));
4149
3855
  const approveClaimResultSchema = z.object({
4150
3856
  claimId: z.string(),
4151
3857
  refundAmount: z.number().int().describe("실제 환불한 금액 — 수량 비율 상품 실결제 금액(쿠폰 배분을 뺀 금액) + 배송비 환불 − 반품 배송비 − 조건부 무료배송 미달 차감 − 쿠폰 조건 미달 차감(`couponChargeAmount`) + 되돌린 쿠폰 차감(`couponChargeRefundAmount`) − 추가 차감(`deductAmount`)"),
@@ -4328,12 +4034,12 @@ const storePointPolicySchema = z.object({
4328
4034
  * `PUT /v1/store/point-policy` 본문 — 준 항목만 바꾼다(생략 = 저장된 값 유지). 리뷰 적립·구매 적립 중 하나라도 켜면 유효 기간이 있어야 한다
4329
4035
  * (본문이나 저장된 값, 없으면 400 `POINT_EXPIRY_REQUIRED`).
4330
4036
  */
4331
- const updatePointPolicyRequestSchema = z.object({
4037
+ const updatePointPolicyRequestSchema = strictRequest(z.object({
4332
4038
  reviewReward: reviewRewardPolicySchema.optional(),
4333
4039
  purchaseEarn: purchaseEarnPolicySchema.optional(),
4334
4040
  use: pointUsePolicySchema.optional(),
4335
4041
  expiryDays: expiryDays.optional()
4336
- });
4042
+ }));
4337
4043
  /** 응답의 원장 유형 — 값이 추가될 수 있어 문자열로 받는다 */
4338
4044
  const responsePointEntryTypeSchema = z.union([z.enum(POINT_ENTRY_TYPES), z.string()]).describe("유형. `EARN_REVIEW` 리뷰 적립 · `REVOKE_REVIEW` 리뷰 삭제 회수 · `EARN_PURCHASE` 구매 적립 · `EXPIRE` 소멸 · `ADJUST` 셀러 지급·차감 · `OPENING` 기존 잔액 이전 · `USE_RESERVE` 결제 사용(결제 시작 때 빠짐) · `USE_RELEASE` 결제가 실패·만료되어 되돌림 · `REFUND_RESTORE` 취소·반품 환불로 반환. 값이 추가될 수 있어 문자열로 받는다");
4339
4045
  /** 원장 항목 — 셀러 조회용(사유·행위자 포함) */
@@ -4380,14 +4086,14 @@ const POINT_ADJUSTMENT_MAX = 1e7;
4380
4086
  * 지급의 소멸 시각은 `expiresAt`(생략하면 정책 유효 기간, 정책이 없으면 400 `POINT_EXPIRY_REQUIRED`), 차감은 소멸이 이른 적립금부터 뺀다
4381
4087
  * (잔액보다 많으면 409 `POINT_BALANCE_INSUFFICIENT`).
4382
4088
  */
4383
- const pointAdjustmentRequestSchema = z.object({
4089
+ const pointAdjustmentRequestSchema = strictRequest(z.object({
4384
4090
  amount: z.number().int().min(-1e7).max(POINT_ADJUSTMENT_MAX).refine((value) => value !== 0, "0원은 조정할 수 없습니다").describe("지급은 양수, 차감은 음수(원)"),
4385
4091
  reason: z.string().trim().min(1).max(200).describe("사유(필수). 구매자에게는 보이지 않는다"),
4386
4092
  expiresAt: z.iso.datetime({ offset: true }).optional().describe("지급분의 소멸 시각. 생략하면 정책 유효 기간(`expiryDays`)으로 정한다. **정책 유효 기간이 없으면 지급에 필수다**(없으면 400 `POINT_EXPIRY_REQUIRED`). 차감에는 주지 않는다")
4387
4093
  }).refine((value) => !(value.amount < 0 && value.expiresAt), {
4388
4094
  message: "차감에는 소멸 시각을 줄 수 없습니다",
4389
4095
  path: ["expiresAt"]
4390
- });
4096
+ }));
4391
4097
  const pointAdjustmentResultSchema = z.object({
4392
4098
  entry: pointEntrySchema,
4393
4099
  balance: z.number().int().describe("조정 뒤 잔액")
@@ -4478,7 +4184,7 @@ const productNoticeSchema = z.object({
4478
4184
  values: z.record(z.string(), z.string()).describe("칸 키 → 셀러가 적은 값. 비운 칸은 없다")
4479
4185
  });
4480
4186
  const MAX_NOTICE_VALUE_LENGTH = 1500;
4481
- const productNoticeRequestSchema = z.object({
4187
+ const productNoticeRequestSchema = z.strictObject({
4482
4188
  schemaId: z.string().trim().min(1).max(50).describe("품목군 코드(`GET /v1/info-schemas`)"),
4483
4189
  version: z.number().int().positive().optional().describe("품목군 버전. 생략하면 현재 버전"),
4484
4190
  values: z.record(z.string().max(50), z.string().max(MAX_NOTICE_VALUE_LENGTH)).default({}).describe("칸 키 → 값. 출처가 `legal`인 칸은 받지 않는다(400). 빈 문자열은 비운 칸으로 저장하지 않는다. 칸 길이는 스키마 `maxLength`")
@@ -4502,13 +4208,13 @@ const productCertificationsSchema = z.object({
4502
4208
  number: z.string().describe("인증 번호")
4503
4209
  })).describe("인증서. 배열 순서가 표시 순서다")
4504
4210
  });
4505
- const productCertificationsRequestSchema = z.object({
4506
- subjects: z.array(z.object({
4211
+ const productCertificationsRequestSchema = z.strictObject({
4212
+ subjects: z.array(z.strictObject({
4507
4213
  subject: z.string().trim().min(1).max(50),
4508
4214
  status: z.enum(CERTIFICATION_STATUSES),
4509
4215
  exemption: z.string().trim().min(1).max(50).nullish()
4510
4216
  })).max(20).default([]).describe("인증 대상 여부. `REQUIRED`인데 그 대상의 인증 종류(`attrs.kinds`) 인증서가 `items`에 없으면 400 `CERTIFICATION_REQUIRED`, `EXEMPT`인데 사유가 없거나 대상이 허용하지 않는 사유면 400 `CERTIFICATION_EXEMPTION_INVALID`"),
4511
- items: z.array(z.object({
4217
+ items: z.array(z.strictObject({
4512
4218
  kind: z.string().trim().min(1).max(50),
4513
4219
  agency: z.string().trim().max(100).nullish(),
4514
4220
  number: z.string().trim().min(1).max(100)
@@ -4530,11 +4236,11 @@ const infoSectionSchema = z.object({
4530
4236
  createdAt: z.string(),
4531
4237
  updatedAt: z.string()
4532
4238
  });
4533
- const infoSectionRequestSchema = z.object({
4239
+ const infoSectionRequestSchema = strictRequest(z.object({
4534
4240
  title: z.string().trim().min(1).max(100),
4535
4241
  body: z.string().default(""),
4536
4242
  bodyJson: z.string().nullable().optional()
4537
- });
4243
+ }));
4538
4244
  /**
4539
4245
  * 안내 섹션 번역 (이슈 #134) — 언어 하나의 제목·본문. 섹션 필드는 상점 기본 언어 값이다. 비운 칸(null)은 스토어프론트가 기본 언어 값으로 대체한다.
4540
4246
  * 섹션을 연결한 모든 상품이 같은 번역을 보인다.
@@ -4607,14 +4313,14 @@ const calendarQuerySchema = z.object({
4607
4313
  * 달력 설정 — 기간의 날짜마다 재고·가격을 덮어쓴다(없는 날은 만든다). `stock`·`price`는 준 것만 바꾸고, `price: null`은 조합 가격으로
4608
4314
  * 되돌린다. `daysOfWeek`(0=일~6=토)를 주면 그 요일만 바꾼다
4609
4315
  */
4610
- const setCalendarRequestSchema = z.object({
4316
+ const setCalendarRequestSchema = strictRequest(z.object({
4611
4317
  variantIds: z.array(z.string()).min(1).max(50),
4612
4318
  from: calendarDateSchema,
4613
4319
  to: calendarDateSchema,
4614
4320
  stock: z.number().int().min(0).max(1e5).optional(),
4615
4321
  price: z.number().int().min(0).multipleOf(10).nullable().optional(),
4616
4322
  daysOfWeek: z.array(z.number().int().min(0).max(6)).min(1).max(7).optional()
4617
- }).refine((value) => value.stock !== void 0 || value.price !== void 0, { message: "stock이나 price 중 하나는 있어야 합니다" });
4323
+ }).refine((value) => value.stock !== void 0 || value.price !== void 0, { message: "stock이나 price 중 하나는 있어야 합니다" }));
4618
4324
  //#endregion
4619
4325
  //#region src/schemas/upload.ts
4620
4326
  /**
@@ -4720,11 +4426,11 @@ function uploadRejection(purpose, filename, size) {
4720
4426
  * 끝나면 `url`이 공개 주소가 된다. 서버가 객체 키를 정하므로 요청은 파일명만 보낸다
4721
4427
  * (확장자만 쓰이고 이름 자체는 저장되지 않는다).
4722
4428
  */
4723
- const uploadRequestSchema = z.object({
4429
+ const uploadRequestSchema = strictRequest(z.object({
4724
4430
  filename: z.string().min(1).max(255),
4725
4431
  purpose: uploadPurposeSchema.default("description").describe("업로드 용도. 허용 확장자와 크기 상한이 용도별로 다르다"),
4726
4432
  size: z.number().int().positive().optional().describe("파일 바이트 크기. 주면 용도별 상한을 발급 전에 검사한다")
4727
- });
4433
+ }));
4728
4434
  const uploadTicketSchema = z.object({
4729
4435
  /** 업로드 완료 후 공개될 주소 */
4730
4436
  url: z.url(),
@@ -4905,7 +4611,7 @@ function customInputLabelForbiddenWord(label) {
4905
4611
  }
4906
4612
  /** 옵션명·값 이름 — 앞뒤 공백을 지우고 빈 값은 받지 않는다 */
4907
4613
  const optionNameSchema = z.string().trim().min(1).max(50);
4908
- const addonValueRequestSchema = z.object({
4614
+ const addonValueRequestSchema = z.strictObject({
4909
4615
  /** 전달 시 기존 값 행을 유지(UPDATE). 생략하면 신규 발급 */
4910
4616
  valueId: z.string().optional(),
4911
4617
  name: optionNameSchema,
@@ -4913,14 +4619,14 @@ const addonValueRequestSchema = z.object({
4913
4619
  prices: additionalCurrencyPricesSchema.optional(),
4914
4620
  usable: z.boolean().default(true)
4915
4621
  });
4916
- const addonGroupRequestSchema = z.object({
4622
+ const addonGroupRequestSchema = z.strictObject({
4917
4623
  /** 전달 시 기존 옵션명 행을 유지(UPDATE). 조합 옵션명의 id는 줄 수 없다(방식을 바꾸려면 새 옵션명으로 보낸다) */
4918
4624
  groupId: z.string().optional(),
4919
4625
  name: optionNameSchema,
4920
4626
  required: z.boolean().default(false),
4921
4627
  values: z.array(addonValueRequestSchema).min(1).max(100)
4922
4628
  });
4923
- const customInputRequestSchema = z.object({
4629
+ const customInputRequestSchema = z.strictObject({
4924
4630
  /** 전달 시 기존 항목 행을 유지(UPDATE). 생략하면 신규 발급 */
4925
4631
  inputId: z.string().optional(),
4926
4632
  label: z.string().trim().min(1).max(30),
@@ -5048,18 +4754,18 @@ function productImageRejection(url) {
5048
4754
  * (`WHERE ... is not null`)의 판정이 갈려 409 대신 500이 나간다.
5049
4755
  */
5050
4756
  const codeSchema = z.string().trim().min(1).max(64);
5051
- const optionValueRequestSchema = z.object({
4757
+ const optionValueRequestSchema = z.strictObject({
5052
4758
  /** 전달 시 기존 값 행을 유지(UPDATE). 생략하면 신규 발급 */
5053
4759
  valueId: z.string().optional(),
5054
4760
  name: z.string().min(1).max(50)
5055
4761
  });
5056
- const optionGroupRequestSchema = z.object({
4762
+ const optionGroupRequestSchema = z.strictObject({
5057
4763
  /** 전달 시 기존 축 행을 유지(UPDATE). 생략하면 신규 발급 */
5058
4764
  groupId: z.string().optional(),
5059
4765
  name: z.string().min(1).max(50),
5060
4766
  values: z.array(optionValueRequestSchema).min(1).max(100)
5061
4767
  });
5062
- const productVariantRequestSchema = z.object({
4768
+ const productVariantRequestSchema = z.strictObject({
5063
4769
  /** 기존 variant 유지 시 전달. 생략하면 신규 생성 */
5064
4770
  variantId: z.string().optional(),
5065
4771
  /** optionGroups 순서대로 각 축에서 고른 값 이름. 서버가 이름 → valueId를 해석한다 */
@@ -5081,7 +4787,7 @@ const productVariantRequestSchema = z.object({
5081
4787
  attributes: z.record(z.string().regex(/^[a-z][a-zA-Z0-9_]{0,39}$/), z.string().max(100)).refine((value) => Object.keys(value).length <= 10, { message: "조합 속성은 10개까지입니다" }).optional().describe("조합 속성(이슈 #115) — 키 → 값 문자열(예: 회차 일시 `showAt`). 플로우가 `item.option.<키>`로 읽고 타입(날짜·숫자 등)은 플로우가 선언한다. 생략하면 지금 값 유지(새 조합은 없음), `{}`면 비운다")
5082
4788
  });
5083
4789
  /** 축 × 값 → variant 전체 교체 요청 (PUT /products/{productId}/options) */
5084
- const optionModelRequestSchema = z.object({
4790
+ const optionModelRequestSchema = z.strictObject({
5085
4791
  optionGroups: z.array(optionGroupRequestSchema).max(3).default([]),
5086
4792
  variants: z.array(productVariantRequestSchema).min(1).max(500),
5087
4793
  addonGroups: z.array(addonGroupRequestSchema).max(5).optional().describe("추가 선택 옵션명 전체(이슈 #59). 주면 통째로 바꾸고, 생략하면 등록은 없음·수정은 현재 값을 그대로 둔다. 끄려면 빈 배열을 보낸다"),
@@ -5141,7 +4847,7 @@ const productWriteShape = {
5141
4847
  */
5142
4848
  descriptionJson: z.string().nullable().optional(),
5143
4849
  images: productImagesRequestSchema.optional().describe("상품 이미지 주소 목록. 첫 장이 대표 이미지(썸네일)다"),
5144
- attributes: z.array(z.object({
4850
+ attributes: z.array(z.strictObject({
5145
4851
  attributeId: z.string(),
5146
4852
  value: z.string()
5147
4853
  })).optional(),
@@ -5192,12 +4898,12 @@ const productListQuerySchema = z.object({
5192
4898
  sort: productSortSchema.optional().describe("정렬 (기본 createdAt.desc)"),
5193
4899
  ...pageQueryShape()
5194
4900
  });
5195
- const discountRequestSchema = z.object({
4901
+ const discountRequestSchema = strictRequest(z.object({
5196
4902
  discountType: z.enum(["RATE", "AMOUNT"]),
5197
4903
  discountValue: z.number().int().min(1),
5198
4904
  startAt: z.string().optional(),
5199
4905
  endAt: z.string().optional()
5200
- });
4906
+ }));
5201
4907
  //#endregion
5202
4908
  //#region src/schemas/webhook-event.ts
5203
4909
  const envelopeFields = {
@@ -6190,7 +5896,7 @@ const webhookDeliveryListQuerySchema = z.object({
6190
5896
  });
6191
5897
  /** 실패 건 일괄 재전송 응답 — `POST /webhooks/{id}/deliveries/redeliver-failed` */
6192
5898
  const webhookRedeliverFailedResultSchema = z.object({ queued: z.number().int().min(0).describe("재전송 대기열에 올린 건수. 최근 72시간의 `FAILED` 중 아직 재전송되지 않은 건이 대상이며 최대 500건이다") });
6193
- const webhookTestRequestSchema = z.object({ eventType: eventTypeSchema.describe("샘플 페이로드로 보낼 이벤트 타입") });
5899
+ const webhookTestRequestSchema = strictRequest(z.object({ eventType: eventTypeSchema.describe("샘플 페이로드로 보낼 이벤트 타입") }));
6194
5900
  /** 테스트 이벤트 발송 결과 (동기 반환). 재시도·정지 판정·전송 기록이 없다 */
6195
5901
  const webhookTestResultSchema = z.object({
6196
5902
  responseStatusCode: z.number().int().nullable().describe("수신 서버의 HTTP 응답 코드. 연결 실패·타임아웃·차단이면 null"),
@@ -6406,10 +6112,10 @@ const appInstallationActivitySchema = z.object({
6406
6112
  * - `{ result }`: accounts 설치 동의 결과(1회용 JWT). 개발자 포털 [내 상점에 설치]가 이 길로 온다
6407
6113
  * - `{ appId, settings }`: 상점 플랫폼 앱 목록 › 설치 화면에서 동의하고 설정까지 채워 바로 설치한다
6408
6114
  */
6409
- const appInstallRequestSchema = z.union([z.object({ result: z.string().min(1).describe("accounts가 발급한 설치 결과 JWT(`typ: sayren-install+jwt`)") }), z.object({
6115
+ const appInstallRequestSchema = strictRequest(z.union([z.object({ result: z.string().min(1).describe("accounts가 발급한 설치 결과 JWT(`typ: sayren-install+jwt`)") }), z.object({
6410
6116
  appId: z.string().min(1),
6411
6117
  settings: z.record(z.string(), settingsValueSchema).default({}).describe("설치와 함께 저장할 설정. 비밀 필드도 여기서 넣는다")
6412
- })]);
6118
+ })]));
6413
6119
  /** 앱 목록 정보 — 현재 버전이 올린 아이콘·README(없으면 매니페스트 `iconUrl`) */
6414
6120
  const appListingSchema = z.object({
6415
6121
  description: z.string().nullable(),
@@ -6773,7 +6479,7 @@ const categoryAttributeSchema = z.object({
6773
6479
  unit: z.string().nullable(),
6774
6480
  allowedValues: z.array(z.string()).optional()
6775
6481
  });
6776
- const categoryCreateRequestSchema = z.object({
6482
+ const categoryCreateRequestSchema = strictRequest(z.object({
6777
6483
  name: z.string().min(1).max(100),
6778
6484
  parentId: z.string().nullable().optional(),
6779
6485
  sortOrder: z.number().int().optional(),
@@ -6784,8 +6490,8 @@ const categoryCreateRequestSchema = z.object({
6784
6490
  metaTitle: z.string().max(100).nullable().optional(),
6785
6491
  metaDescription: z.string().max(300).nullable().optional(),
6786
6492
  metaKeywords: z.string().max(200).nullable().optional()
6787
- });
6788
- const categoryPatchRequestSchema = z.object({
6493
+ }));
6494
+ const categoryPatchRequestSchema = strictRequest(z.object({
6789
6495
  name: z.string().min(1).max(100).optional(),
6790
6496
  parentId: z.string().nullable().optional(),
6791
6497
  sortOrder: z.number().int().optional(),
@@ -6797,7 +6503,7 @@ const categoryPatchRequestSchema = z.object({
6797
6503
  metaDescription: z.string().max(300).nullable().optional(),
6798
6504
  metaKeywords: z.string().max(200).nullable().optional(),
6799
6505
  flowId: z.string().nullable().optional().describe("주문 흐름(이슈 #115) — 게시한 흐름 id, null이면 기본 흐름. 맨 아래 카테고리에만 지정한다(400 `CATEGORY_NOT_LEAF`). 게시하지 않은 흐름은 409 `FLOW_NOT_PUBLISHED`")
6800
- });
6506
+ }));
6801
6507
  const categoryDeleteStrategySchema = z.enum(["reparent", "cascade"]);
6802
6508
  /**
6803
6509
  * `GET /v1/categories` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열). 응답 형태가 쿼리로 갈린다:
@@ -7120,7 +6826,7 @@ const periodRefine = (body, ctx) => {
7120
6826
  * 직접 선택(`MANUAL`)은 `productIds`가 처음 담을 상품과 순서다. 조건 자동(`AUTOMATIC`)은 `rules`가 있어야 하고 `productIds`를 받지 않는다.
7121
6827
  * `productSort`를 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST`(판매량 상위 조건이 있으면 `BEST_SELLING`)다. 조건 자동은 `MANUAL`을 쓸 수 없다.
7122
6828
  */
7123
- const collectionCreateRequestSchema = z.object({
6829
+ const collectionCreateRequestSchema = strictRequest(z.object({
7124
6830
  title: z.string().trim().min(1).max(60).describe("제목"),
7125
6831
  slug: slugField.optional(),
7126
6832
  type: z.enum(COLLECTION_TYPES).default("MANUAL").describe("유형. `MANUAL`(직접 선택)·`AUTOMATIC`(조건 자동). 만든 뒤 바꿀 수 없다"),
@@ -7135,12 +6841,12 @@ const collectionCreateRequestSchema = z.object({
7135
6841
  metaTitle: commonFields.metaTitle.optional(),
7136
6842
  metaDescription: commonFields.metaDescription.optional(),
7137
6843
  productIds: productIdsField.optional()
7138
- }).superRefine(periodRefine);
6844
+ }).superRefine(periodRefine));
7139
6845
  /**
7140
6846
  * `PATCH /v1/collections/{collectionId}` — 준 항목만 바뀐다. `type`을 주면 400 `COLLECTION_TYPE_IMMUTABLE`이다.
7141
6847
  * `revision`을 주면 그 번호일 때만 바뀌고, 그 사이 다른 수정이 있었으면 409 `COLLECTION_CHANGED`다.
7142
6848
  */
7143
- const collectionPatchRequestSchema = z.object({
6849
+ const collectionPatchRequestSchema = strictRequest(z.object({
7144
6850
  title: z.string().trim().min(1).max(60).optional(),
7145
6851
  slug: slugField.optional(),
7146
6852
  type: z.string().optional().describe("바꿀 수 없다. 주면 400 `COLLECTION_TYPE_IMMUTABLE`"),
@@ -7155,14 +6861,14 @@ const collectionPatchRequestSchema = z.object({
7155
6861
  metaTitle: commonFields.metaTitle.optional(),
7156
6862
  metaDescription: commonFields.metaDescription.optional(),
7157
6863
  revision: z.number().int().min(0).optional().describe("읽은 수정 번호")
7158
- }).superRefine(periodRefine);
6864
+ }).superRefine(periodRefine));
7159
6865
  /** `PUT /v1/collections/{collectionId}/products` — 담긴 상품을 통째로 바꾼다(순서 포함) */
7160
- const collectionProductsReplaceRequestSchema = z.object({
6866
+ const collectionProductsReplaceRequestSchema = strictRequest(z.object({
7161
6867
  productIds: productIdsField,
7162
6868
  revision: z.number().int().min(0).optional().describe("읽은 수정 번호")
7163
- });
6869
+ }));
7164
6870
  /** `POST /v1/collections/{collectionId}/products` — 뒤에 붙인다. 이미 담긴 상품은 그 자리에 둔다 */
7165
- const collectionProductsAddRequestSchema = z.object({ productIds: z.array(z.string().min(1)).min(1).max(500) });
6871
+ const collectionProductsAddRequestSchema = strictRequest(z.object({ productIds: z.array(z.string().min(1)).min(1).max(500) }));
7166
6872
  /** 컬렉션에 담긴 상품 한 줄 */
7167
6873
  const collectionProductSchema = z.object({
7168
6874
  productId: z.string(),
@@ -7199,10 +6905,10 @@ const collectionProductListQuerySchema = z.object({ ...pageQueryShape({
7199
6905
  maxSize: MAX_COLLECTION_PRODUCTS
7200
6906
  }) });
7201
6907
  /** `POST /v1/collections/preview` — 저장하지 않고 조건으로 나오는 상품을 본다 */
7202
- const collectionPreviewRequestSchema = z.object({
6908
+ const collectionPreviewRequestSchema = strictRequest(z.object({
7203
6909
  rules: collectionRulesSchema,
7204
6910
  productSort: collectionProductSortRequestSchema.optional().describe("미리보기 순서. 생략하면 `LATEST`(판매량 상위 조건이 있으면 `BEST_SELLING`)이고, `MANUAL`이면 `LATEST`다")
7205
- });
6911
+ }));
7206
6912
  /** 미리보기 응답 — 조건을 만족하는 판매 중 상품 수와 앞 20개 */
7207
6913
  const collectionPreviewSchema = z.object({
7208
6914
  count: z.number().int().describe("조건을 만족하는 판매 중 상품 수(조회 시각 기준)"),
@@ -7333,10 +7039,10 @@ const orderItemFlowSchema = z.object({
7333
7039
  branches: z.array(flowStateSchema).optional().describe("활성 위치가 둘 이상(병렬 가지·하위 흐름)이면 각 위치의 상태. `flowState`는 그 가운데 가장 앞 단계다")
7334
7040
  });
7335
7041
  /** 상태 직접 이동(#115) — 연결선을 지나지 않고 다른 상태로 옮긴다. 블록(재고·환불·송장)은 실행하지 않는다 */
7336
- const moveFlowStateRequestSchema = z.object({
7042
+ const moveFlowStateRequestSchema = strictRequest(z.object({
7337
7043
  to: z.string().min(1).describe("옮길 상태 키(`moveTargets[].key`)"),
7338
7044
  reason: z.string().trim().max(200).optional().describe("옮긴 사유(실행 기록에 남는다)")
7339
- });
7045
+ }));
7340
7046
  const flowRunStepSchema = z.object({
7341
7047
  step: z.number().int(),
7342
7048
  block: z.string().describe("실행한 블록 종류"),
@@ -7432,7 +7138,7 @@ const commerceFlowSchema = commerceFlowSummarySchema.extend({
7432
7138
  }))
7433
7139
  });
7434
7140
  /** 진행 중 주문을 활성 버전으로 옮기기(#115) — 한 번에 `limit`개까지. 남으면 다시 부른다 */
7435
- const migrateFlowVersionRequestSchema = z.object({ limit: z.number().int().min(1).max(500).optional().describe("한 번에 옮길 흐름 수(기본 100)") });
7141
+ const migrateFlowVersionRequestSchema = strictRequest(z.object({ limit: z.number().int().min(1).max(500).optional().describe("한 번에 옮길 흐름 수(기본 100)") }));
7436
7142
  const migrateFlowVersionResultSchema = z.object({
7437
7143
  fromVersion: z.number().int(),
7438
7144
  toVersion: z.number().int(),
@@ -7444,19 +7150,19 @@ const migrateFlowVersionResultSchema = z.object({
7444
7150
  })).describe("이번에 옮기지 못한 흐름(그 버전에 남는다)"),
7445
7151
  remaining: z.number().int().describe("아직 이 버전에 남은 진행 중 흐름 수(건너뛴 것 포함)")
7446
7152
  });
7447
- const createCommerceFlowRequestSchema = z.object({
7153
+ const createCommerceFlowRequestSchema = strictRequest(z.object({
7448
7154
  key: z.string().regex(/^[a-z][a-z0-9-]{1,48}$/).describe("상점 안 유일한 키(소문자·숫자·하이픈)"),
7449
7155
  name: z.string().min(1).max(60).optional(),
7450
7156
  presetKey: z.string().optional().describe("출발한 프리셋(출처로 남는다). 없으면 빈 플로우"),
7451
7157
  graph: flowDocumentSchema.optional().describe("편집기에서 고친 그래프(#115). 없으면 프리셋 그래프 그대로, 프리셋도 없으면 빈 흐름(결제 완료 노드 하나)이다"),
7452
7158
  definition: flowDocumentSchema.optional().describe("흐름 설정 `requires`(progression·groupClaim·fulfillmentMethods). 없으면 프리셋의 설정"),
7453
7159
  variables: z.record(z.string(), z.unknown()).optional().describe("쓰지 않는다(무시). 값은 그래프의 노드 설정 안에 있다(#115)")
7454
- });
7455
- const saveFlowDraftRequestSchema = z.object({
7160
+ }));
7161
+ const saveFlowDraftRequestSchema = strictRequest(z.object({
7456
7162
  graph: flowDocumentSchema,
7457
7163
  definition: flowDocumentSchema.optional().describe("흐름 설정 `requires`(progression·groupClaim·fulfillmentMethods)"),
7458
7164
  variables: z.record(z.string(), z.unknown()).optional().describe("쓰지 않는다(무시). 값은 그래프의 노드 설정 안에 있다(#115)")
7459
- });
7165
+ }));
7460
7166
  const flowIssueSchema = z.object({
7461
7167
  code: z.string(),
7462
7168
  message: z.string(),
@@ -7545,7 +7251,7 @@ const flowDraftOperationSchema = z.discriminatedUnion("op", [
7545
7251
  ])).optional()
7546
7252
  }).describe("흐름 설정(진행 단위·묶음 클레임·이행 방식) 바꾸기")
7547
7253
  ]);
7548
- const applyFlowOperationsRequestSchema = z.object({ operations: z.array(flowDraftOperationSchema).min(1).describe("차례대로 적용한다. 묶음은 원자적이다 — 하나라도 형식이 틀리면 아무것도 바꾸지 않는다(400)") });
7254
+ const applyFlowOperationsRequestSchema = strictRequest(z.object({ operations: z.array(flowDraftOperationSchema).min(1).describe("차례대로 적용한다. 묶음은 원자적이다 — 하나라도 형식이 틀리면 아무것도 바꾸지 않는다(400)") }));
7549
7255
  const flowOperationsResultSchema = z.object({
7550
7256
  revision: z.number().int().describe("저장 뒤 초안 revision — 다음 조작의 If-Match"),
7551
7257
  changed: z.object({
@@ -7576,10 +7282,10 @@ const flowSecretSchema = z.object({
7576
7282
  headerNames: z.array(z.string()).describe("저장한 헤더 이름(값은 보이지 않는다)"),
7577
7283
  updatedAt: z.string()
7578
7284
  });
7579
- const saveFlowSecretRequestSchema = z.object({
7285
+ const saveFlowSecretRequestSchema = strictRequest(z.object({
7580
7286
  url: z.url().refine((value) => value.startsWith("https://"), { message: "https 주소만 받습니다" }).describe("요청 주소. https만, 사설·루프백 주소는 400 `FLOW_SECRET_URL_INVALID`"),
7581
7287
  headers: z.record(z.string().regex(/^[A-Za-z0-9-]{1,64}$/), z.string().max(2e3)).refine((value) => Object.keys(value).length <= 10, { message: "헤더는 10개까지입니다" }).default({}).describe("함께 보낼 헤더(인증 등). 값은 암호화해 두고 다시 보여 주지 않는다")
7582
- });
7288
+ }));
7583
7289
  /**
7584
7290
  * 주문 전체 행동 결과(#115) — 같은 행동을 주문의 주문상품마다 실행한다. 한 주문상품의 실패가 다른 주문상품을 되돌리지 않는다(부분 실행).
7585
7291
  * 묶음 진행이면 한 번 실행이 묶음의 주문상품을 함께 움직인다(COMPLETED로 함께 나온다). 그 행동이 없는 주문상품은 SKIPPED다
@@ -7608,11 +7314,11 @@ const simulationEventSchema = z.object({
7608
7314
  ]).describe("start 결제 승인 · seller.action 셀러 버튼 · buyer.action 구매자 버튼 · event 사건 · timer 타이머 키"),
7609
7315
  key: z.string().optional().describe("행동·사건·타이머 키(start는 없음)")
7610
7316
  });
7611
- const simulateFlowRequestSchema = z.object({
7317
+ const simulateFlowRequestSchema = strictRequest(z.object({
7612
7318
  startAt: z.iso.datetime({ offset: true }).optional().describe("가상 시계 시작(기본: 지금)"),
7613
7319
  context: z.record(z.string(), z.unknown()).optional().describe("식이 읽을 값(item·order·buyer·product). 비우면 견본 주문 값"),
7614
7320
  steps: z.array(z.union([z.object({ event: simulationEventSchema }), z.object({ advance: z.string().regex(/^P/).describe("시간 경과(ISO 8601 기간)") })])).min(1).max(100)
7615
- });
7321
+ }));
7616
7322
  const simulationStepSchema = z.object({
7617
7323
  step: z.number().int(),
7618
7324
  input: z.record(z.string(), z.unknown()).describe("넣은 사건(`event`) 또는 시간 경과(`advance`)"),
@@ -7638,7 +7344,7 @@ const simulateFlowResultSchema = z.object({
7638
7344
  errors: z.array(flowIssueSchema),
7639
7345
  trace: z.array(simulationStepSchema)
7640
7346
  });
7641
- const replayFlowRequestSchema = z.object({ orderItemId: z.string().describe("재생할 주문상품 — 그 흐름의 실행 기록을 초안으로 다시 돌린다") });
7347
+ const replayFlowRequestSchema = strictRequest(z.object({ orderItemId: z.string().describe("재생할 주문상품 — 그 흐름의 실행 기록을 초안으로 다시 돌린다") }));
7642
7348
  const replayFlowResultSchema = z.object({
7643
7349
  orderItemId: z.string(),
7644
7350
  compiled: z.boolean(),
@@ -7786,7 +7492,7 @@ const flowEditSessionViewSchema = z.object({
7786
7492
  streamToken: z.string()
7787
7493
  }).nullable().describe("흐름 채널 구독(SSE, `Authorization: Bearer streamToken`) — session·ops·saved·released 이벤트. 중계가 없는 환경이면 null")
7788
7494
  });
7789
- const claimFlowEditSessionRequestSchema = z.object({ takeover: z.boolean().optional().describe("다른 주체가 잡고 있어도 넘겨받는다. 앞 주체의 저장하지 않은 수정은 사라지고, AI 도우미면 그 실행이 멈춘다") });
7495
+ const claimFlowEditSessionRequestSchema = strictRequest(z.object({ takeover: z.boolean().optional().describe("다른 주체가 잡고 있어도 넘겨받는다. 앞 주체의 저장하지 않은 수정은 사라지고, AI 도우미면 그 실행이 멈춘다") }));
7790
7496
  //#endregion
7791
7497
  //#region src/schemas/promotion.ts
7792
7498
  /**
@@ -8465,7 +8171,7 @@ const couponTargetInputSchema = z.strictObject({
8465
8171
  });
8466
8172
  const couponTimeField = (description) => z.iso.datetime({ offset: true }).nullable().optional().describe(description);
8467
8173
  /** `POST /v1/coupons` */
8468
- const createCouponRequestSchema = z.strictObject({
8174
+ const createCouponRequestSchema = strictRequest(z.strictObject({
8469
8175
  name: z.string().trim().min(1).max(60).describe(descriptions.name),
8470
8176
  description: z.string().max(300).nullable().optional().describe(descriptions.description),
8471
8177
  kind: couponKindSchema,
@@ -8496,12 +8202,12 @@ const createCouponRequestSchema = z.strictObject({
8496
8202
  if (body.issueMethod !== "CODE" && body.perMemberUseLimit != null) issue("perMemberUseLimit", "발급형 쿠폰은 발급 한 장이 한 번 쓰입니다. 1인 발급 수 한도를 사용하십시오");
8497
8203
  if (!(body.conditions?.memberOnly ?? COUPON_CONDITIONS_DEFAULTS.memberOnly) && (body.issueMethod !== "CODE" || body.perMemberUseLimit != null)) issue("conditions", "비회원에게 여는 쿠폰은 코드 입력형이면서 1인 사용 한도가 없어야 합니다");
8498
8204
  if (body.startsAt && body.endsAt && Date.parse(body.endsAt) <= Date.parse(body.startsAt)) issue("endsAt", "종료 시각은 시작 시각보다 뒤여야 합니다");
8499
- });
8205
+ }));
8500
8206
  /**
8501
8207
  * `PATCH /v1/coupons/{couponId}` — 준 항목만 바뀐다. 발급·사용이 시작된 쿠폰(`locked`)은 이름·설명·종료일 연장·
8502
8208
  * 한도 상향만 받고, 그 밖의 항목이 현재 값과 다르면 409 `COUPON_LOCKED`다. 종류·발급 방식은 바꿀 수 없다.
8503
8209
  */
8504
- const updateCouponRequestSchema = z.strictObject({
8210
+ const updateCouponRequestSchema = strictRequest(z.strictObject({
8505
8211
  name: z.string().trim().min(1).max(60).optional().describe(descriptions.name),
8506
8212
  description: z.string().max(300).nullable().optional().describe(descriptions.description),
8507
8213
  benefit: couponBenefitSchema.optional(),
@@ -8515,7 +8221,7 @@ const updateCouponRequestSchema = z.strictObject({
8515
8221
  totalUseLimit: limitField(descriptions.totalUseLimit),
8516
8222
  perMemberIssueLimit: limitField(descriptions.perMemberIssueLimit),
8517
8223
  perMemberUseLimit: limitField(descriptions.perMemberUseLimit)
8518
- });
8224
+ }));
8519
8225
  /** 쿠폰 응답 */
8520
8226
  const couponSchema = z.object({
8521
8227
  couponId: z.string(),
@@ -8783,7 +8489,7 @@ const customerOrderSchema = z.object({
8783
8489
  }))
8784
8490
  });
8785
8491
  /** `POST /v1/customers/{id}/withdraw` 본문 */
8786
- const withdrawCustomerRequestSchema = z.object({
8492
+ const withdrawCustomerRequestSchema = strictRequest(z.object({
8787
8493
  reason: z.enum([
8788
8494
  "BUYER_REQUEST",
8789
8495
  "DORMANT",
@@ -8791,7 +8497,7 @@ const withdrawCustomerRequestSchema = z.object({
8791
8497
  "OTHER"
8792
8498
  ]).describe("처리 사유 — 구매자 요청·장기 미이용·부정 이용·기타. 감사 로그에 남는다"),
8793
8499
  memo: z.string().max(200).optional().describe("사유 보충(선택)")
8794
- });
8500
+ }));
8795
8501
  /** `WITHDRAWAL_BLOCKED`의 `error.details` — 탈퇴를 막는 항목 수(스토어프론트 탈퇴와 같다) */
8796
8502
  const customerWithdrawalBlockedDetailsSchema = z.object({
8797
8503
  inProgressOrderItems: z.number().int(),
@@ -8932,15 +8638,15 @@ const inventoryOperationResultSchema = z.object({
8932
8638
  createdAt: z.string()
8933
8639
  });
8934
8640
  /** 수거 완료의 재입고 지정(Q3) — 생략하면 조합은 할당 순서(교환 → 판매), 위치는 반품지에 연결된 위치 → 할당 위치다 */
8935
- const claimCollectCompleteRequestSchema = z.object({ restock: z.object({
8641
+ const claimCollectCompleteRequestSchema = strictRequest(z.object({ restock: z.object({
8936
8642
  optionId: z.string().min(1).optional().describe("돌아온 조합 — 그 주문상품의 할당 조합이어야 한다(아니면 400 `INVALID_RESTOCK_OPTION`)"),
8937
8643
  inventoryLocationId: z.string().min(1).optional().describe("재입고할 재고 위치")
8938
- }).optional() });
8939
- const claimRedeliveryRequestSchema = z.object({
8644
+ }).optional() }));
8645
+ const claimRedeliveryRequestSchema = strictRequest(z.object({
8940
8646
  carrierCode: z.string().min(1),
8941
8647
  trackingNumber: z.string().min(1),
8942
8648
  inventoryLocationId: z.string().min(1).optional().describe("교환품을 보낼 재고 위치. 생략하면 그 상품의 기준 위치")
8943
- });
8649
+ }));
8944
8650
  //#endregion
8945
8651
  //#region src/schemas/login.ts
8946
8652
  /** 소셜 로그인 공급자 */
@@ -8973,14 +8679,14 @@ const loginSettingsSchema = z.object({
8973
8679
  providers: z.array(loginProviderStatusSchema)
8974
8680
  });
8975
8681
  /** `PATCH /v1/store/login-settings` */
8976
- const updateLoginSettingsRequestSchema = z.object({ passwordLoginEnabled: z.boolean() });
8682
+ const updateLoginSettingsRequestSchema = strictRequest(z.object({ passwordLoginEnabled: z.boolean() }));
8977
8683
  /** `PUT /v1/store/auth-providers/{provider}` — 저장 전에 연결 테스트를 한다 */
8978
- const saveLoginProviderRequestSchema = z.object({
8684
+ const saveLoginProviderRequestSchema = strictRequest(z.object({
8979
8685
  clientId: z.string().trim().min(1).max(200),
8980
8686
  clientSecret: z.string().trim().min(1).max(500)
8981
- });
8687
+ }));
8982
8688
  /** `PATCH /v1/store/auth-providers/{provider}` */
8983
- const updateLoginProviderRequestSchema = z.object({ enabled: z.boolean() });
8689
+ const updateLoginProviderRequestSchema = strictRequest(z.object({ enabled: z.boolean() }));
8984
8690
  /** 연결 테스트 결과 */
8985
8691
  const loginProviderTestSchema = z.object({
8986
8692
  ok: z.boolean(),
@@ -9170,36 +8876,36 @@ const payPalCredentialsInputSchema = z.object({
9170
8876
  clientSecret: secretInput().optional().describe("Secret. 비밀 값. 최초 연결 시 필수, 수정 시 생략하면 기존 값을 유지한다")
9171
8877
  });
9172
8878
  const upsertEnvironment = () => pgEnvironmentSchema.describe("저장할 자격 증명 세트. PG마다 `TEST`(샌드박스)·`LIVE`(실결제) 세트를 따로 둔다. 어느 세트로 결제할지는 이 값이 아니라 샌드박스 스위치(`sandboxMode`)가 정한다");
9173
- const upsertTossPaymentsProviderRequestSchema = z.object({
8879
+ const upsertTossPaymentsProviderRequestSchema = strictRequest(z.object({
9174
8880
  environment: upsertEnvironment(),
9175
8881
  credentials: tossPaymentsCredentialsInputSchema
9176
- });
9177
- const upsertPortOneProviderRequestSchema = z.object({
8882
+ }));
8883
+ const upsertPortOneProviderRequestSchema = strictRequest(z.object({
9178
8884
  environment: upsertEnvironment(),
9179
8885
  credentials: portOneCredentialsInputSchema
9180
- });
9181
- const upsertKakaoPayProviderRequestSchema = z.object({
8886
+ }));
8887
+ const upsertKakaoPayProviderRequestSchema = strictRequest(z.object({
9182
8888
  environment: upsertEnvironment(),
9183
8889
  credentials: kakaoPayCredentialsInputSchema
9184
- });
9185
- const upsertNaverPayProviderRequestSchema = z.object({
8890
+ }));
8891
+ const upsertNaverPayProviderRequestSchema = strictRequest(z.object({
9186
8892
  environment: upsertEnvironment(),
9187
8893
  credentials: naverPayCredentialsInputSchema
9188
- });
9189
- const upsertPayPalProviderRequestSchema = z.object({
8894
+ }));
8895
+ const upsertPayPalProviderRequestSchema = strictRequest(z.object({
9190
8896
  environment: upsertEnvironment(),
9191
8897
  credentials: payPalCredentialsInputSchema
9192
- });
9193
- const updatePaymentProviderRequestSchema = z.object({
8898
+ }));
8899
+ const updatePaymentProviderRequestSchema = strictRequest(z.object({
9194
8900
  enabled: z.boolean().optional().describe("사용 여부. 켜려면 활성 환경(샌드박스면 TEST, 아니면 LIVE) 자격 증명이 모두 저장돼 있어야 한다(`PAYMENT_PROVIDER_INCOMPLETE`)"),
9195
8901
  sandboxMode: z.boolean().optional().describe("샌드박스 스위치. `true`면 새 결제에 TEST 세트를 쓴다(항상 허용). `false`(라이브 전환)는 라이브 개방 조건을 모두 충족해야 한다(`LIVE_GATE_NOT_MET`)"),
9196
8902
  easyPayProviders: z.array(easyPayProviderSchema).max(easyPayProviderSchema.options.length).optional().describe("이 PG로 받는 간편결제사 — 통째로 바꾼다. PG 계약(포트원은 채널)에 추가한 간편결제만 켠다. 켠 간편결제사마다 스토어프론트 결제 옵션이 하나씩 생긴다(포트원은 간편결제를 받는 채널이 있어야 한다)")
9197
- }).refine((body) => body.enabled !== void 0 || body.sandboxMode !== void 0 || body.easyPayProviders !== void 0, { message: "enabled·sandboxMode·easyPayProviders 중 하나는 보내야 합니다" });
9198
- const verifyPaymentProviderRequestSchema = z.object({ environment: pgEnvironmentSchema.optional().describe("연결 테스트할 자격 증명 세트. 생략하면 활성 환경(샌드박스면 TEST, 아니면 LIVE)") });
9199
- const updatePaymentSettingsRequestSchema = z.object({
8903
+ }).refine((body) => body.enabled !== void 0 || body.sandboxMode !== void 0 || body.easyPayProviders !== void 0, { message: "enabled·sandboxMode·easyPayProviders 중 하나는 보내야 합니다" }));
8904
+ const verifyPaymentProviderRequestSchema = strictRequest(z.object({ environment: pgEnvironmentSchema.optional().describe("연결 테스트할 자격 증명 세트. 생략하면 활성 환경(샌드박스면 TEST, 아니면 LIVE)") }));
8905
+ const updatePaymentSettingsRequestSchema = strictRequest(z.object({
9200
8906
  priority: z.array(pgProviderSchema).min(1).max(50).optional().describe("PG 우선순위(앞이 1순위) — 스토어프론트 결제 옵션 목록의 PG 순서다. 연결된 PG 수만큼 **모두 한 번씩** 나열한다(길이 상한 50은 안전장치다). 빠지거나 중복되거나 연결되지 않은 PG가 있으면 `INVALID_PRIORITY`"),
9201
8907
  checkoutOrigins: z.array(z.string().max(200)).max(20).optional().describe("결제 도메인 — 통째로 바꾼다. 결제를 마친 구매자가 돌아올 스토어프론트 origin(`https://shop.example.com`, https·경로 없음). 결제 시작의 `returnUrl`은 이 목록 안이어야 한다. 비어 있으면 실결제를 시작할 수 없다(테스트 결제는 localhost 허용). 같은 도메인을 PG 가맹 정보에도 등록한다. 형식이 틀리면 `INVALID_CHECKOUT_ORIGIN`")
9202
- }).refine((body) => body.priority !== void 0 || body.checkoutOrigins !== void 0, { message: "priority 또는 checkoutOrigins 중 하나는 보내야 합니다" });
8908
+ }).refine((body) => body.priority !== void 0 || body.checkoutOrigins !== void 0, { message: "priority 또는 checkoutOrigins 중 하나는 보내야 합니다" }));
9203
8909
  const maskedSecretSchema = z.object({
9204
8910
  field: z.string().describe("비밀 필드 이름 (`secretKey`·`apiSecret`·`webhookSecret`)"),
9205
8911
  configured: z.boolean().describe("값이 저장돼 있는가"),
@@ -9279,7 +8985,7 @@ const paymentProviderSchema = z.object({
9279
8985
  platformTestKeysAvailable: z.boolean().optional().default(false).describe("이 PG에 sayren 지정 테스트 키가 있어 테스트모드 키를 켤 수 있는가"),
9280
8986
  easyPayProviders: z.array(easyPayProviderResponseSchema).describe("이 PG로 받는 간편결제사. 연결되지 않았으면 빈 목록. 현재 값은 `NAVERPAY`·`KAKAOPAY`·`TOSSPAY`·`PAYCO`이고 값이 추가될 수 있어 문자열로 받는다"),
9281
8987
  retiredCredentialCount: z.number().int().describe("보관된(가맹점 교체·연결 해제로 새 결제에 더 쓰이지 않는) 자격 증명 수. 그 가맹점으로 받은 결제의 환불·대사에 계속 쓰인다"),
9282
- routingExclusion: z.string().nullable().optional().default(null).describe("지금 새 결제의 후보가 아닌 사유. 후보면 null. 판정 원천은 서버 라우팅이다(상점 플랫폼이 다시 계산하지 않는다). 후보가 아닌 PG에는 항상 사유 코드를 붙인다(연결 안 된 PG 포함) — 모든 PG는 `candidates`에 있거나 이 값이 null이 아니다. 현재 값: `NOT_CONNECTED`(연결 안 됨) · `DISABLED`(사용 중지) · `CREDENTIAL_MISSING`(활성 환경 자격 증명 없음) · `SANDBOX_IN_LIVE_STORE`(다른 PG가 라이브라 이 샌드박스 PG는 실구매자 결제에 쓰지 않음) · `PLATFORM_BLOCKED`(플랫폼이 실결제를 막음) · `MODE_MISMATCH`(라이브를 연 서버 모드와 현재 모드가 다름). 값이 추가될 수 있어 문자열로 받는다 — 모르는 값은 후보 아님으로 다룬다. 서버는 항상 싣는다. 이 필드가 없는 이전 서버 응답은 기본값(null)으로 읽는다")
8988
+ routingExclusion: z.string().nullable().optional().default(null).describe("지금 새 결제의 후보가 아닌 사유. 후보면 null. 판정 원천은 서버 라우팅이다(상점 플랫폼이 다시 계산하지 않는다). 후보가 아닌 PG에는 항상 사유 코드를 붙인다(연결 안 된 PG 포함) — 모든 PG는 `candidates`에 있거나 이 값이 null이 아니다. 현재 값: `NOT_CONNECTED`(연결 안 됨) · `DISABLED`(사용 중지) · `CREDENTIAL_MISSING`(활성 환경 자격 증명 없음) · `SANDBOX_IN_LIVE_STORE`(더는 반환하지 않음 — PG는 각자 쓰인다) · `PLATFORM_BLOCKED`(플랫폼이 실결제를 막음) · `MODE_MISMATCH`(라이브를 연 서버 모드와 현재 모드가 다름). 값이 추가될 수 있어 문자열로 받는다 — 모르는 값은 후보 아님으로 다룬다. 서버는 항상 싣는다. 이 필드가 없는 이전 서버 응답은 기본값(null)으로 읽는다")
9283
8989
  });
9284
8990
  /**
9285
8991
  * `PaymentProvider.routingExclusion`의 현재 값 — 응답 스키마는 서버가 사유를 추가해도 파싱이 깨지지 않게 문자열로 받는다.
@@ -9495,7 +9201,7 @@ const paymentListQuerySchema = z.object({
9495
9201
  size: z.string().optional().describe("페이지 크기 (기본 20, 최대 100)")
9496
9202
  });
9497
9203
  /** 테스트모드 키 활성화 요청(2026-10-14) — `PUT /v1/store/payment-providers/{provider}/platform-test-keys` */
9498
- const setPlatformTestKeysRequestSchema = z.object({ enabled: z.boolean().describe("`true`면 sayren 지정 테스트 키를 TEST 세트로 저장하고 PG를 켠다. `false`면 고정만 푼다(TEST 세트는 그대로)") });
9204
+ const setPlatformTestKeysRequestSchema = strictRequest(z.object({ enabled: z.boolean().describe("`true`면 sayren 지정 테스트 키를 TEST 세트로 저장하고 PG를 켠다. `false`면 고정만 푼다(TEST 세트는 그대로)") }));
9499
9205
  /** 결제 상태 PG 한 줄 — 비밀 값·공개 키 없이 연결·사용·환경·테스트모드 키만 */
9500
9206
  const paymentStatusProviderSchema = z.object({
9501
9207
  provider: pgProviderResponseSchema,
@@ -9669,7 +9375,7 @@ const deliveryMethodSchema = z.enum([
9669
9375
  "QUICK",
9670
9376
  "NOTHING"
9671
9377
  ]);
9672
- const dispatchRequestSchema = z.object({
9378
+ const dispatchRequestSchema = strictRequest(z.object({
9673
9379
  deliveryMethod: deliveryMethodSchema,
9674
9380
  carrierCode: z.string().optional(),
9675
9381
  trackingNumber: z.string().optional(),
@@ -9681,7 +9387,7 @@ const dispatchRequestSchema = z.object({
9681
9387
  * 잡 전체를 멈출 수 있어 입력에서 좁혔다. 검증을 통과한 값도 저장 전에 UTC ISO로 정규화한다.
9682
9388
  */
9683
9389
  dispatchedAt: z.iso.datetime({ offset: true }).optional()
9684
- }).refine((value) => value.deliveryMethod === "DIRECT" || value.deliveryMethod === "NOTHING" ? true : !!value.carrierCode && !!value.trackingNumber, { message: "COURIER/QUICK 발송은 carrierCode와 trackingNumber가 필수입니다" });
9390
+ }).refine((value) => value.deliveryMethod === "DIRECT" || value.deliveryMethod === "NOTHING" ? true : !!value.carrierCode && !!value.trackingNumber, { message: "COURIER/QUICK 발송은 carrierCode와 trackingNumber가 필수입니다" }));
9685
9391
  const deliveryInfoSchema = z.object({
9686
9392
  orderItemId: z.string(),
9687
9393
  deliveryMethod: deliveryMethodSchema,
@@ -9728,7 +9434,7 @@ const carrierSchema = z.object({
9728
9434
  name: z.string(),
9729
9435
  trackingUrlTemplate: z.string()
9730
9436
  });
9731
- const holdOrderItemRequestSchema = z.object({
9437
+ const holdOrderItemRequestSchema = strictRequest(z.object({
9732
9438
  reason: z.enum([
9733
9439
  "OUT_OF_STOCK",
9734
9440
  "CUSTOMER_REQUEST",
@@ -9737,8 +9443,8 @@ const holdOrderItemRequestSchema = z.object({
9737
9443
  ]),
9738
9444
  detail: z.string().max(500).optional(),
9739
9445
  expectedDispatchDate: z.string()
9740
- });
9741
- const cancelBySellerRequestSchema = z.object({
9446
+ }));
9447
+ const cancelBySellerRequestSchema = strictRequest(z.object({
9742
9448
  reason: z.enum([
9743
9449
  "OUT_OF_STOCK",
9744
9450
  "PRICE_ERROR",
@@ -9748,17 +9454,17 @@ const cancelBySellerRequestSchema = z.object({
9748
9454
  detail: z.string().max(500).optional(),
9749
9455
  quantity: z.number().int().min(1).optional().describe("취소할 수량. 생략하면 남은 수량 전체다. 남은 수량보다 크면 400 `INVALID_QUANTITY`. 일부만 취소하면 주문상품은 상태를 유지한 채 `canceledQuantity`가 늘고, 전 수량이 소진되면 `CANCELED`가 된다"),
9750
9456
  holdRefund: z.boolean().optional().describe("true면 주문만 취소하고 결제 환불은 대기로 남긴다(#115). 정산·재고·적립금 반환은 그대로 하고, PG 환불은 결제 상세의 `POST /v1/payments/refunds/{refundId}/process`로 따로 한다. 생략하면 취소와 함께 환불한다")
9751
- });
9457
+ }));
9752
9458
  /**
9753
9459
  * 제공 처리 요청 (이슈 #48) — `POST /v1/order-items/{orderItemId}/fulfill`. 배송 없는 주문상품(`MANUAL`)을
9754
9460
  * 제공 완료(`DELIVERED`)로 바꾼다.
9755
9461
  */
9756
- const fulfillRequestSchema = z.object({ note: z.string().trim().max(1e3).optional().describe("구매자에게 보일 이용 안내(예: 예약 방법, 수령 장소). 주문 상세에 실린다") });
9462
+ const fulfillRequestSchema = strictRequest(z.object({ note: z.string().trim().max(1e3).optional().describe("구매자에게 보일 이용 안내(예: 예약 방법, 수령 장소). 주문 상세에 실린다") }));
9757
9463
  /** 제공 처리 일괄 요청 — `POST /v1/order-items/fulfill` */
9758
- const fulfillBulkRequestSchema = z.object({
9464
+ const fulfillBulkRequestSchema = strictRequest(z.object({
9759
9465
  orderItemIds: z.array(z.string()).min(1).max(100),
9760
9466
  note: fulfillRequestSchema.shape.note
9761
- });
9467
+ }));
9762
9468
  /** `POST /v1/order-items/{orderItemId}/cancel` 응답 — 셀러 직권취소 환불 결과 */
9763
9469
  const cancelBySellerResultSchema = z.object({
9764
9470
  orderItemId: z.string(),
@@ -10116,17 +9822,17 @@ const savedOptionSetSchema = z.object({
10116
9822
  createdAt: z.string(),
10117
9823
  updatedAt: z.string()
10118
9824
  });
10119
- const savedOptionValueRequestSchema = z.object({
9825
+ const savedOptionValueRequestSchema = z.strictObject({
10120
9826
  name: nameSchema,
10121
9827
  additionalPrice: z.number().int().min(0).default(0)
10122
9828
  });
10123
- const savedOptionGroupRequestSchema = z.object({
9829
+ const savedOptionGroupRequestSchema = z.strictObject({
10124
9830
  name: nameSchema,
10125
9831
  kind: optionGroupKindSchema,
10126
9832
  required: z.boolean().default(false).describe("추가 선택만 쓴다. 조합 옵션명에 true를 주면 400이다"),
10127
9833
  values: z.array(savedOptionValueRequestSchema).min(1).max(100)
10128
9834
  });
10129
- const savedCustomInputRequestSchema = z.object({
9835
+ const savedCustomInputRequestSchema = z.strictObject({
10130
9836
  label: z.string().trim().min(1).max(30),
10131
9837
  placeholder: z.string().trim().max(100).nullish(),
10132
9838
  maxLength: z.number().int().min(1).max(200),
@@ -10140,7 +9846,7 @@ const savedCustomInputRequestSchema = z.object({
10140
9846
  * 저장 옵션 만들기·수정 본문. 조합 옵션명은 최대 `MAX_OPTION_GROUPS`개, 추가 선택은 최대 `MAX_ADDON_GROUPS`개이고
10141
9847
  * 옵션명과 직접 입력 항목이 모두 비면 400이다. 수정(PUT)은 통째로 바꾼다.
10142
9848
  */
10143
- const savedOptionSetRequestSchema = z.object({
9849
+ const savedOptionSetRequestSchema = z.strictObject({
10144
9850
  name: z.string().trim().min(1).max(50),
10145
9851
  optionSort: optionSortSchema.default("REGISTERED"),
10146
9852
  groups: z.array(savedOptionGroupRequestSchema).max(8).default([]),
@@ -10152,7 +9858,7 @@ const savedOptionSetRequestSchema = z.object({
10152
9858
  * 조합 추가금이 값별 추가금의 합으로 되돌려지면 값별로 저장하고, 조합마다 제각각이면 추가금을 빼고
10153
9859
  * 응답 `additionalPriceDropped: true`로 알린다. `replaceOptionSetId`를 주면 그 저장 옵션을 덮어쓴다(이름 중복의 덮어쓰기).
10154
9860
  */
10155
- const savedOptionSetFromProductRequestSchema = z.object({
9861
+ const savedOptionSetFromProductRequestSchema = z.strictObject({
10156
9862
  productId: z.string(),
10157
9863
  name: z.string().trim().min(1).max(50),
10158
9864
  includeOptions: z.boolean().default(true).describe("옵션명(조합·추가 선택)을 저장하는가"),
@@ -10270,14 +9976,14 @@ const brandBriefSchema = z.object({
10270
9976
  notes: z.string().trim().max(4e3).nullable().describe("인터뷰 메모 (타깃 고객, 판매 방식, 셀러가 강조한 요구)")
10271
9977
  });
10272
9978
  /** `PUT /v1/storefront/brand-brief` — 브리프 전체를 바꾼다. 생략한 항목은 비운다 */
10273
- const putBrandBriefRequestSchema = z.object({
9979
+ const putBrandBriefRequestSchema = strictRequest(z.object({
10274
9980
  industry: storeIndustrySchema.nullable().default(null),
10275
9981
  mood: z.string().trim().max(200).nullable().default(null),
10276
9982
  pointColor: z.string().regex(/^#[0-9a-fA-F]{6}$/, "#RRGGBB 형식이어야 합니다").nullable().default(null),
10277
9983
  references: z.array(brandBriefReferenceSchema).max(5).default([]),
10278
9984
  productSource: brandBriefProductSourceSchema.nullable().default(null),
10279
9985
  notes: z.string().trim().max(4e3).nullable().default(null)
10280
- });
9986
+ }));
10281
9987
  /** `GET·PUT /v1/storefront/brand-brief` 응답 — 저장한 적이 없으면 `brief`·`updatedAt`이 null이다 */
10282
9988
  const brandBriefViewSchema = z.object({
10283
9989
  brief: brandBriefSchema.nullable(),
@@ -10348,7 +10054,7 @@ const starterStatusSchema = z.object({
10348
10054
  //#endregion
10349
10055
  //#region src/client.ts
10350
10056
  function createStoreClient(options) {
10351
- const fetchFn = options.fetch ?? globalThis.fetch;
10057
+ const fetchFn = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
10352
10058
  const { session } = options;
10353
10059
  const tokenSource = options.accessToken ?? (session ? () => session.getToken() : void 0);
10354
10060
  const refresh = options.refresh ?? (session ? () => session.refresh() : void 0);
@@ -10359,7 +10065,7 @@ function createStoreClient(options) {
10359
10065
  }
10360
10066
  /** 계정 API(`/me/*`) — 상점을 고르지 않는다 */
10361
10067
  const userHttp = createHttp({
10362
- baseUrl: options.baseUrl,
10068
+ baseUrl: options.baseUrl ?? "https://api.sayren.io/v1",
10363
10069
  fetch: fetchFn,
10364
10070
  headers: bearer,
10365
10071
  refresh,
@@ -10367,7 +10073,7 @@ function createStoreClient(options) {
10367
10073
  });
10368
10074
  /** 상점 API — 같은 계정 토큰 + `X-Store-Id` */
10369
10075
  const storeHttp = createHttp({
10370
- baseUrl: options.baseUrl,
10076
+ baseUrl: options.baseUrl ?? "https://api.sayren.io/v1",
10371
10077
  fetch: fetchFn,
10372
10078
  headers: () => {
10373
10079
  const storeId = resolveToken(options.storeId);
@@ -11479,7 +11185,7 @@ async function refreshUserToken(options) {
11479
11185
  ...options.resource ? { resource: options.resource } : {}
11480
11186
  }, options.fetch);
11481
11187
  }
11482
- const customerDelegationRequestSchema = z.object({
11188
+ const customerDelegationRequestSchema = strictRequest(z.object({
11483
11189
  uid: z.string().regex(/^[A-Za-z0-9._:@|-]{1,128}$/).optional().describe("셀러 자체 인증의 사용자 id(1~128자, 영문·숫자·`._:@|-`). 처음 보는 id면 구매자를 만든다"),
11484
11190
  email: z.email().max(254).optional().describe("uid가 없으면 이메일로 지목한다. uid와 함께 주면 처음 만들 때의 이메일이다"),
11485
11191
  name: z.string().max(50).optional().describe("처음 만들 때의 이름"),
@@ -11487,7 +11193,7 @@ const customerDelegationRequestSchema = z.object({
11487
11193
  }).refine((value) => Boolean(value.uid || value.email), {
11488
11194
  message: "uid 또는 email이 필요합니다",
11489
11195
  path: ["uid"]
11490
- }).describe("구매자 위임 요청");
11196
+ }).describe("구매자 위임 요청"));
11491
11197
  const customerDelegationSchema = z.object({
11492
11198
  accessToken: z.string().describe("구매자 액세스 토큰(스토어프론트 API Bearer)"),
11493
11199
  tokenType: z.literal("Bearer"),
@@ -11549,9 +11255,10 @@ const REVOKE_TIMEOUT_MS = 5e3;
11549
11255
  /** Web Locks 이름 — 탭 간 refresh 회전 직렬화용 */
11550
11256
  const REFRESH_LOCK = STORE_SESSION_KEYS.refresh;
11551
11257
  function createStoreSession(options) {
11552
- const { baseUrl, clientId, storage, authServer } = options;
11258
+ const { clientId, storage, authServer } = options;
11259
+ const baseUrl = options.baseUrl ?? "https://api.sayren.io/v1";
11553
11260
  const { revokeUrl, tokenUrl, resource } = authServer;
11554
- const fetchFn = options.fetch ?? globalThis.fetch;
11261
+ const fetchFn = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
11555
11262
  const listeners = /* @__PURE__ */ new Set();
11556
11263
  function notify() {
11557
11264
  for (const listener of listeners) listener();
@@ -11712,4 +11419,4 @@ function createStoreSession(options) {
11712
11419
  };
11713
11420
  }
11714
11421
  //#endregion
11715
- export { AI_AGENT_NOTES_DIR, AI_AGENT_PHASES, AI_DESIGN_BOARDS_MAX, AI_DESIGN_BOARD_FILE_PATTERN, AI_DESIGN_BOARD_KINDS, AI_DESIGN_CANVAS_PATH, AI_DESIGN_CONFIRM_APPROVE, AI_DESIGN_DIR, AI_DESIGN_VIEWPORTS, AI_MESSAGE_MAX_ATTACHMENTS, AI_MESSAGE_MAX_CHARS, AI_RUN_ACTIVE_STATUSES, AI_RUN_FILE_CHANGES_RETENTION_DAYS, AI_SETUP_CONFIRM_APPROVE, AI_TODOS_MAX, AI_TODO_STATUSES, APPROVAL_ALREADY_DECIDED_CODE, APPROVAL_REQUIRED_CODE, APP_CAPABILITIES, APP_DEPLOY_KEY_PATTERN, APP_DEPLOY_KEY_PREFIX, APP_EVENTS_MAX, APP_EVENT_SCOPES, APP_EVENT_TYPES, APP_FLOW_EVENT_PATTERN, APP_FLOW_ITEMS_MAX, APP_FLOW_NOTIFICATION_PATTERN, APP_HANDLE_PATTERN, APP_HTTP_KEY_PATTERN, APP_ICON_CONTENT_TYPES, APP_ICON_MAX_BYTES, APP_ICON_MIN_PX, APP_LIFECYCLE_EVENT_TYPES, APP_NETWORK_DENIED_SUFFIXES, APP_NETWORK_HOSTS_MAX, APP_PUBLIC_HTTP_MAX, APP_README_MAX_BYTES, APP_RESERVED_HANDLES, APP_SCHEDULES_MAX, APP_SCHEDULE_INTERVALS, APP_SCHEDULE_NAME_PATTERN, APP_SECRETS_MAX, APP_SECRET_NAME_PATTERN, APP_SECRET_PATTERNS, APP_SERVER_BUNDLE_MAX_GZIP_BYTES, APP_SETTINGS_MAX_FIELDS, APP_SETTING_FIELD_TYPES, APP_SETTING_KEY_PATTERN, APP_STORAGE_KEY_PATTERN, APP_STORAGE_MAX_BYTES, APP_STORAGE_MAX_KEYS, APP_TOOL_NAME_PATTERN, APP_UI_MAX_BYTES, APP_UI_MAX_FILES, ApiError, ApprovalPendingError, BASE_CURRENCY, BRAND_BRIEF_MAX_REFERENCES, BUSINESS_INFO_MAX_LENGTH, BUSINESS_NUMBER_PATTERN, CASH_RECEIPT_STATUS_VALUES, CERTIFICATION_STATUSES, COLLECTION_BEST_SELLING_DAYS, COLLECTION_PREVIEW_SIZE, COLLECTION_PRODUCT_SORTS, COLLECTION_SALES_SORT_DEFAULT_DAYS, COLLECTION_SLUG_PATTERN, COLLECTION_TYPES, COUPON_CODE_PATTERN, COUPON_CONDITIONS_DEFAULTS, COUPON_TARGET_ALL, COUPON_TARGET_LIST_MAX, CURRENCIES, CURRENCY_CODES, CUSTOM_INPUT_FORBIDDEN_WORDS, CUSTOM_INPUT_TYPES, DEDICATED_EASY_PAY_PROVIDER, DEFAULT_STORE_LOCALE, FULFILLMENT_METHODS, FULFILLMENT_METHODS_BY_TYPE, FULFILLMENT_METHOD_RULES, FULFILLMENT_RULES, INSTALLABLE_SCOPES, InvalidPriceUnitError, KAKAOPAY_TEST_CID, KNOWN_WEBHOOK_EVENT_TYPES, KRW_MONEY_RULES, MAX_ADDON_GROUPS, MAX_ANALYTICS_ALLOWED_ORIGINS, MAX_AUTO_TRANSITION_DAYS, MAX_CALENDAR_DAYS, MAX_CERTIFICATION_ITEMS, MAX_COLLECTIONS, MAX_COLLECTION_BEST_SELLING_TOP, MAX_COLLECTION_CREATED_WITHIN_DAYS, MAX_COLLECTION_DESCRIPTION, MAX_COLLECTION_PRODUCTS, MAX_COLLECTION_PRODUCTS_PER_ADD, MAX_COLLECTION_RULES, MAX_COLLECTION_RULE_CATEGORIES, MAX_COLLECTION_TITLE, MAX_CUSTOM_INPUTS, MAX_CUSTOM_INPUT_LENGTH, MAX_INFO_SECTION_TITLE, MAX_INVENTORY_OPERATION_LINES, MAX_NOTICE_VALUE_LENGTH, MAX_OPTION_GROUPS, MAX_PICKUP_LOCATIONS, MAX_PRODUCT_IMAGES, MAX_PRODUCT_INFO_SECTIONS, MAX_SAVED_OPTION_SETS, MAX_SAVED_OPTION_SET_NAME, MAX_STAY_NIGHTS, MAX_VALUES_PER_GROUP, MAX_VARIANTS, MCP_TELEMETRY_MAX_RESULTS, MIN_PAYMENT_AMOUNT, NON_INSTALLABLE_SCOPES, NO_COUPON_SETTLEMENT, NO_SHIPPING_BUNDLE_KEY, PAYMENT_ROUTING_EXCLUSION_CODES, PAYPAL_CURRENCIES, PLATFORM_CODE_SETS, POINT_ADJUSTMENT_MAX, POINT_EARN_RATE_BP_MAX, POINT_ENTRY_TYPES, POINT_EXPIRY_DAYS_MAX, POINT_EXPIRY_DAYS_MIN, POINT_LOT_SOURCES, POINT_POLICY_DEFAULTS, POINT_REVIEW_REWARD_MAX, POINT_USE_UNITS, PORTONE_CHANNEL_NAME_MAX_LENGTH, PORTONE_MAX_CHANNELS, PORTONE_MIN_CHANNELS, REFUND_POLICY_DEFAULTS, REFUND_POLICY_DELIVERY_FEE_KEYS, REMOTE_AREA_ZIP_RANGES, RESERVED_STOREFRONT_SLUGS, RESERVED_STORE_CODES, SCOPE_DESCRIPTIONS, SHIPPING_POLICY_DEFAULTS, STARTER_SELLER_TASKS, STARTER_STAGES, STOREFRONT_BLOCKED_PATH_SEGMENTS, STOREFRONT_BUILD_STAGES, STOREFRONT_BUILD_TERMINAL_STATUSES, STOREFRONT_CHECK_TERMINAL_STATUSES, STOREFRONT_CLOSED_SITE_HOLD_DAYS, STOREFRONT_CUSTOM_DOMAIN_LIMIT_DEFAULT, STOREFRONT_DOMAIN_DNS_GRACE_DAYS, STOREFRONT_DOMAIN_DNS_WAIT_DAYS, STOREFRONT_DOMAIN_TXT_LABEL, STOREFRONT_EDIT_ACTIVITY_TIMEOUT_MINUTES, STOREFRONT_EDIT_CAPACITY, STOREFRONT_EDIT_IDLE_MINUTES, STOREFRONT_EDIT_PREVIEW_SUFFIX, STOREFRONT_EDIT_START_STAGES, STOREFRONT_FILE_BATCH_MAX, STOREFRONT_FILE_MAX_BYTES, STOREFRONT_PATH_SEGMENT_PATTERN, STOREFRONT_PLATFORM_DOMAINS, STOREFRONT_PUBLIC_SUFFIXES, STOREFRONT_SEARCH_REGEX_MAX_LENGTH, STOREFRONT_SHOWCASE_SLUG_PREFIX, STOREFRONT_SITE_CREATE_LIMIT, STOREFRONT_SLUG_CHANGE_LIMIT, STOREFRONT_SLUG_CHANGE_WINDOW_DAYS, STOREFRONT_SLUG_HOLD_DAYS, STOREFRONT_SLUG_PATTERN, STOREFRONT_SOURCE_BLOB_BATCH_MAX, STOREFRONT_SOURCE_PART_BYTES, STOREFRONT_WORKSPACE_MAX_BYTES, STOREFRONT_WORKSPACE_MAX_FILES, STORE_CODE_PATTERN, STORE_DRAFT_ATTACHMENT_MAX_BYTES, STORE_DRAFT_MAX_ATTACHMENTS, STORE_DRAFT_RETENTION_DAYS, STORE_ROLE_SCOPES, STORE_SCOPE_RESOURCES, STORE_SESSION_KEYS, STORE_SHOP_TYPES, TEMPLATE_STORE_LOCKED_BUSINESS_FIELDS, TOSS_WIDGET_CLIENT_KEY_PATTERN, TOSS_WIDGET_KEY_MESSAGE, TOSS_WIDGET_SECRET_KEY_PATTERN, UPLOAD_PURPOSE_LIMITS, VARIANT_COUNT_WARNING, VARIANT_STOCK_EXCLUSIVE_MESSAGE, WEBHOOK_DEFAULT_TOLERANCE_SEC, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_EVENT_TYPE_HEADER, WEBHOOK_FAILURE_REASONS, WEBHOOK_HEADERS, WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES, WEBHOOK_RESOURCE_TYPES, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_USER_AGENT, addStorefrontDomainRequestSchema, additionalCurrencyPriceSchema, additionalCurrencyPricesSchema, addonGroupRequestSchema, addonGroupSchema, addonValueRequestSchema, addonValueSchema, addressChangeRequestListSchema, addressTypeSchema, agentPolicyDecisionSchema, aiActivitySchema, aiAgentPhaseSchema, aiAttachmentSchema, aiChoiceOptionSchema, aiConversationFileChangesSchema, aiConversationSchema, aiConversationSummarySchema, aiDesignBoardSchema, aiDesignCanvasSchema, aiDesignConfirmBoardSchema, aiDesignSelectionSchema, aiFileChangeKindSchema, aiFocusAreaSchema, aiFocusSchema, aiMessagePartSchema, aiMessageSchema, aiPreviewSelectionSchema, aiRunChangesSchema, aiRunChangesStatusSchema, aiRunFileDiffSchema, aiRunRevertConflictDetailsSchema, aiRunRevertResultSchema, aiRunSchema, aiRunStatusSchema, aiSetupConfirmItemSchema, aiStreamAccessSchema, aiStreamEventSchema, aiStreamRecordSchema, aiTodoSchema, aiToolChangeSchema, allocateByWeight, analyticsChannelSchema, analyticsCheckoutOutcomeSchema, analyticsCheckoutSchema, analyticsDeviceRowSchema, analyticsDevicesSchema, analyticsFunnelStepSchema, analyticsOriginSchema, analyticsOverviewSchema, analyticsPagesQuerySchema, analyticsPagesSchema, analyticsProductRowSchema, analyticsProductSortSchema, analyticsProductsQuerySchema, analyticsProductsSchema, analyticsRangeQuerySchema, analyticsRealtimeSchema, analyticsSearchQuerySchema, analyticsSearchSchema, analyticsSourceGroupBySchema, analyticsSourceRowSchema, analyticsSourcesQuerySchema, analyticsSourcesSchema, analyticsTotalsSchema, apiLogErrorSchema, apiLogListQuerySchema, apiLogPageSchema, apiLogPrincipalSchema, apiLogPrincipalTypeSchema, apiLogSchema, apiLogStatusFilterSchema, apiLogSummarySchema, appArtifactUploadSchema, appBuildSchema, appBuildStageSchema, appCapabilitiesOf, appDeployKeyCreateSchema, appDeployKeyCreatedSchema, appDeployKeySchema, appDevTokenSchema, appDistributionSchema, appEventTypeSchema, appFlowEventSchema, appFlowEventSummarySchema, appFlowNotificationSchema, appFlowNotificationSummarySchema, appFlowParamSchema, appFlowSummaryOf, appHandleSchema, appHttpKeyMatches, appIconProblem, appInstallRequestSchema, appInstallationActivitySchema, appInstallationAppSchema, appInstallationRunSchema, appInstallationSchema, appInstallationSelfSchema, appInstallationSettingsSchema, appInstallationSettingsUpdateSchema, appInstallationStatusSchema, appInvocationSchema, appListingReviewSchema, appListingReviewStatusSchema, appListingSchema, appManifestProblems, appManifestSchema, appManifestWidens, appNetworkHostProblem, appNetworkHostSchema, appReleaseResultSchema, appRuntimeSchema, appScheduleIntervalLabel, appScheduleListOf, appScheduleSummarySchema, appScopeSchema, appSecretSummarySchema, appSessionSchema, appSettingFieldSchema, appStatusSchema, appStorageEntrySchema, appStorageKeysSchema, appStorageListQuerySchema, appStoragePutSchema, appToolCallSchema, appToolInputSchema, appToolListOf, appToolResultSchema, appToolSchema, appToolSummarySchema, appVersionSchema, appVersionStatusSchema, appVisibilitySchema, applyFlowOperationsRequestSchema, approvalDecisionRequestSchema, approvalListQuerySchema, approvalPageSchema, approvalRequestSchema, approvalStatusSchema, approveClaimResultSchema, assertSaleUnit, auditActorSchema, auditActorTypeSchema, auditLogListQuerySchema, auditLogOutcomeSchema, auditLogPageSchema, auditLogSchema, auditLogSourceSchema, bestSellingRuleOf, brandBriefProductSourceSchema, brandBriefReferenceSchema, brandBriefSchema, brandBriefViewSchema, buildAuthorizeUrl, buildQuery, bulkResultSchema, businessInfoPatchShape, businessInfoResponseShape, businessNumberSchema, calendarDateSchema, calendarDaySchema, calendarQuerySchema, cancelBySellerRequestSchema, cancelBySellerResultSchema, carrierSchema, cashReceiptSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryLocalizationRequestSchema, categoryLocalizationSchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeStorefrontSlugRequestSchema, changeStorefrontTemplateRequestSchema, changeTypeSchema, claimCollectCompleteRequestSchema, claimDetailSchema, claimFlowEditSessionRequestSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimRedeliveryRequestSchema, claimReturnAddressSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, collectionCreateRequestSchema, collectionListQuerySchema, collectionLocalizationRequestSchema, collectionLocalizationSchema, collectionPageSchema, collectionPatchRequestSchema, collectionPreviewRequestSchema, collectionPreviewSchema, collectionProductListQuerySchema, collectionProductSchema, collectionProductSortRequestSchema, collectionProductsAddRequestSchema, collectionProductsReplaceRequestSchema, collectionRuleCategoryIds, collectionRuleSchema, collectionRuleViewSchema, collectionRulesPredicate, collectionRulesSchema, collectionSchema, collectionStateCountsSchema, collectionStateOf, collectionStateSchema, commerceFlowCheckSchema, commerceFlowSchema, commerceFlowSummarySchema, commerceFlowVersionViewSchema, commerceNumberField, compareBySales, connectStorefrontGitRequestSchema, consentActionSchema, consentKindSchema, consentSourceSchema, couponBenefitSchema, couponConditionsInputSchema, couponConditionsSchema, couponDiscountOf, couponIssueListQuerySchema, couponIssueMethodSchema, couponIssueSchema, couponIssueStatusSchema, couponKindSchema, couponListQuerySchema, couponRedemptionListQuerySchema, couponRedemptionSchema, couponRejectReasonSchema, couponRuleSchema, couponSchema, couponStatsSchema, couponStatusSchema, couponTargetInputSchema, couponTargetSchema, createAiConversationRequestSchema, createAiConversationResponseSchema, createCommerceFlowRequestSchema, createCouponRequestSchema, createMarketRequestSchema, createPkcePair, createStoreClient, createStoreDraftRequestSchema, createStoreDraftResponseSchema, createStoreSession, createStorefrontEditPreviewLinkRequestSchema, createStorefrontPreviewLinkRequestSchema, createStorefrontSiteRequestSchema, createStorefrontVersionRequestSchema, currencyCodeSchema, currencyRefundFeesSchema, currencyShippingPolicySchema, currencySpecOf, customInputLabelForbiddenWord, customInputRequestSchema, customInputSchema, customInputValueSchema, customerAddressSchema, customerConsentListQuerySchema, customerConsentSchema, customerConsentStateSchema, customerConsentsSchema, customerCouponSchema, customerDelegationRequestSchema, customerDelegationSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerPointsSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, defaultFulfillmentMethodOf, deleteStorefrontFileRequestSchema, deliveryBundleKeyOf, deliveryFeeWaiverSchema, deliveryInfoSchema, deliveryMethodSchema, deliveryStatusSchema, deliveryTypeSchema, descendantCategoryIdsOf, describeScope, devStoreSchema, developerAppCreateSchema, developerAppSchema, developerInstallationSchema, developerOrgSchema, developerStoreSchema, disableStorefrontHostingRequestSchema, discountRequestSchema, discountSchema, dispatchRequestSchema, easyPayProviderResponseSchema, easyPayProviderSchema, eventTypeSchema, exchangeAuthorizationCode, floorToSaleUnit, flowActionRequestSchema, flowActionResultSchema, flowActionSchema, flowAuthoringGuideSchema, flowDraftEdgesSchema, flowDraftNodeSchema, flowDraftNodesSchema, flowDraftOperationSchema, flowEditSessionViewSchema, flowFieldValueSchema, flowInputFieldSchema, flowIssueSchema, flowNodeIdSchema, flowNodeTypeDetailSchema, flowNodeTypesSchema, flowNotificationWebhookEventDataSchema, flowNotificationWebhookEventSchema, flowOperationsResultSchema, flowPresetDetailSchema, flowPresetSummarySchema, flowRunSchema, flowRunStepSchema, flowSecretNameSchema, flowSecretSchema, flowStateChangedWebhookEventDataSchema, flowStateChangedWebhookEventSchema, flowStateSchema, formatOrderNo, fromDecimalString, fulfillBulkRequestSchema, fulfillRequestSchema, fulfillmentMethodOf, fulfillmentMethodSchema, fulfillmentMethodsOf, fulfillmentRuleOf, fulfillmentTypeOf, fulfillmentTypeResponseSchema, fulfillmentTypeSchema, holdOrderItemRequestSchema, infoFieldSourceSchema, infoSchemaFieldSchema, infoSchemaSchema, infoSectionLocalizationRequestSchema, infoSectionLocalizationSchema, infoSectionRequestSchema, infoSectionSchema, inquiryListQuerySchema, inquirySchema, inquiryWebhookEventDataSchema, inquiryWebhookEventSchema, inventoryAdjustmentLineSchema, inventoryAdjustmentReasonSchema, inventoryAdjustmentRequestSchema, inventoryChangedWebhookEventDataSchema, inventoryChangedWebhookEventSchema, inventoryLevelListQuerySchema, inventoryLevelPageSchema, inventoryLevelSchema, inventoryLocationRequestSchema, inventoryLocationSchema, inventoryModeSchema, inventoryMovementKindSchema, inventoryMovementListQuerySchema, inventoryMovementPageSchema, inventoryMovementSchema, inventoryOperationResultSchema, inventoryTransferRequestSchema, invitationDeliveryStatusSchema, invitationListQuerySchema, invitationSchema, inviteMemberRequestSchema, isAiAgentNotesPath, isAiDesignPath, isCouponTargetLine, isCurrencyCode, isEditableStorefrontPath, isInstallableScope, isReservedStoreCode, isReservedStorefrontSlug, isSaleUnitPrice, isShowcaseStorefrontSlug, isStoreScope, isWebOrigin, issueCouponRequestSchema, issueCouponResultSchema, kakaoPayCredentialsInputSchema, linkStorefrontGitInstallationRequestSchema, liveGateConditionCodeSchema, liveGateConditionSchema, liveGateErrorDetailsSchema, liveGateSchema, localeCodeSchema, loginProviderSchema, loginProviderStatusSchema, loginProviderTestSchema, loginSettingsSchema, marketSchema, maskedSecretSchema, matchesCollectionRules, mcpRuleResultSchema, mcpToolEventSchema, migrateFlowVersionRequestSchema, migrateFlowVersionResultSchema, minPaymentOf, minorToMajor, moneyRulesOf, moveFlowStateRequestSchema, moveStorefrontFileRequestSchema, myAccountSchema, myStoreSchema, naverPayCredentialsInputSchema, nightsOf, normalizeBusinessNumber, normalizeCouponCode, normalizeLocale, normalizeStorefrontHostname, normalizeStorefrontPath, oauthTokenResponseSchema, openFulfillmentUnion, optionGroupKindSchema, optionGroupRequestSchema, optionGroupSchema, optionModelRequestSchema, optionModelSchema, optionSelectionSchema, optionSortSchema, optionValueRequestSchema, optionValueSchema, orderCanceledWebhookEventDataSchema, orderCanceledWebhookEventSchema, orderDiscountSchema, orderFlowActionResultSchema, orderFulfilledWebhookEventDataSchema, orderFulfilledWebhookEventSchema, orderItemFlowSchema, orderItemFulfillmentSchema, orderItemFulfillmentSnapshotResponseSchema, orderItemFulfillmentSnapshotSchema, orderItemListQuerySchema, orderItemMemoResultSchema, orderItemPageSchema, orderItemSchema, orderItemStatusSchema, orderListQuerySchema, orderSchema, orderSummaryPageSchema, orderSummarySchema, orderWebhookEventDataSchema, orderWebhookEventSchema, pageInfoSchema, pageQueryShape, pageSchema, parseOrderNo, parseWebhookEvent, payPalCredentialsInputSchema, paymentAttemptRecordSchema, paymentAttemptStatusSchema, paymentCredentialSetSchema, paymentFailureWarningSchema, paymentListQuerySchema, paymentProviderSchema, paymentProviderVerificationSchema, paymentRecordDetailSchema, paymentRecordPageSchema, paymentRecordSchema, paymentRecordStatusSchema, paymentRefundRecordSchema, paymentSettingsSchema, paymentStatusProviderSchema, paymentStatusSchema, pgEnvironmentSchema, pgPaymentMethodSchema, pgProviderResponseSchema, pgProviderSchema, pgVerificationResultSchema, pickupLocationRequestSchema, pickupLocationSchema, pickupLocationSnapshotSchema, planCodeSchema, planEntitlementsSchema, planErrorDetailsSchema, platformCodeSchema, pointAdjustmentRequestSchema, pointAdjustmentResultSchema, pointEarnOf, pointEarnRateBpSchema, pointEarningEnabled, pointEntrySchema, pointExpiresAtOf, pointHistoryQuerySchema, pointLotSchema, pointPolicyNoticeSchema, pointPolicySchema, pointRestoreExpiresAtOf, pointUseOf, pointUsePolicySchema, policyDocumentUrlSchema, policyVersionSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCertificationsRequestSchema, productCertificationsSchema, productCreateRequestSchema, productCurrencyPriceSchema, productCurrencyPricesSchema, productFulfillmentCreateSchema, productFulfillmentResponseSchema, productFulfillmentSchema, productFulfillmentUpdateSchema, productImageRejection, productImageUrlSchema, productListQuerySchema, productLocalizationNeedsTranslation, productLocalizationRequestSchema, productLocalizationSchema, productNoticeRequestSchema, productNoticeSchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productRefundPolicyOverride, productRefundPolicyPatchSchema, productReplaceRequestSchema, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, proratedPaidRefundBase, proratedPointRefund, proratedRefundBase, publicPlanSchema, publicPlansSchema, publishStorefrontVersionRequestSchema, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, purchaseEarnPolicySchema, purchaseEarnRateOf, putBrandBriefRequestSchema, quoteDelivery, quotePricing, rankBestSelling, refreshUserToken, refundPolicyPatchSchema, refundPolicySchema, rejectClaimRequestSchema, remoteAreaLabelOf, remoteAreaOf, remoteAreaSchema, remoteSurchargeOf, replaceStorefrontSourceRequestSchema, replayFlowRequestSchema, replayFlowResultSchema, requiresCollection, requiresShipping, resolvePointPolicy, resolveRefundPolicy, resolveShippingPolicy, resolvedFlowSchema, responsePlanCodeSchema, responsePointEntryTypeSchema, reviewListQuerySchema, reviewReportResultSchema, reviewRewardPointOf, reviewRewardPolicySchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, rollbackStorefrontRequestSchema, runStorefrontCheckRequestSchema, salesReportCurrencySchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, saveFlowDraftRequestSchema, saveFlowSecretRequestSchema, saveLoginProviderRequestSchema, savedCustomInputRequestSchema, savedCustomInputSchema, savedOptionGroupRequestSchema, savedOptionGroupSchema, savedOptionSetCompositionSchema, savedOptionSetFromProductRequestSchema, savedOptionSetFromProductResultSchema, savedOptionSetListQuerySchema, savedOptionSetLocalizationRequestSchema, savedOptionSetLocalizationSchema, savedOptionSetRequestSchema, savedOptionSetSchema, savedOptionSetSortSchema, savedOptionValueRequestSchema, savedOptionValueSchema, scopeAccessSchema, scopesCoverEvent, searchStorefrontFilesRequestSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCancelPreviewSchema, sellerCustomerInquirySchema, sendAiMessageRequestSchema, sendAiMessageResponseSchema, setCalendarRequestSchema, setPlatformTestKeysRequestSchema, setStorefrontDeployApprovalRequestSchema, setStorefrontVisibilityRequestSchema, settleCouponShortfall, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, shippingCurrencyPriceSchema, shippingCurrencyPricesSchema, shippingPolicyPatchSchema, shippingPolicySchema, simulateFlowRequestSchema, simulateFlowResultSchema, simulationStepSchema, splitRefund, starterSellerTaskSchema, starterStageSchema, starterStatusSchema, starterStoreInfoFieldSchema, stayRangeSchema, staySnapshotSchema, storeAppDetailSchema, storeAppSchema, storeCodeSchema, storeDraftPreviewSchema, storeDraftSchema, storeIndustrySchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storePointPolicySchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeSetupBriefSchema, storeShopTypeSchema, storeSubscriptionSchema, storeTemplateSchema, storedAdditionalCurrencyPriceSchema, storedProductCurrencyPriceSchema, storedShippingCurrencyPriceSchema, storefrontBuildDependenciesSchema, storefrontBuildListQuerySchema, storefrontBuildSchema, storefrontBuildStatusSchema, storefrontCheckSchema, storefrontCheckStatusSchema, storefrontCustomDomainStatusSchema, storefrontCustomHostnameProblem, storefrontDependencyFindingSchema, storefrontDeploymentLogSchema, storefrontDeploymentSchema, storefrontDeploymentStepSchema, storefrontDevLogsSchema, storefrontDnsRecordSchema, storefrontDomainSchema, storefrontDomainTxtNameOf, storefrontEditFailureSchema, storefrontEditPreviewLabelOf, storefrontEditPreviewSchema, storefrontEditSessionSchema, storefrontEditSessionStatusSchema, storefrontEditingSchema, storefrontFileConflictDetailsSchema, storefrontFileContentQuerySchema, storefrontFileContentSchema, storefrontFileDeleteResultSchema, storefrontFileEncodingSchema, storefrontFileEntrySchema, storefrontFileHashSchema, storefrontFileListQuerySchema, storefrontFileListSchema, storefrontFileMoveResultSchema, storefrontFilePathSchema, storefrontFileSearchResultSchema, storefrontFileWriteResultSchema, storefrontGitConnectStateSchema, storefrontGitMergeRequestSchema, storefrontGitMergeSchema, storefrontGitRepositorySchema, storefrontGitStatusSchema, storefrontHostingSchema, storefrontPreviewLinkSchema, storefrontProvisioningSchema, storefrontRuleResultSchema, storefrontRuleSeveritySchema, storefrontSiteDomainSchema, storefrontSiteDomainsSchema, storefrontSiteSchema, storefrontSiteSnapshotSchema, storefrontSiteStatusSchema, storefrontSlugAvailabilityQuerySchema, storefrontSlugAvailabilitySchema, storefrontSlugSchema, storefrontSourceArchivePartSchema, storefrontSourceArchiveQuerySchema, storefrontSourceBlobsResultSchema, storefrontSourceModeSchema, storefrontSourceRefSchema, storefrontSourceReplacedSchema, storefrontSourceSchema, storefrontSuspensionSchema, storefrontTemplateSchema, storefrontVerifyReportSchema, storefrontVersionCreatedSchema, storefrontVersionPreviewLabelOf, storefrontVersionSchema, storefrontVersionStatusSchema, storefrontVisibilitySchema, subscriptionLimitsSchema, subscriptionStatusSchema, subscriptionUsageSchema, toDecimalString, toMinor, tossPaymentsCredentialsInputSchema, trackingStageResponseSchema, trackingUpdateResultSchema, unknownWebhookEventSchema, updateCouponRequestSchema, updateLoginProviderRequestSchema, updateLoginSettingsRequestSchema, updateMarketRequestSchema, updateMemberRoleRequestSchema, updatePaymentProviderRequestSchema, updatePaymentSettingsRequestSchema, updatePointPolicyRequestSchema, updateStoreRequestSchema, updateStoreTemplateRequestSchema, uploadExtensionOf, uploadPurposeSchema, uploadRejection, uploadRequestSchema, uploadStorefrontSourceBlobsRequestSchema, uploadTicketSchema, upsertKakaoPayProviderRequestSchema, upsertNaverPayProviderRequestSchema, upsertPayPalProviderRequestSchema, upsertPortOneProviderRequestSchema, upsertTossPaymentsProviderRequestSchema, variantStockRequestSchema, variantStockSchema, verifyPaymentProviderRequestSchema, webhookCreatedSchema, webhookDeliveryDetailSchema, webhookDeliveryErrorCodeSchema, webhookDeliveryListQuerySchema, webhookDeliveryResourceSchema, webhookDeliverySchema, webhookDeliveryStatusSchema, webhookEventSchema, webhookFailureReasonSchema, webhookRedeliverFailedResultSchema, webhookRequestHeaderSchema, webhookRequestSchema, webhookResourceTypeSchema, webhookSchema, webhookSecretRotatedSchema, webhookStatusSchema, webhookTestRequestSchema, webhookTestResultSchema, withdrawCustomerRequestSchema, writeDryRunResultSchema, writePreviewSchema, writeStorefrontFilesRequestSchema };
11422
+ export { AI_AGENT_NOTES_DIR, AI_AGENT_PHASES, AI_DESIGN_BOARDS_MAX, AI_DESIGN_BOARD_FILE_PATTERN, AI_DESIGN_BOARD_KINDS, AI_DESIGN_CANVAS_PATH, AI_DESIGN_CONFIRM_APPROVE, AI_DESIGN_DIR, AI_DESIGN_GUIDE_PATH, AI_DESIGN_VIEWPORTS, AI_MESSAGE_MAX_ATTACHMENTS, AI_MESSAGE_MAX_CHARS, AI_RUN_ACTIVE_STATUSES, AI_RUN_FILE_CHANGES_RETENTION_DAYS, AI_RUN_RESUME_CHOICE, AI_SETUP_CONFIRM_APPROVE, AI_SITEMAP_PATH, AI_TODOS_MAX, AI_TODO_STATUSES, AI_TOOL_CHANGE_LINE_MAX, AI_TOOL_CHANGE_RANGES_MAX, APPROVAL_ALREADY_DECIDED_CODE, APPROVAL_REQUIRED_CODE, APP_CAPABILITIES, APP_DEPLOY_KEY_PATTERN, APP_DEPLOY_KEY_PREFIX, APP_EVENTS_MAX, APP_EVENT_SCOPES, APP_EVENT_TYPES, APP_FLOW_EVENT_PATTERN, APP_FLOW_ITEMS_MAX, APP_FLOW_NOTIFICATION_PATTERN, APP_HANDLE_PATTERN, APP_HTTP_KEY_PATTERN, APP_ICON_CONTENT_TYPES, APP_ICON_MAX_BYTES, APP_ICON_MIN_PX, APP_LIFECYCLE_EVENT_TYPES, APP_NETWORK_DENIED_SUFFIXES, APP_NETWORK_HOSTS_MAX, APP_PUBLIC_HTTP_MAX, APP_README_MAX_BYTES, APP_RESERVED_HANDLES, APP_SCHEDULES_MAX, APP_SCHEDULE_INTERVALS, APP_SCHEDULE_NAME_PATTERN, APP_SECRETS_MAX, APP_SECRET_NAME_PATTERN, APP_SECRET_PATTERNS, APP_SERVER_BUNDLE_MAX_GZIP_BYTES, APP_SETTINGS_MAX_FIELDS, APP_SETTING_FIELD_TYPES, APP_SETTING_KEY_PATTERN, APP_STORAGE_KEY_PATTERN, APP_STORAGE_MAX_BYTES, APP_STORAGE_MAX_KEYS, APP_TOOL_NAME_PATTERN, APP_UI_MAX_BYTES, APP_UI_MAX_FILES, ApiError, ApprovalPendingError, BASE_CURRENCY, BRAND_BRIEF_MAX_REFERENCES, BUSINESS_INFO_MAX_LENGTH, BUSINESS_NUMBER_PATTERN, CASH_RECEIPT_STATUS_VALUES, CERTIFICATION_STATUSES, COLLECTION_BEST_SELLING_DAYS, COLLECTION_PREVIEW_SIZE, COLLECTION_PRODUCT_SORTS, COLLECTION_SALES_SORT_DEFAULT_DAYS, COLLECTION_SLUG_PATTERN, COLLECTION_TYPES, COUPON_CODE_PATTERN, COUPON_CONDITIONS_DEFAULTS, COUPON_TARGET_ALL, COUPON_TARGET_LIST_MAX, CURRENCIES, CURRENCY_CODES, CUSTOM_INPUT_FORBIDDEN_WORDS, CUSTOM_INPUT_TYPES, DEDICATED_EASY_PAY_PROVIDER, DEFAULT_STORE_LOCALE, FULFILLMENT_METHODS, FULFILLMENT_METHODS_BY_TYPE, FULFILLMENT_METHOD_RULES, FULFILLMENT_RULES, INSTALLABLE_SCOPES, InvalidPriceUnitError, KAKAOPAY_TEST_CID, KNOWN_WEBHOOK_EVENT_TYPES, KRW_MONEY_RULES, MAX_ADDON_GROUPS, MAX_ANALYTICS_ALLOWED_ORIGINS, MAX_AUTO_TRANSITION_DAYS, MAX_CALENDAR_DAYS, MAX_CERTIFICATION_ITEMS, MAX_COLLECTIONS, MAX_COLLECTION_BEST_SELLING_TOP, MAX_COLLECTION_CREATED_WITHIN_DAYS, MAX_COLLECTION_DESCRIPTION, MAX_COLLECTION_PRODUCTS, MAX_COLLECTION_PRODUCTS_PER_ADD, MAX_COLLECTION_RULES, MAX_COLLECTION_RULE_CATEGORIES, MAX_COLLECTION_TITLE, MAX_CUSTOM_INPUTS, MAX_CUSTOM_INPUT_LENGTH, MAX_INFO_SECTION_TITLE, MAX_INVENTORY_OPERATION_LINES, MAX_NOTICE_VALUE_LENGTH, MAX_OPTION_GROUPS, MAX_PICKUP_LOCATIONS, MAX_PRODUCT_IMAGES, MAX_PRODUCT_INFO_SECTIONS, MAX_SAVED_OPTION_SETS, MAX_SAVED_OPTION_SET_NAME, MAX_STAY_NIGHTS, MAX_VALUES_PER_GROUP, MAX_VARIANTS, MCP_TELEMETRY_MAX_RESULTS, MIN_PAYMENT_AMOUNT, NON_INSTALLABLE_SCOPES, NO_COUPON_SETTLEMENT, NO_SHIPPING_BUNDLE_KEY, PAYMENT_ROUTING_EXCLUSION_CODES, PAYPAL_CURRENCIES, PLATFORM_CODE_SETS, POINT_ADJUSTMENT_MAX, POINT_EARN_RATE_BP_MAX, POINT_ENTRY_TYPES, POINT_EXPIRY_DAYS_MAX, POINT_EXPIRY_DAYS_MIN, POINT_LOT_SOURCES, POINT_POLICY_DEFAULTS, POINT_REVIEW_REWARD_MAX, POINT_USE_UNITS, PORTONE_CHANNEL_NAME_MAX_LENGTH, PORTONE_MAX_CHANNELS, PORTONE_MIN_CHANNELS, REFUND_POLICY_DEFAULTS, REFUND_POLICY_DELIVERY_FEE_KEYS, REMOTE_AREA_ZIP_RANGES, RESERVED_STOREFRONT_SLUGS, RESERVED_STORE_CODES, SAYREN_API_BASE_URL, SAYREN_API_ORIGIN, SCOPE_DESCRIPTIONS, SHIPPING_POLICY_DEFAULTS, STARTER_SELLER_TASKS, STARTER_STAGES, STOREFRONT_BLOCKED_PATH_SEGMENTS, STOREFRONT_BUILD_STAGES, STOREFRONT_BUILD_TERMINAL_STATUSES, STOREFRONT_CHECK_TERMINAL_STATUSES, STOREFRONT_CLOSED_SITE_HOLD_DAYS, STOREFRONT_CUSTOM_DOMAIN_LIMIT_DEFAULT, STOREFRONT_DOMAIN_DNS_GRACE_DAYS, STOREFRONT_DOMAIN_DNS_WAIT_DAYS, STOREFRONT_DOMAIN_TXT_LABEL, STOREFRONT_EDIT_ACTIVITY_TIMEOUT_MINUTES, STOREFRONT_EDIT_CAPACITY, STOREFRONT_EDIT_IDLE_MINUTES, STOREFRONT_EDIT_PREVIEW_SUFFIX, STOREFRONT_EDIT_START_STAGES, STOREFRONT_FILE_BATCH_MAX, STOREFRONT_FILE_MAX_BYTES, STOREFRONT_PATH_SEGMENT_PATTERN, STOREFRONT_PLATFORM_DOMAINS, STOREFRONT_PUBLIC_SUFFIXES, STOREFRONT_SEARCH_REGEX_MAX_LENGTH, STOREFRONT_SHOWCASE_SLUG_PREFIX, STOREFRONT_SITE_CREATE_LIMIT, STOREFRONT_SLUG_CHANGE_LIMIT, STOREFRONT_SLUG_CHANGE_WINDOW_DAYS, STOREFRONT_SLUG_HOLD_DAYS, STOREFRONT_SLUG_PATTERN, STOREFRONT_SOURCE_BLOB_BATCH_MAX, STOREFRONT_SOURCE_PART_BYTES, STOREFRONT_WORKSPACE_MAX_BYTES, STOREFRONT_WORKSPACE_MAX_FILES, STORE_CODE_PATTERN, STORE_DRAFT_ATTACHMENT_MAX_BYTES, STORE_DRAFT_MAX_ATTACHMENTS, STORE_DRAFT_RETENTION_DAYS, STORE_ROLE_SCOPES, STORE_SCOPE_RESOURCES, STORE_SESSION_KEYS, STORE_SHOP_TYPES, TEMPLATE_STORE_LOCKED_BUSINESS_FIELDS, TOSS_WIDGET_CLIENT_KEY_PATTERN, TOSS_WIDGET_KEY_MESSAGE, TOSS_WIDGET_SECRET_KEY_PATTERN, UPLOAD_PURPOSE_LIMITS, VARIANT_COUNT_WARNING, VARIANT_STOCK_EXCLUSIVE_MESSAGE, WEBHOOK_DEFAULT_TOLERANCE_SEC, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_EVENT_TYPE_HEADER, WEBHOOK_FAILURE_REASONS, WEBHOOK_HEADERS, WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES, WEBHOOK_RESOURCE_TYPES, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_USER_AGENT, addStorefrontDomainRequestSchema, additionalCurrencyPriceSchema, additionalCurrencyPricesSchema, addonGroupRequestSchema, addonGroupSchema, addonValueRequestSchema, addonValueSchema, addressChangeRequestListSchema, addressTypeSchema, agentPolicyDecisionSchema, aiActivitySchema, aiAgentPhaseSchema, aiAttachmentSchema, aiChoiceOptionSchema, aiConversationFileChangesSchema, aiConversationSchema, aiConversationSummarySchema, aiDesignBoardSchema, aiDesignCanvasSchema, aiDesignConfirmBoardSchema, aiDesignSelectionSchema, aiFileChangeKindSchema, aiFocusAreaSchema, aiFocusSchema, aiMessagePartSchema, aiMessageSchema, aiPreviewSelectionSchema, aiRunChangesSchema, aiRunChangesStatusSchema, aiRunFileDiffSchema, aiRunRevertConflictDetailsSchema, aiRunRevertResultSchema, aiRunSchema, aiRunStatusSchema, aiSetupConfirmItemSchema, aiStreamAccessSchema, aiStreamEventSchema, aiStreamRecordSchema, aiTodoSchema, aiToolChangeSchema, allocateByWeight, analyticsChannelSchema, analyticsCheckoutOutcomeSchema, analyticsCheckoutSchema, analyticsDeviceRowSchema, analyticsDevicesSchema, analyticsFunnelStepSchema, analyticsOriginSchema, analyticsOverviewSchema, analyticsPagesQuerySchema, analyticsPagesSchema, analyticsProductRowSchema, analyticsProductSortSchema, analyticsProductsQuerySchema, analyticsProductsSchema, analyticsRangeQuerySchema, analyticsRealtimeSchema, analyticsSearchQuerySchema, analyticsSearchSchema, analyticsSourceGroupBySchema, analyticsSourceRowSchema, analyticsSourcesQuerySchema, analyticsSourcesSchema, analyticsTotalsSchema, apiLogErrorSchema, apiLogListQuerySchema, apiLogPageSchema, apiLogPrincipalSchema, apiLogPrincipalTypeSchema, apiLogSchema, apiLogStatusFilterSchema, apiLogSummarySchema, appArtifactUploadSchema, appBuildSchema, appBuildStageSchema, appCapabilitiesOf, appDeployKeyCreateSchema, appDeployKeyCreatedSchema, appDeployKeySchema, appDevTokenSchema, appDistributionSchema, appEventTypeSchema, appFlowEventSchema, appFlowEventSummarySchema, appFlowNotificationSchema, appFlowNotificationSummarySchema, appFlowParamSchema, appFlowSummaryOf, appHandleSchema, appHttpKeyMatches, appIconProblem, appInstallRequestSchema, appInstallationActivitySchema, appInstallationAppSchema, appInstallationRunSchema, appInstallationSchema, appInstallationSelfSchema, appInstallationSettingsSchema, appInstallationSettingsUpdateSchema, appInstallationStatusSchema, appInvocationSchema, appListingReviewSchema, appListingReviewStatusSchema, appListingSchema, appManifestProblems, appManifestSchema, appManifestWidens, appNetworkHostProblem, appNetworkHostSchema, appReleaseResultSchema, appRuntimeSchema, appScheduleIntervalLabel, appScheduleListOf, appScheduleSummarySchema, appScopeSchema, appSecretSummarySchema, appSessionSchema, appSettingFieldSchema, appStatusSchema, appStorageEntrySchema, appStorageKeysSchema, appStorageListQuerySchema, appStoragePutSchema, appToolCallSchema, appToolInputSchema, appToolListOf, appToolResultSchema, appToolSchema, appToolSummarySchema, appVersionSchema, appVersionStatusSchema, appVisibilitySchema, applyFlowOperationsRequestSchema, approvalDecisionRequestSchema, approvalListQuerySchema, approvalPageSchema, approvalRequestSchema, approvalStatusSchema, approveClaimResultSchema, assertSaleUnit, auditActorSchema, auditActorTypeSchema, auditLogListQuerySchema, auditLogOutcomeSchema, auditLogPageSchema, auditLogSchema, auditLogSourceSchema, bestSellingRuleOf, brandBriefProductSourceSchema, brandBriefReferenceSchema, brandBriefSchema, brandBriefViewSchema, buildAuthorizeUrl, buildQuery, bulkResultSchema, businessInfoPatchShape, businessInfoResponseShape, businessNumberSchema, calendarDateSchema, calendarDaySchema, calendarQuerySchema, cancelBySellerRequestSchema, cancelBySellerResultSchema, carrierSchema, cashReceiptSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryLocalizationRequestSchema, categoryLocalizationSchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeStorefrontSlugRequestSchema, changeStorefrontTemplateRequestSchema, changeTypeSchema, claimCollectCompleteRequestSchema, claimDetailSchema, claimFlowEditSessionRequestSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimRedeliveryRequestSchema, claimReturnAddressSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, collectionCreateRequestSchema, collectionListQuerySchema, collectionLocalizationRequestSchema, collectionLocalizationSchema, collectionPageSchema, collectionPatchRequestSchema, collectionPreviewRequestSchema, collectionPreviewSchema, collectionProductListQuerySchema, collectionProductSchema, collectionProductSortRequestSchema, collectionProductsAddRequestSchema, collectionProductsReplaceRequestSchema, collectionRuleCategoryIds, collectionRuleSchema, collectionRuleViewSchema, collectionRulesPredicate, collectionRulesSchema, collectionSchema, collectionStateCountsSchema, collectionStateOf, collectionStateSchema, commerceFlowCheckSchema, commerceFlowSchema, commerceFlowSummarySchema, commerceFlowVersionViewSchema, commerceNumberField, compareBySales, connectStorefrontGitRequestSchema, consentActionSchema, consentKindSchema, consentSourceSchema, couponBenefitSchema, couponConditionsInputSchema, couponConditionsSchema, couponDiscountOf, couponIssueListQuerySchema, couponIssueMethodSchema, couponIssueSchema, couponIssueStatusSchema, couponKindSchema, couponListQuerySchema, couponRedemptionListQuerySchema, couponRedemptionSchema, couponRejectReasonSchema, couponRuleSchema, couponSchema, couponStatsSchema, couponStatusSchema, couponTargetInputSchema, couponTargetSchema, createAiConversationRequestSchema, createAiConversationResponseSchema, createCommerceFlowRequestSchema, createCouponRequestSchema, createMarketRequestSchema, createPkcePair, createStoreClient, createStoreDraftRequestSchema, createStoreDraftResponseSchema, createStoreSession, createStorefrontEditPreviewLinkRequestSchema, createStorefrontPreviewLinkRequestSchema, createStorefrontSiteRequestSchema, createStorefrontVersionRequestSchema, currencyCodeSchema, currencyRefundFeesSchema, currencyShippingPolicySchema, currencySpecOf, customInputLabelForbiddenWord, customInputRequestSchema, customInputSchema, customInputValueSchema, customerAddressSchema, customerConsentListQuerySchema, customerConsentSchema, customerConsentStateSchema, customerConsentsSchema, customerCouponSchema, customerDelegationRequestSchema, customerDelegationSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerPointsSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, defaultFulfillmentMethodOf, deleteStorefrontFileRequestSchema, deliveryBundleKeyOf, deliveryFeeWaiverSchema, deliveryInfoSchema, deliveryMethodSchema, deliveryStatusSchema, deliveryTypeSchema, descendantCategoryIdsOf, describeScope, devStoreSchema, developerAppCreateSchema, developerAppSchema, developerInstallationSchema, developerOrgSchema, developerStoreSchema, disableStorefrontHostingRequestSchema, discountRequestSchema, discountSchema, dispatchRequestSchema, easyPayProviderResponseSchema, easyPayProviderSchema, eventTypeSchema, exchangeAuthorizationCode, floorToSaleUnit, flowActionRequestSchema, flowActionResultSchema, flowActionSchema, flowAuthoringGuideSchema, flowDraftEdgesSchema, flowDraftNodeSchema, flowDraftNodesSchema, flowDraftOperationSchema, flowEditSessionViewSchema, flowFieldValueSchema, flowInputFieldSchema, flowIssueSchema, flowNodeIdSchema, flowNodeTypeDetailSchema, flowNodeTypesSchema, flowNotificationWebhookEventDataSchema, flowNotificationWebhookEventSchema, flowOperationsResultSchema, flowPresetDetailSchema, flowPresetSummarySchema, flowRunSchema, flowRunStepSchema, flowSecretNameSchema, flowSecretSchema, flowStateChangedWebhookEventDataSchema, flowStateChangedWebhookEventSchema, flowStateSchema, formatOrderNo, fromDecimalString, fulfillBulkRequestSchema, fulfillRequestSchema, fulfillmentMethodOf, fulfillmentMethodSchema, fulfillmentMethodsOf, fulfillmentRuleOf, fulfillmentTypeOf, fulfillmentTypeResponseSchema, fulfillmentTypeSchema, holdOrderItemRequestSchema, infoFieldSourceSchema, infoSchemaFieldSchema, infoSchemaSchema, infoSectionLocalizationRequestSchema, infoSectionLocalizationSchema, infoSectionRequestSchema, infoSectionSchema, inquiryListQuerySchema, inquirySchema, inquiryWebhookEventDataSchema, inquiryWebhookEventSchema, inventoryAdjustmentLineSchema, inventoryAdjustmentReasonSchema, inventoryAdjustmentRequestSchema, inventoryChangedWebhookEventDataSchema, inventoryChangedWebhookEventSchema, inventoryLevelListQuerySchema, inventoryLevelPageSchema, inventoryLevelSchema, inventoryLocationRequestSchema, inventoryLocationSchema, inventoryModeSchema, inventoryMovementKindSchema, inventoryMovementListQuerySchema, inventoryMovementPageSchema, inventoryMovementSchema, inventoryOperationResultSchema, inventoryTransferRequestSchema, invitationDeliveryStatusSchema, invitationListQuerySchema, invitationSchema, inviteMemberRequestSchema, isAiAgentNotesPath, isAiChoiceAnswer, isAiDesignPath, isAiWorkspaceDocPath, isCouponTargetLine, isCurrencyCode, isEditableStorefrontPath, isInstallableScope, isReservedStoreCode, isReservedStorefrontSlug, isSaleUnitPrice, isShowcaseStorefrontSlug, isStoreScope, isWebOrigin, issueCouponRequestSchema, issueCouponResultSchema, kakaoPayCredentialsInputSchema, linkStorefrontGitInstallationRequestSchema, liveGateConditionCodeSchema, liveGateConditionSchema, liveGateErrorDetailsSchema, liveGateSchema, localeCodeSchema, loginProviderSchema, loginProviderStatusSchema, loginProviderTestSchema, loginSettingsSchema, marketSchema, maskedSecretSchema, matchesCollectionRules, mcpRuleResultSchema, mcpToolEventSchema, migrateFlowVersionRequestSchema, migrateFlowVersionResultSchema, minPaymentOf, minorToMajor, moneyRulesOf, moveFlowStateRequestSchema, moveStorefrontFileRequestSchema, myAccountSchema, myStoreSchema, naverPayCredentialsInputSchema, nightsOf, normalizeBusinessNumber, normalizeCouponCode, normalizeLocale, normalizeStorefrontHostname, normalizeStorefrontPath, oauthTokenResponseSchema, openFulfillmentUnion, optionGroupKindSchema, optionGroupRequestSchema, optionGroupSchema, optionModelRequestSchema, optionModelSchema, optionSelectionSchema, optionSortSchema, optionValueRequestSchema, optionValueSchema, orderCanceledWebhookEventDataSchema, orderCanceledWebhookEventSchema, orderDiscountSchema, orderFlowActionResultSchema, orderFulfilledWebhookEventDataSchema, orderFulfilledWebhookEventSchema, orderItemFlowSchema, orderItemFulfillmentSchema, orderItemFulfillmentSnapshotResponseSchema, orderItemFulfillmentSnapshotSchema, orderItemListQuerySchema, orderItemMemoResultSchema, orderItemPageSchema, orderItemSchema, orderItemStatusSchema, orderListQuerySchema, orderSchema, orderSummaryPageSchema, orderSummarySchema, orderWebhookEventDataSchema, orderWebhookEventSchema, pageInfoSchema, pageQueryShape, pageSchema, parseOrderNo, parseWebhookEvent, payPalCredentialsInputSchema, paymentAttemptRecordSchema, paymentAttemptStatusSchema, paymentCredentialSetSchema, paymentFailureWarningSchema, paymentListQuerySchema, paymentProviderSchema, paymentProviderVerificationSchema, paymentRecordDetailSchema, paymentRecordPageSchema, paymentRecordSchema, paymentRecordStatusSchema, paymentRefundRecordSchema, paymentSettingsSchema, paymentStatusProviderSchema, paymentStatusSchema, pgEnvironmentSchema, pgPaymentMethodSchema, pgProviderResponseSchema, pgProviderSchema, pgVerificationResultSchema, pickupLocationRequestSchema, pickupLocationSchema, pickupLocationSnapshotSchema, planCodeSchema, planEntitlementsSchema, planErrorDetailsSchema, platformCodeSchema, pointAdjustmentRequestSchema, pointAdjustmentResultSchema, pointEarnOf, pointEarnRateBpSchema, pointEarningEnabled, pointEntrySchema, pointExpiresAtOf, pointHistoryQuerySchema, pointLotSchema, pointPolicyNoticeSchema, pointPolicySchema, pointRestoreExpiresAtOf, pointUseOf, pointUsePolicySchema, policyDocumentUrlSchema, policyVersionSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCertificationsRequestSchema, productCertificationsSchema, productCreateRequestSchema, productCurrencyPriceSchema, productCurrencyPricesSchema, productFulfillmentCreateSchema, productFulfillmentResponseSchema, productFulfillmentSchema, productFulfillmentUpdateSchema, productImageRejection, productImageUrlSchema, productListQuerySchema, productLocalizationNeedsTranslation, productLocalizationRequestSchema, productLocalizationSchema, productNoticeRequestSchema, productNoticeSchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productRefundPolicyOverride, productRefundPolicyPatchSchema, productReplaceRequestSchema, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, proratedPaidRefundBase, proratedPointRefund, proratedRefundBase, publicPlanSchema, publicPlansSchema, publishStorefrontVersionRequestSchema, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, purchaseEarnPolicySchema, purchaseEarnRateOf, putBrandBriefRequestSchema, quoteDelivery, quotePricing, rankBestSelling, refreshUserToken, refundPolicyPatchSchema, refundPolicySchema, rejectClaimRequestSchema, remoteAreaLabelOf, remoteAreaOf, remoteAreaSchema, remoteSurchargeOf, replaceStorefrontSourceRequestSchema, replayFlowRequestSchema, replayFlowResultSchema, requiresCollection, requiresShipping, resolvePointPolicy, resolveRefundPolicy, resolveShippingPolicy, resolvedFlowSchema, responsePlanCodeSchema, responsePointEntryTypeSchema, reviewListQuerySchema, reviewReportResultSchema, reviewRewardPointOf, reviewRewardPolicySchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, rollbackStorefrontRequestSchema, runStorefrontCheckRequestSchema, salesReportCurrencySchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, saveFlowDraftRequestSchema, saveFlowSecretRequestSchema, saveLoginProviderRequestSchema, savedCustomInputRequestSchema, savedCustomInputSchema, savedOptionGroupRequestSchema, savedOptionGroupSchema, savedOptionSetCompositionSchema, savedOptionSetFromProductRequestSchema, savedOptionSetFromProductResultSchema, savedOptionSetListQuerySchema, savedOptionSetLocalizationRequestSchema, savedOptionSetLocalizationSchema, savedOptionSetRequestSchema, savedOptionSetSchema, savedOptionSetSortSchema, savedOptionValueRequestSchema, savedOptionValueSchema, scopeAccessSchema, scopesCoverEvent, searchStorefrontFilesRequestSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCancelPreviewSchema, sellerCustomerInquirySchema, sendAiMessageRequestSchema, sendAiMessageResponseSchema, setCalendarRequestSchema, setPlatformTestKeysRequestSchema, setStorefrontDeployApprovalRequestSchema, setStorefrontVisibilityRequestSchema, settleCouponShortfall, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, shippingCurrencyPriceSchema, shippingCurrencyPricesSchema, shippingPolicyPatchSchema, shippingPolicySchema, simulateFlowRequestSchema, simulateFlowResultSchema, simulationStepSchema, splitRefund, starterSellerTaskSchema, starterStageSchema, starterStatusSchema, starterStoreInfoFieldSchema, stayRangeSchema, staySnapshotSchema, storeAppDetailSchema, storeAppSchema, storeCodeSchema, storeDraftPreviewSchema, storeDraftSchema, storeIndustrySchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storePointPolicySchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeSetupBriefSchema, storeShopTypeSchema, storeSubscriptionSchema, storeTemplateSchema, storedAdditionalCurrencyPriceSchema, storedProductCurrencyPriceSchema, storedShippingCurrencyPriceSchema, storefrontBuildDependenciesSchema, storefrontBuildListQuerySchema, storefrontBuildSchema, storefrontBuildStatusSchema, storefrontCheckSchema, storefrontCheckStatusSchema, storefrontCustomDomainStatusSchema, storefrontCustomHostnameProblem, storefrontDependencyFindingSchema, storefrontDeploymentLogSchema, storefrontDeploymentSchema, storefrontDeploymentStepSchema, storefrontDevLogsSchema, storefrontDnsRecordSchema, storefrontDomainSchema, storefrontDomainTxtNameOf, storefrontEditFailureSchema, storefrontEditPreviewLabelOf, storefrontEditPreviewSchema, storefrontEditSessionSchema, storefrontEditSessionStatusSchema, storefrontEditingSchema, storefrontFileConflictDetailsSchema, storefrontFileContentQuerySchema, storefrontFileContentSchema, storefrontFileDeleteResultSchema, storefrontFileEncodingSchema, storefrontFileEntrySchema, storefrontFileHashSchema, storefrontFileListQuerySchema, storefrontFileListSchema, storefrontFileMoveResultSchema, storefrontFilePathSchema, storefrontFileSearchResultSchema, storefrontFileWriteResultSchema, storefrontGitConnectStateSchema, storefrontGitMergeRequestSchema, storefrontGitMergeSchema, storefrontGitRepositorySchema, storefrontGitStatusSchema, storefrontHostingSchema, storefrontPreviewLinkSchema, storefrontProvisioningSchema, storefrontRuleResultSchema, storefrontRuleSeveritySchema, storefrontSiteDomainSchema, storefrontSiteDomainsSchema, storefrontSiteSchema, storefrontSiteSnapshotSchema, storefrontSiteStatusSchema, storefrontSlugAvailabilityQuerySchema, storefrontSlugAvailabilitySchema, storefrontSlugSchema, storefrontSourceArchivePartSchema, storefrontSourceArchiveQuerySchema, storefrontSourceBlobsResultSchema, storefrontSourceModeSchema, storefrontSourceRefSchema, storefrontSourceReplacedSchema, storefrontSourceSchema, storefrontSuspensionSchema, storefrontTemplateSchema, storefrontVerifyReportSchema, storefrontVersionCreatedSchema, storefrontVersionPreviewLabelOf, storefrontVersionSchema, storefrontVersionStatusSchema, storefrontVisibilitySchema, subscriptionLimitsSchema, subscriptionStatusSchema, subscriptionUsageSchema, toDecimalString, toMinor, tossPaymentsCredentialsInputSchema, trackingStageResponseSchema, trackingUpdateResultSchema, unknownWebhookEventSchema, updateCouponRequestSchema, updateLoginProviderRequestSchema, updateLoginSettingsRequestSchema, updateMarketRequestSchema, updateMemberRoleRequestSchema, updatePaymentProviderRequestSchema, updatePaymentSettingsRequestSchema, updatePointPolicyRequestSchema, updateStoreRequestSchema, updateStoreTemplateRequestSchema, uploadExtensionOf, uploadPurposeSchema, uploadRejection, uploadRequestSchema, uploadStorefrontSourceBlobsRequestSchema, uploadTicketSchema, upsertKakaoPayProviderRequestSchema, upsertNaverPayProviderRequestSchema, upsertPayPalProviderRequestSchema, upsertPortOneProviderRequestSchema, upsertTossPaymentsProviderRequestSchema, variantStockRequestSchema, variantStockSchema, verifyPaymentProviderRequestSchema, webhookCreatedSchema, webhookDeliveryDetailSchema, webhookDeliveryErrorCodeSchema, webhookDeliveryListQuerySchema, webhookDeliveryResourceSchema, webhookDeliverySchema, webhookDeliveryStatusSchema, webhookEventSchema, webhookFailureReasonSchema, webhookRedeliverFailedResultSchema, webhookRequestHeaderSchema, webhookRequestSchema, webhookResourceTypeSchema, webhookSchema, webhookSecretRotatedSchema, webhookStatusSchema, webhookTestRequestSchema, webhookTestResultSchema, withdrawCustomerRequestSchema, writeDryRunResultSchema, writePreviewSchema, writeStorefrontFilesRequestSchema };