@underdogai/mesh-event-schemas 0.6.0 → 0.9.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/blocks.d.ts CHANGED
@@ -15,6 +15,56 @@ export declare const ToneSchema: z.ZodEnum<["neutral", "success", "warning", "da
15
15
  export type Tone = z.infer<typeof ToneSchema>;
16
16
  export declare const ButtonStyleSchema: z.ZodEnum<["default", "primary", "danger"]>;
17
17
  export type ButtonStyle = z.infer<typeof ButtonStyleSchema>;
18
+ /**
19
+ * **참조 값**(0.8.0) — 사람·엔티티를 문자열이 아니라 가리키는 값으로 싣는다.
20
+ *
21
+ * 왜 필요한가: 같은 사람이 카드 안에서 세 표기로 흩어진다 — fields 의 "현호 손", 옵션 라벨
22
+ * "goya@bluepinlabs.com", 이력의 "heetae". 앱이 서버에서 표시명을 만들어 문자열로 박기 때문인데,
23
+ * 그러면 형식이 갈리고 얼굴이 없고 개명·동명이인에 취약하다. 값이 **MXID 참조**이고 클라가 방 상태로
24
+ * 이름·아바타를 해석하면, 어느 블록에 놓여도 같은 얼굴로 선다.
25
+ *
26
+ * 🔴 **평문 사본은 남는다**(`fields.parts` 와 같은 규칙 — §4). `ref` 를 모르는 옛 클라는 이 키를
27
+ * zod strip 으로 벗기고 `value`/`label`/`name` 문자열을 지금처럼 그린다. 그래서 참조를 실으면서도
28
+ * 사본을 비우면 **그 필드가 빈칸이 된다** — 사본은 선택이 아니라 계약이다.
29
+ *
30
+ * 🔴 **이것도 권한이 아니다.** 값이 MXID 라는 것은 서버가 멤버십으로 재검증할 수 있다는 뜻이지,
31
+ * 클라가 신원을 판정한다는 뜻이 아니다.
32
+ */
33
+ export declare const RefSchema: z.ZodUnion<[z.ZodObject<{
34
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
35
+ user: z.ZodString;
36
+ }, "strip", z.ZodTypeAny, {
37
+ user: string;
38
+ }, {
39
+ user: string;
40
+ }>, z.ZodObject<{
41
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
42
+ entity: z.ZodObject<{
43
+ type: z.ZodString;
44
+ id: z.ZodString;
45
+ }, "strip", z.ZodTypeAny, {
46
+ type: string;
47
+ id: string;
48
+ }, {
49
+ type: string;
50
+ id: string;
51
+ }>;
52
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
53
+ url: z.ZodOptional<z.ZodString>;
54
+ }, "strip", z.ZodTypeAny, {
55
+ entity: {
56
+ type: string;
57
+ id: string;
58
+ };
59
+ url?: string | undefined;
60
+ }, {
61
+ entity: {
62
+ type: string;
63
+ id: string;
64
+ };
65
+ url?: string | undefined;
66
+ }>]>;
67
+ export type Ref = z.infer<typeof RefSchema>;
18
68
  /** 파괴적 액션 전에 클라이언트가 띄우는 확인 다이얼로그. 서버도 별도로 HITL 재검증한다. */
19
69
  export declare const ConfirmSchema: z.ZodObject<{
20
70
  title: z.ZodString;
@@ -101,6 +151,54 @@ export declare const FieldsBlockSchema: z.ZodObject<{
101
151
  text: string;
102
152
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
103
153
  }>, "many">>;
154
+ /**
155
+ * 이 값이 가리키는 사람/엔티티 (0.8.0). 있으면 렌더러가 칩(아바타+이름 / 종류+라벨)으로 그린다.
156
+ * 🔴 **`value` 는 평문 사본으로 남긴다** — `parts` 와 같은 규칙이다(RefSchema 머리말).
157
+ */
158
+ ref: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
159
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
160
+ user: z.ZodString;
161
+ }, "strip", z.ZodTypeAny, {
162
+ user: string;
163
+ }, {
164
+ user: string;
165
+ }>, z.ZodObject<{
166
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
167
+ entity: z.ZodObject<{
168
+ type: z.ZodString;
169
+ id: z.ZodString;
170
+ }, "strip", z.ZodTypeAny, {
171
+ type: string;
172
+ id: string;
173
+ }, {
174
+ type: string;
175
+ id: string;
176
+ }>;
177
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
178
+ url: z.ZodOptional<z.ZodString>;
179
+ }, "strip", z.ZodTypeAny, {
180
+ entity: {
181
+ type: string;
182
+ id: string;
183
+ };
184
+ url?: string | undefined;
185
+ }, {
186
+ entity: {
187
+ type: string;
188
+ id: string;
189
+ };
190
+ url?: string | undefined;
191
+ }>]>>;
192
+ /**
193
+ * **이 항목은 문단이다**(0.9.0) — 값이 아니라 본문. 전체폭으로 서고 값 서체(600)를 풀며
194
+ * 인라인 마크다운을 그린다.
195
+ *
196
+ * 왜 필요한가(감사 문서 D): "막힌 일: ㅁㄴㄹ…" 같은 자유 서술이 지금은 굵은 값 서체로 서서
197
+ * 숫자·상태와 같은 무게로 읽힌다. 작성자가 `short` 로 열 수를 강제하던 것과 같은 자리 —
198
+ * 작성자는 "이건 문단이다"만 말하고 폭·서체는 렌더러가 정한다.
199
+ * ⚠️ `short` 와 같이 주면 `long` 이 이긴다(반폭 문단은 없다).
200
+ */
201
+ long: z.ZodOptional<z.ZodBoolean>;
104
202
  }, "strip", z.ZodTypeAny, {
105
203
  value: string;
106
204
  label: string;
@@ -109,6 +207,16 @@ export declare const FieldsBlockSchema: z.ZodObject<{
109
207
  text: string;
110
208
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
111
209
  }[] | undefined;
210
+ ref?: {
211
+ user: string;
212
+ } | {
213
+ entity: {
214
+ type: string;
215
+ id: string;
216
+ };
217
+ url?: string | undefined;
218
+ } | undefined;
219
+ long?: boolean | undefined;
112
220
  }, {
113
221
  value: string;
114
222
  label: string;
@@ -117,7 +225,26 @@ export declare const FieldsBlockSchema: z.ZodObject<{
117
225
  text: string;
118
226
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
119
227
  }[] | undefined;
228
+ ref?: {
229
+ user: string;
230
+ } | {
231
+ entity: {
232
+ type: string;
233
+ id: string;
234
+ };
235
+ url?: string | undefined;
236
+ } | undefined;
237
+ long?: boolean | undefined;
120
238
  }>, "many">;
239
+ /**
240
+ * 열 수 **명시 오버라이드**(0.9.0). 생략이 기본이고, 기본은 폭이 정하는 auto-fit 이다
241
+ * (그리고 `short` 넷이면 2×2 로 묶인다 — 0.7.0 에서 이미 들어간 규칙).
242
+ *
243
+ * 🔴 **기본을 되돌리지 않는다.** 이 키는 auto-fit 이 틀리는 드문 경우(라벨이 길어 3열이 찢어지는
244
+ * 표 같은 fields)를 위한 탈출구다 — 늘 주면 좁은 화면에서 열이 안 줄어 값이 짜부라진다.
245
+ * `"auto"` 는 명시적으로 기본을 고르는 값이다(작성자가 "여긴 렌더러에 맡긴다"를 적을 수 있게).
246
+ */
247
+ columns: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<"auto">]>>;
121
248
  }, "strip", z.ZodTypeAny, {
122
249
  type: "fields";
123
250
  items: {
@@ -128,7 +255,18 @@ export declare const FieldsBlockSchema: z.ZodObject<{
128
255
  text: string;
129
256
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
130
257
  }[] | undefined;
258
+ ref?: {
259
+ user: string;
260
+ } | {
261
+ entity: {
262
+ type: string;
263
+ id: string;
264
+ };
265
+ url?: string | undefined;
266
+ } | undefined;
267
+ long?: boolean | undefined;
131
268
  }[];
269
+ columns?: 2 | 3 | "auto" | undefined;
132
270
  }, {
133
271
  type: "fields";
134
272
  items: {
@@ -139,7 +277,18 @@ export declare const FieldsBlockSchema: z.ZodObject<{
139
277
  text: string;
140
278
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
141
279
  }[] | undefined;
280
+ ref?: {
281
+ user: string;
282
+ } | {
283
+ entity: {
284
+ type: string;
285
+ id: string;
286
+ };
287
+ url?: string | undefined;
288
+ } | undefined;
289
+ long?: boolean | undefined;
142
290
  }[];
291
+ columns?: 2 | 3 | "auto" | undefined;
143
292
  }>;
144
293
  export declare const ImageBlockSchema: z.ZodObject<{
145
294
  type: z.ZodLiteral<"image">;
@@ -158,9 +307,18 @@ export declare const ImageBlockSchema: z.ZodObject<{
158
307
  mxc?: string | undefined;
159
308
  alt?: string | undefined;
160
309
  }>;
310
+ /**
311
+ * 작은 보조 텍스트/아이콘 줄.
312
+ *
313
+ * ⬜ **여기엔 `ref` 원소를 안 둔다(0.8.0에서 일부러 뺐다).** 다른 자리의 참조는 *기존 객체의 새 키*라
314
+ * 옛 클라가 zod strip 으로 벗기고 평문 사본을 그리지만, 여기 `elements` 는 **닫힌 유니온**이라 새
315
+ * 모양의 원소 하나가 유니온 전체를 실패시키고 → 배열이 실패하고 → `dropUnknownBlocks` 가 **context
316
+ * 블록을 통째로 떨군다**. 즉 "평문 사본이 곁에 선다"는 규칙이 성립하지 않는 유일한 자리다
317
+ * (`parts`·`hidden_for`·`ref` 가 다 되는 이유가 그 셋은 키 추가이기 때문이다).
318
+ * 사람을 보조 줄에 그리고 싶으면 `activity` 블록이나 `fields` 항목의 `ref` 를 쓴다.
319
+ */
161
320
  export declare const ContextBlockSchema: z.ZodObject<{
162
321
  type: z.ZodLiteral<"context">;
163
- /** 작은 보조 텍스트/아이콘 줄 */
164
322
  elements: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
165
323
  icon: z.ZodString;
166
324
  }, "strip", z.ZodTypeAny, {
@@ -237,26 +395,68 @@ export declare const InputBlockSchema: z.ZodObject<{
237
395
  * 단일 업로드로 동작한다(기능 축소일 뿐 파손 없음).
238
396
  */
239
397
  multiple: z.ZodOptional<z.ZodBoolean>;
398
+ /**
399
+ * 하한/상한 (0.7.0) — number/date/datetime/time 공용. **문자열**이다: 날짜·시각은 그 타입의 값
400
+ * 형식(`2026-09-22`·`18:15`)이고, number 면 숫자를 적은 문자열이다(와이어 canonical JSON 은
401
+ * 소수를 허용하지 않아 숫자 축을 열 수 없다 — `slider` 가 int 만 받는 것과 같은 제약).
402
+ *
403
+ * `"today"` 리터럴을 허용한다 — "기한은 오늘 이후"는 카드를 **보낸 날**이 아니라 **보는 날** 기준이라야
404
+ * 맞다(카드는 타임라인에 남고 며칠 뒤에도 눌린다). 렌더러가 그릴 때 해석한다.
405
+ *
406
+ * 🔴 **UX 다, 진실은 서버**(`hidden_for` 와 같은 자세). 클라가 미리 잠그는 건 헛걸음을 줄이려는
407
+ * 것뿐이고, 진짜 판정은 언제나 핸들러·게이트가 한다. 이 키를 모르는 옛 클라는 strip 하고 지금처럼
408
+ * 아무 제약 없이 제출한다 — 그러면 서버가 사람이 읽을 이유와 함께 거절한다(`action.result`).
409
+ */
410
+ min: z.ZodOptional<z.ZodString>;
411
+ max: z.ZodOptional<z.ZodString>;
412
+ /** 글자 수 하한/상한 (0.7.0) — 텍스트 계열 전용. 🔴 UX 다, 진실은 서버. */
413
+ minLength: z.ZodOptional<z.ZodNumber>;
414
+ maxLength: z.ZodOptional<z.ZodNumber>;
415
+ /**
416
+ * 값이 맞아야 하는 정규식 **소스**(0.7.0, 예: `"^[A-Z]{2}-\\d{4}$"`). 플래그·구분자 없이 패턴만 적는다.
417
+ *
418
+ * 🔴 렌더러는 `new RegExp` 를 **try/catch 로 감싼다** — 작성자가 자바스크립트가 아닌 방언(파이썬
419
+ * `(?P<x>…)` 등)을 보내면 던지는데, 그걸로 카드 전체가 죽으면 안 된다. 못 읽는 패턴은 무시한다
420
+ * (= 제약 없음). 진짜 판정은 여전히 서버다.
421
+ */
422
+ pattern: z.ZodOptional<z.ZodString>;
423
+ /**
424
+ * 제약 위반 시 보여 줄 **작성자 소유 문장**(0.7.0). 없으면 렌더러 크롬 문구를 쓴다
425
+ * (`LabelContext` — "누구의 문자열인가"가 경계선이고, 도메인 사정을 아는 문장은 작성자 것이다).
426
+ */
427
+ error: z.ZodOptional<z.ZodString>;
240
428
  }, "strip", z.ZodTypeAny, {
241
429
  type: "input";
242
430
  name: string;
243
431
  value?: string | undefined;
244
432
  label?: string | undefined;
245
- input?: "number" | "text" | "date" | "url" | "textarea" | "datetime" | "time" | "email" | "file" | undefined;
433
+ input?: "number" | "date" | "url" | "text" | "textarea" | "datetime" | "time" | "email" | "file" | undefined;
246
434
  placeholder?: string | undefined;
247
435
  required?: boolean | undefined;
248
436
  accept?: string | undefined;
249
437
  multiple?: boolean | undefined;
438
+ min?: string | undefined;
439
+ max?: string | undefined;
440
+ minLength?: number | undefined;
441
+ maxLength?: number | undefined;
442
+ pattern?: string | undefined;
443
+ error?: string | undefined;
250
444
  }, {
251
445
  type: "input";
252
446
  name: string;
253
447
  value?: string | undefined;
254
448
  label?: string | undefined;
255
- input?: "number" | "text" | "date" | "url" | "textarea" | "datetime" | "time" | "email" | "file" | undefined;
449
+ input?: "number" | "date" | "url" | "text" | "textarea" | "datetime" | "time" | "email" | "file" | undefined;
256
450
  placeholder?: string | undefined;
257
451
  required?: boolean | undefined;
258
452
  accept?: string | undefined;
259
453
  multiple?: boolean | undefined;
454
+ min?: string | undefined;
455
+ max?: string | undefined;
456
+ minLength?: number | undefined;
457
+ maxLength?: number | undefined;
458
+ pattern?: string | undefined;
459
+ error?: string | undefined;
260
460
  }>;
261
461
  /** 토글(스위치) — checkbox 와 같은 불리언을 수집하되 on/off 스위치 어포던스로 렌더. */
262
462
  export declare const ToggleBlockSchema: z.ZodObject<{
@@ -325,7 +525,13 @@ export type SliderBlock = z.infer<typeof SliderBlockSchema>;
325
525
  * 욱여넣던 것을 두 줄로 가른다(가독성). 옛 클라는 zod 가 벗겨내므로 라벨만 보인다(하위호환).
326
526
  * `style` = 표현 힌트(선택): "cards" 는 옵션을 전체폭 카드 행으로, "segmented" 는 한 줄 세그먼트로
327
527
  * (짧은 라벨 전용 — 렌더러가 hint 를 숨긴다). 값 의미는 동일하고 옛 클라는 평 라디오로 그린다.
328
- * ⚠️ 위치 선택자(:first-child)로 특정 폼만 다르게 칠하지 말 것 — 표현은 이 필드로 선언한다. */
528
+ * ⚠️ 위치 선택자(:first-child)로 특정 폼만 다르게 칠하지 말 것 — 표현은 이 필드로 선언한다.
529
+ *
530
+ * 📎 **0.9.0 부터 이것은 `select` 의 별칭이다** — `style: "list"` · `multi` 없음 · `source` 없음의
531
+ * `select` 와 **같은 컨트롤로 그려진다**(`spec-renderer/OptionGroup.tsx` 한 벌). 스키마를 합치지
532
+ * 않는 이유는 둘뿐이다: ① 이미 나간 카드가 `type: "radio"` 로 쌓여 있고, ② `style: "cards"` 는
533
+ * 라디오에만 있는 표현이다. 새로 쓰는 카드라면 어느 쪽을 골라도 되고, **선택 축이 하나라도 늘면**
534
+ * (`multi`·`source`·`searchable`) `select` 로 가야 한다 — 그 축들은 여기 없다. */
329
535
  export declare const RadioBlockSchema: z.ZodObject<{
330
536
  type: z.ZodLiteral<"radio">;
331
537
  name: z.ZodString;
@@ -345,6 +551,10 @@ export declare const RadioBlockSchema: z.ZodObject<{
345
551
  }>, "many">;
346
552
  value: z.ZodOptional<z.ZodString>;
347
553
  style: z.ZodOptional<z.ZodEnum<["cards", "segmented"]>>;
554
+ /** 고르지 않으면 제출을 잠근다 (0.7.0). 🔴 UX 다, 진실은 서버 — `input.required` 와 같은 자세. */
555
+ required: z.ZodOptional<z.ZodBoolean>;
556
+ /** 미선택 시 보여 줄 작성자 소유 문장 (0.7.0). 없으면 렌더러 크롬 문구. */
557
+ error: z.ZodOptional<z.ZodString>;
348
558
  }, "strip", z.ZodTypeAny, {
349
559
  options: {
350
560
  value: string;
@@ -355,6 +565,8 @@ export declare const RadioBlockSchema: z.ZodObject<{
355
565
  name: string;
356
566
  value?: string | undefined;
357
567
  label?: string | undefined;
568
+ required?: boolean | undefined;
569
+ error?: string | undefined;
358
570
  style?: "cards" | "segmented" | undefined;
359
571
  }, {
360
572
  options: {
@@ -366,48 +578,299 @@ export declare const RadioBlockSchema: z.ZodObject<{
366
578
  name: string;
367
579
  value?: string | undefined;
368
580
  label?: string | undefined;
581
+ required?: boolean | undefined;
582
+ error?: string | undefined;
369
583
  style?: "cards" | "segmented" | undefined;
370
584
  }>;
585
+ /**
586
+ * **후보 공급원**(0.9.0) — 후보가 *어디서 오는가*. 생략하면 `options` 배열이 곧 후보다(지금까지의 동작).
587
+ *
588
+ * 왜 축인가: "검색하기" 버튼 + 체크박스 18개 + "사람 더 보기 · 13명" 은 서로 다른 기능이 아니라
589
+ * **후보가 카드 밖에 있을 때** 작성자가 손으로 만든 우회 UI 다(감사 문서 B). 공급원을 선언으로
590
+ * 올리면 검색·스크롤·아바타 행은 렌더러가 정한다.
591
+ *
592
+ * 🔴 **`source` 를 줘도 `options` 는 계약이다.** 이 키를 모르는 옛 클라는 zod strip 으로 벗기고
593
+ * `options` 만 그린다 — 비워 보내면 그 클라에서 **고를 것이 없는 select** 가 선다(`ref` 의 평문
594
+ * 사본과 같은 규칙, `RefSchema` 머리말). 방 멤버는 빌더가 채울 수 없으므로(서버는 방 상태를 모를
595
+ * 수 있다) 그땐 카드 `fallback` 이 대신 설명해야 한다.
596
+ */
597
+ export declare const SelectSourceSchema: z.ZodUnion<[z.ZodObject<{
598
+ /** 이 방의 멤버가 후보다. 값은 MXID 배열이고, 이름·아바타는 클라가 방 상태로 해석한다. */
599
+ kind: z.ZodLiteral<"room">;
600
+ /** 보는 사람 자신을 후보에서 뺀다(기본 false). "받을 사람"처럼 나를 고를 일이 없는 자리. */
601
+ exclude_self: z.ZodOptional<z.ZodBoolean>;
602
+ /** 후보에서 뺄 MXID 목록 — 이미 담당인 사람, 퇴사 처리 중인 계정 등. */
603
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
604
+ /** 봇·에이전트 계정도 후보에 넣는다(기본 false — 사람을 고르는 자리가 대부분이다). */
605
+ include_bots: z.ZodOptional<z.ZodBoolean>;
606
+ }, "strip", z.ZodTypeAny, {
607
+ kind: "room";
608
+ exclude_self?: boolean | undefined;
609
+ exclude?: string[] | undefined;
610
+ include_bots?: boolean | undefined;
611
+ }, {
612
+ kind: "room";
613
+ exclude_self?: boolean | undefined;
614
+ exclude?: string[] | undefined;
615
+ include_bots?: boolean | undefined;
616
+ }>, z.ZodObject<{
617
+ /** 타이핑할 때마다 서버에 묻는다 — 답은 `org.corp.ui.action.result` 의 `kind: "options"`. */
618
+ kind: z.ZodLiteral<"query">;
619
+ /**
620
+ * 질의를 받을 액션. 클라는 `action_type: "query"` 로 `{ q, name }` 을 실어 보낸다.
621
+ * 🔴 사람이 누른 게 아니므로 앱은 **부작용 없이** `ctx.result({ kind: "options", name, options })`
622
+ * 로만 답해야 한다(같은 핸들러가 제출도 처리한다면 `action_type` 으로 갈라야 한다).
623
+ */
624
+ action_id: z.ZodString;
625
+ /** 몇 글자부터 묻나(기본 1). 한 글자에 전체 스캔이 도는 백엔드라면 올린다. */
626
+ min_chars: z.ZodOptional<z.ZodNumber>;
627
+ /** 타이핑이 멎고 몇 ms 뒤에 묻나(기본 300). */
628
+ debounce_ms: z.ZodOptional<z.ZodNumber>;
629
+ }, "strip", z.ZodTypeAny, {
630
+ kind: "query";
631
+ action_id: string;
632
+ min_chars?: number | undefined;
633
+ debounce_ms?: number | undefined;
634
+ }, {
635
+ kind: "query";
636
+ action_id: string;
637
+ min_chars?: number | undefined;
638
+ debounce_ms?: number | undefined;
639
+ }>]>;
640
+ export type SelectSource = z.infer<typeof SelectSourceSchema>;
641
+ /**
642
+ * **하나의 선택 모델**(감사 문서 B) — "후보 집합에서 N 개를 고른다"는 일 하나가 세 축으로 선다:
643
+ * 공급원(`source`) × 개수(`multi`·`min`·`max`) × 표현(`style`·`searchable`).
644
+ *
645
+ * 축이 직교라서 사람 선택도, 검색도, "더 보기"도 **새 블록이 아니라 축의 값**이다. 배치 판정
646
+ * (네이티브냐 콤보박스냐, 칩이냐)은 작성자가 아니라 렌더러가 한다 —
647
+ * `spec-renderer/chooseModel.ts` 의 `choosePlan` 이 그 판정표를 한 자리에서 갖는다.
648
+ */
371
649
  export declare const SelectBlockSchema: z.ZodObject<{
372
650
  type: z.ZodLiteral<"select">;
373
651
  name: z.ZodString;
374
652
  label: z.ZodOptional<z.ZodString>;
375
653
  placeholder: z.ZodOptional<z.ZodString>;
654
+ /**
655
+ * 후보 목록. `ref`(0.8.0)를 주면 렌더러가 행을 칩(아바타·이름·MXID)으로 그린다 —
656
+ * 🔴 `label` 은 평문 사본으로 남긴다(RefSchema 머리말).
657
+ * `hint`(0.9.0)는 라벨 아래 한 줄 보조 설명 — `radio` 의 같은 이름 키와 같은 뜻이다.
658
+ */
376
659
  options: z.ZodArray<z.ZodObject<{
377
660
  value: z.ZodString;
378
661
  label: z.ZodString;
662
+ hint: z.ZodOptional<z.ZodString>;
663
+ ref: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
664
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
665
+ user: z.ZodString;
666
+ }, "strip", z.ZodTypeAny, {
667
+ user: string;
668
+ }, {
669
+ user: string;
670
+ }>, z.ZodObject<{
671
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
672
+ entity: z.ZodObject<{
673
+ type: z.ZodString;
674
+ id: z.ZodString;
675
+ }, "strip", z.ZodTypeAny, {
676
+ type: string;
677
+ id: string;
678
+ }, {
679
+ type: string;
680
+ id: string;
681
+ }>;
682
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
683
+ url: z.ZodOptional<z.ZodString>;
684
+ }, "strip", z.ZodTypeAny, {
685
+ entity: {
686
+ type: string;
687
+ id: string;
688
+ };
689
+ url?: string | undefined;
690
+ }, {
691
+ entity: {
692
+ type: string;
693
+ id: string;
694
+ };
695
+ url?: string | undefined;
696
+ }>]>>;
379
697
  }, "strip", z.ZodTypeAny, {
380
698
  value: string;
381
699
  label: string;
700
+ ref?: {
701
+ user: string;
702
+ } | {
703
+ entity: {
704
+ type: string;
705
+ id: string;
706
+ };
707
+ url?: string | undefined;
708
+ } | undefined;
709
+ hint?: string | undefined;
382
710
  }, {
383
711
  value: string;
384
712
  label: string;
713
+ ref?: {
714
+ user: string;
715
+ } | {
716
+ entity: {
717
+ type: string;
718
+ id: string;
719
+ };
720
+ url?: string | undefined;
721
+ } | undefined;
722
+ hint?: string | undefined;
385
723
  }>, "many">;
386
724
  value: z.ZodOptional<z.ZodString>;
387
725
  multi: z.ZodOptional<z.ZodBoolean>;
726
+ /** 후보가 어디서 오나 (0.9.0). 생략 = `options` 배열. 위 `SelectSourceSchema` 머리말 참조. */
727
+ source: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
728
+ /** 이 방의 멤버가 후보다. 값은 MXID 배열이고, 이름·아바타는 클라가 방 상태로 해석한다. */
729
+ kind: z.ZodLiteral<"room">;
730
+ /** 보는 사람 자신을 후보에서 뺀다(기본 false). "받을 사람"처럼 나를 고를 일이 없는 자리. */
731
+ exclude_self: z.ZodOptional<z.ZodBoolean>;
732
+ /** 후보에서 뺄 MXID 목록 — 이미 담당인 사람, 퇴사 처리 중인 계정 등. */
733
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
734
+ /** 봇·에이전트 계정도 후보에 넣는다(기본 false — 사람을 고르는 자리가 대부분이다). */
735
+ include_bots: z.ZodOptional<z.ZodBoolean>;
736
+ }, "strip", z.ZodTypeAny, {
737
+ kind: "room";
738
+ exclude_self?: boolean | undefined;
739
+ exclude?: string[] | undefined;
740
+ include_bots?: boolean | undefined;
741
+ }, {
742
+ kind: "room";
743
+ exclude_self?: boolean | undefined;
744
+ exclude?: string[] | undefined;
745
+ include_bots?: boolean | undefined;
746
+ }>, z.ZodObject<{
747
+ /** 타이핑할 때마다 서버에 묻는다 — 답은 `org.corp.ui.action.result` 의 `kind: "options"`. */
748
+ kind: z.ZodLiteral<"query">;
749
+ /**
750
+ * 질의를 받을 액션. 클라는 `action_type: "query"` 로 `{ q, name }` 을 실어 보낸다.
751
+ * 🔴 사람이 누른 게 아니므로 앱은 **부작용 없이** `ctx.result({ kind: "options", name, options })`
752
+ * 로만 답해야 한다(같은 핸들러가 제출도 처리한다면 `action_type` 으로 갈라야 한다).
753
+ */
754
+ action_id: z.ZodString;
755
+ /** 몇 글자부터 묻나(기본 1). 한 글자에 전체 스캔이 도는 백엔드라면 올린다. */
756
+ min_chars: z.ZodOptional<z.ZodNumber>;
757
+ /** 타이핑이 멎고 몇 ms 뒤에 묻나(기본 300). */
758
+ debounce_ms: z.ZodOptional<z.ZodNumber>;
759
+ }, "strip", z.ZodTypeAny, {
760
+ kind: "query";
761
+ action_id: string;
762
+ min_chars?: number | undefined;
763
+ debounce_ms?: number | undefined;
764
+ }, {
765
+ kind: "query";
766
+ action_id: string;
767
+ min_chars?: number | undefined;
768
+ debounce_ms?: number | undefined;
769
+ }>]>>;
770
+ /**
771
+ * 표현 힌트 (0.9.0) — **능력이 아니라 룩이다.** 생략하면 렌더러가 후보 수·`multi`·`source` 로 고른다.
772
+ * · `list`/`segmented` — `radio` 의 같은 이름 표현과 **같은 뜻**(펼친 목록 / 한 줄 세그먼트).
773
+ * `multi` 와 같이 쓰면 그릴 수 있는 컨트롤이 없어 칩 콤보박스로 떨어진다.
774
+ * · `dropdown` — 트리거 + 떠 있는 목록(콤보박스). 네이티브 `<select>` 가 아니다.
775
+ * · `chips` — 고른 것이 트리거 안에서 칩으로 선다(`multi` 의 기본 표현).
776
+ */
777
+ style: z.ZodOptional<z.ZodEnum<["list", "segmented", "dropdown", "chips"]>>;
778
+ /**
779
+ * 목록 안 검색창 (0.9.0). 생략하면 렌더러가 켠다 — 후보가 8 개를 넘거나, 공급원이 방/질의일 때.
780
+ * 🔴 이건 "검색하기 **버튼**"이 아니다. 타이핑이 곧 필터이고, 왕복은 `source: query` 일 때만 돈다.
781
+ */
782
+ searchable: z.ZodOptional<z.ZodBoolean>;
783
+ /** 고르지 않으면 제출을 잠근다 (0.7.0). 🔴 UX 다, 진실은 서버. */
784
+ required: z.ZodOptional<z.ZodBoolean>;
785
+ /**
786
+ * `multi: true` 전용 — **고른 개수**의 하한/상한 (0.7.0). 단일 선택에선 무시한다.
787
+ * (`input` 의 `min`/`max` 는 값의 크기라 문자열인데, 여기는 개수라 정수다.)
788
+ * 🔴 UX 다, 진실은 서버.
789
+ */
790
+ min: z.ZodOptional<z.ZodNumber>;
791
+ max: z.ZodOptional<z.ZodNumber>;
792
+ /** 제약 위반 시 보여 줄 작성자 소유 문장 (0.7.0). 없으면 렌더러 크롬 문구. */
793
+ error: z.ZodOptional<z.ZodString>;
388
794
  }, "strip", z.ZodTypeAny, {
389
795
  options: {
390
796
  value: string;
391
797
  label: string;
798
+ ref?: {
799
+ user: string;
800
+ } | {
801
+ entity: {
802
+ type: string;
803
+ id: string;
804
+ };
805
+ url?: string | undefined;
806
+ } | undefined;
807
+ hint?: string | undefined;
392
808
  }[];
393
809
  type: "select";
394
810
  name: string;
395
811
  value?: string | undefined;
396
812
  label?: string | undefined;
397
813
  placeholder?: string | undefined;
814
+ required?: boolean | undefined;
815
+ min?: number | undefined;
816
+ max?: number | undefined;
817
+ error?: string | undefined;
818
+ style?: "segmented" | "list" | "dropdown" | "chips" | undefined;
398
819
  multi?: boolean | undefined;
820
+ source?: {
821
+ kind: "room";
822
+ exclude_self?: boolean | undefined;
823
+ exclude?: string[] | undefined;
824
+ include_bots?: boolean | undefined;
825
+ } | {
826
+ kind: "query";
827
+ action_id: string;
828
+ min_chars?: number | undefined;
829
+ debounce_ms?: number | undefined;
830
+ } | undefined;
831
+ searchable?: boolean | undefined;
399
832
  }, {
400
833
  options: {
401
834
  value: string;
402
835
  label: string;
836
+ ref?: {
837
+ user: string;
838
+ } | {
839
+ entity: {
840
+ type: string;
841
+ id: string;
842
+ };
843
+ url?: string | undefined;
844
+ } | undefined;
845
+ hint?: string | undefined;
403
846
  }[];
404
847
  type: "select";
405
848
  name: string;
406
849
  value?: string | undefined;
407
850
  label?: string | undefined;
408
851
  placeholder?: string | undefined;
852
+ required?: boolean | undefined;
853
+ min?: number | undefined;
854
+ max?: number | undefined;
855
+ error?: string | undefined;
856
+ style?: "segmented" | "list" | "dropdown" | "chips" | undefined;
409
857
  multi?: boolean | undefined;
858
+ source?: {
859
+ kind: "room";
860
+ exclude_self?: boolean | undefined;
861
+ exclude?: string[] | undefined;
862
+ include_bots?: boolean | undefined;
863
+ } | {
864
+ kind: "query";
865
+ action_id: string;
866
+ min_chars?: number | undefined;
867
+ debounce_ms?: number | undefined;
868
+ } | undefined;
869
+ searchable?: boolean | undefined;
410
870
  }>;
871
+ export type SelectBlock = z.infer<typeof SelectBlockSchema>;
872
+ /** 후보 한 줄 — `select.options[]` 와 `action.result` 의 `options[]` 가 같은 모양을 쓴다. */
873
+ export type SelectOption = SelectBlock["options"][number];
411
874
  export declare const CheckboxBlockSchema: z.ZodObject<{
412
875
  type: z.ZodLiteral<"checkbox">;
413
876
  name: z.ZodString;
@@ -507,6 +970,36 @@ export declare const ButtonBlockSchema: z.ZodObject<{
507
970
  * 보여 줘도 안전하다(누르면 서버가 사람이 읽을 이유와 함께 거절한다).
508
971
  */
509
972
  hidden_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
973
+ /**
974
+ * `hidden_for` 의 **짝**(0.7.0) — 이 MXID 들에게만 버튼을 보인다(화이트리스트).
975
+ *
976
+ * 왜 둘 다 있나: 두 축은 아는 것이 다르다. `hidden_for` 는 "이 사람은 절대 못 누른다"를 아는 경우고
977
+ * (자기 PR 자기 승인), `visible_for` 는 "이 사람만 누를 수 있다"를 아는 경우다(현재 수신자). 후자를
978
+ * `hidden_for` 로 쓰려면 방 멤버 전원을 열거해야 하고, 그 목록은 카드를 만든 **순간**에 굳는다 —
979
+ * 나중에 들어온 사람에게 버튼이 그냥 보인다.
980
+ *
981
+ * 🔴 **둘 다 있으면 `hidden_for` 가 이긴다.** "못 누른다"가 "누를 수 있다"보다 강한 진술이라서다
982
+ * (겹치는 경우는 보통 작성자의 실수이고, 그때 안전한 쪽은 감추는 쪽이다).
983
+ * 🔴 **권한이 아니다** — `hidden_for` 와 똑같이 UX 고, 진짜 게이트는 언제나 서버다.
984
+ * 이 키를 모르는 옛 클라는 strip 하고 **전원에게** 버튼을 보인다 → 누르면 서버가 거절한다.
985
+ */
986
+ visible_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
987
+ /**
988
+ * 버튼이 잠기거나 감춰진 **이유 한 줄**(0.7.0) — 사람이 읽을 문장(작성자 소유).
989
+ * `disabled` 면 버튼 옆 보조 텍스트로, `visible_for` 로 감춰졌으면 버튼 자리에 이 줄만 남는다.
990
+ * "눌러 봐야 안다"를 없애는 것이 요점이다. 🔴 UX 다, 진실은 서버.
991
+ */
992
+ disabled_reason: z.ZodOptional<z.ZodString>;
993
+ /**
994
+ * **중요도**(0.9.0) — 배치가 아니라 의도다. `"secondary"` 는 "이건 부차적이다"라는 말이고,
995
+ * 액션 줄이 좁아 한 줄에 못 들어갈 때 렌더러가 **먼저 ⋯ 메뉴로 접는** 대상이 된다.
996
+ *
997
+ * 🔴 **`style` 과 다른 축이다.** `style` 은 *생김새*(기본/강조/위험)이고 이것은 *중요도*다 —
998
+ * `style: "danger"` 인 "보고 취소"가 부차적일 수 있다(위험하지만 주 동작은 아니다). 둘을 한
999
+ * 축으로 묶으면 그 카드를 표현할 수 없다.
1000
+ * ⚠️ 생략하면 지금과 **완전히 같다**(안 접힌다). 접기는 `"secondary"` 를 선언한 것에만 일어난다.
1001
+ */
1002
+ priority: z.ZodOptional<z.ZodEnum<["primary", "secondary"]>>;
510
1003
  }, "strip", z.ZodTypeAny, {
511
1004
  type: "button";
512
1005
  text: string;
@@ -521,6 +1014,9 @@ export declare const ButtonBlockSchema: z.ZodObject<{
521
1014
  } | undefined;
522
1015
  disabled?: boolean | undefined;
523
1016
  hidden_for?: string[] | undefined;
1017
+ visible_for?: string[] | undefined;
1018
+ disabled_reason?: string | undefined;
1019
+ priority?: "primary" | "secondary" | undefined;
524
1020
  }, {
525
1021
  type: "button";
526
1022
  text: string;
@@ -535,6 +1031,9 @@ export declare const ButtonBlockSchema: z.ZodObject<{
535
1031
  } | undefined;
536
1032
  disabled?: boolean | undefined;
537
1033
  hidden_for?: string[] | undefined;
1034
+ visible_for?: string[] | undefined;
1035
+ disabled_reason?: string | undefined;
1036
+ priority?: "primary" | "secondary" | undefined;
538
1037
  }>;
539
1038
  export type ButtonBlock = z.infer<typeof ButtonBlockSchema>;
540
1039
  /**
@@ -549,157 +1048,24 @@ export declare const LinkButtonBlockSchema: z.ZodObject<{
549
1048
  style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
550
1049
  /** 새 탭으로 열기(기본 true). */
551
1050
  external: z.ZodOptional<z.ZodBoolean>;
1051
+ /** 중요도 (0.9.0) — `ButtonBlockSchema.priority` 와 같은 뜻. 좁으면 ⋯ 로 접힌다. */
1052
+ priority: z.ZodOptional<z.ZodEnum<["primary", "secondary"]>>;
552
1053
  }, "strip", z.ZodTypeAny, {
553
1054
  type: "linkButton";
554
- text: string;
555
1055
  url: string;
1056
+ text: string;
556
1057
  style?: "danger" | "default" | "primary" | undefined;
1058
+ priority?: "primary" | "secondary" | undefined;
557
1059
  external?: boolean | undefined;
558
1060
  }, {
559
1061
  type: "linkButton";
560
- text: string;
561
1062
  url: string;
1063
+ text: string;
562
1064
  style?: "danger" | "default" | "primary" | undefined;
1065
+ priority?: "primary" | "secondary" | undefined;
563
1066
  external?: boolean | undefined;
564
1067
  }>;
565
1068
  export type LinkButtonBlock = z.infer<typeof LinkButtonBlockSchema>;
566
- /** 버튼 한 줄 묶음 — 액션 버튼(button)과 링크 버튼(linkButton)을 섞어 배치 가능. */
567
- export declare const ActionsBlockSchema: z.ZodObject<{
568
- type: z.ZodLiteral<"actions">;
569
- elements: z.ZodArray<z.ZodUnion<[z.ZodObject<{
570
- type: z.ZodLiteral<"button">;
571
- /** 어떤 액션인지 식별. 클릭 시 org.corp.ui.action.action_id 로 회신됨. */
572
- action_id: z.ZodString;
573
- text: z.ZodString;
574
- style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
575
- /** 버튼 고유 페이로드 (폼 값과 별개로 함께 전송) */
576
- value: z.ZodOptional<z.ZodString>;
577
- confirm: z.ZodOptional<z.ZodObject<{
578
- title: z.ZodString;
579
- text: z.ZodString;
580
- ok: z.ZodOptional<z.ZodString>;
581
- cancel: z.ZodOptional<z.ZodString>;
582
- }, "strip", z.ZodTypeAny, {
583
- title: string;
584
- text: string;
585
- ok?: string | undefined;
586
- cancel?: string | undefined;
587
- }, {
588
- title: string;
589
- text: string;
590
- ok?: string | undefined;
591
- cancel?: string | undefined;
592
- }>>;
593
- disabled: z.ZodOptional<z.ZodBoolean>;
594
- /**
595
- * 이 MXID 들에게는 버튼을 **감춘다**(뷰어별 어포던스).
596
- *
597
- * 왜 필요한가: 카드 한 장은 방 전체가 같이 본다. 그런데 "이 사람만 절대 못 누르는 버튼"이 있다 —
598
- * Forgejo 는 **자기 PR 자기 승인**을 422 로 거절한다(`approve your own pull is not allowed`).
599
- * 그래서 작성자에게 Approve 를 보여 주면 눌러도 실패 카드만 쌓인다. 카드 전체에서 버튼을 빼면
600
- * 남들이 승인을 못 하므로, 판정은 **보는 사람별**이어야 한다.
601
- *
602
- * 🔴 **권한이 아니다.** 진짜 게이트는 언제나 서버다(disabled/confirm 과 같은 자세) — 이건 없는
603
- * 어포던스를 안 보여 주기 위한 것뿐이다. 그래서 이 키를 모르는 옛 클라이언트가 버튼을 그대로
604
- * 보여 줘도 안전하다(누르면 서버가 사람이 읽을 이유와 함께 거절한다).
605
- */
606
- hidden_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
607
- }, "strip", z.ZodTypeAny, {
608
- type: "button";
609
- text: string;
610
- action_id: string;
611
- value?: string | undefined;
612
- style?: "danger" | "default" | "primary" | undefined;
613
- confirm?: {
614
- title: string;
615
- text: string;
616
- ok?: string | undefined;
617
- cancel?: string | undefined;
618
- } | undefined;
619
- disabled?: boolean | undefined;
620
- hidden_for?: string[] | undefined;
621
- }, {
622
- type: "button";
623
- text: string;
624
- action_id: string;
625
- value?: string | undefined;
626
- style?: "danger" | "default" | "primary" | undefined;
627
- confirm?: {
628
- title: string;
629
- text: string;
630
- ok?: string | undefined;
631
- cancel?: string | undefined;
632
- } | undefined;
633
- disabled?: boolean | undefined;
634
- hidden_for?: string[] | undefined;
635
- }>, z.ZodObject<{
636
- type: z.ZodLiteral<"linkButton">;
637
- text: z.ZodString;
638
- /** 이동할 https URL. 클라이언트가 출처를 검증(아니면 비활성 표시). */
639
- url: z.ZodString;
640
- style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
641
- /** 새 탭으로 열기(기본 true). */
642
- external: z.ZodOptional<z.ZodBoolean>;
643
- }, "strip", z.ZodTypeAny, {
644
- type: "linkButton";
645
- text: string;
646
- url: string;
647
- style?: "danger" | "default" | "primary" | undefined;
648
- external?: boolean | undefined;
649
- }, {
650
- type: "linkButton";
651
- text: string;
652
- url: string;
653
- style?: "danger" | "default" | "primary" | undefined;
654
- external?: boolean | undefined;
655
- }>]>, "many">;
656
- }, "strip", z.ZodTypeAny, {
657
- type: "actions";
658
- elements: ({
659
- type: "button";
660
- text: string;
661
- action_id: string;
662
- value?: string | undefined;
663
- style?: "danger" | "default" | "primary" | undefined;
664
- confirm?: {
665
- title: string;
666
- text: string;
667
- ok?: string | undefined;
668
- cancel?: string | undefined;
669
- } | undefined;
670
- disabled?: boolean | undefined;
671
- hidden_for?: string[] | undefined;
672
- } | {
673
- type: "linkButton";
674
- text: string;
675
- url: string;
676
- style?: "danger" | "default" | "primary" | undefined;
677
- external?: boolean | undefined;
678
- })[];
679
- }, {
680
- type: "actions";
681
- elements: ({
682
- type: "button";
683
- text: string;
684
- action_id: string;
685
- value?: string | undefined;
686
- style?: "danger" | "default" | "primary" | undefined;
687
- confirm?: {
688
- title: string;
689
- text: string;
690
- ok?: string | undefined;
691
- cancel?: string | undefined;
692
- } | undefined;
693
- disabled?: boolean | undefined;
694
- hidden_for?: string[] | undefined;
695
- } | {
696
- type: "linkButton";
697
- text: string;
698
- url: string;
699
- style?: "danger" | "default" | "primary" | undefined;
700
- external?: boolean | undefined;
701
- })[];
702
- }>;
703
1069
  /**
704
1070
  * 오버플로 메뉴 — "⋯" 트리거를 누르면 액션 항목 목록이 팝오버로 열린다(공간 절약형 액션 묶음).
705
1071
  * 각 항목은 button 과 동일하게 action_id 로 회신하고 confirm(파괴적 액션 확인)도 지원.
@@ -732,6 +1098,12 @@ export declare const OverflowBlockSchema: z.ZodObject<{
732
1098
  cancel?: string | undefined;
733
1099
  }>>;
734
1100
  disabled: z.ZodOptional<z.ZodBoolean>;
1101
+ /** 이 MXID 들에게만 항목을 보인다 (0.7.0) — `ButtonBlockSchema.visible_for` 와 같은 규칙. 🔴 UX 다, 진실은 서버. */
1102
+ visible_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1103
+ /** 이 MXID 들에게 항목을 감춘다 (0.7.0) — 둘 다 있으면 이쪽이 이긴다(버튼과 같은 규칙). */
1104
+ hidden_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1105
+ /** 잠기거나 감춰진 이유 한 줄 (0.7.0, 작성자 소유 문장). 🔴 UX 다, 진실은 서버. */
1106
+ disabled_reason: z.ZodOptional<z.ZodString>;
735
1107
  }, "strip", z.ZodTypeAny, {
736
1108
  text: string;
737
1109
  action_id: string;
@@ -744,6 +1116,9 @@ export declare const OverflowBlockSchema: z.ZodObject<{
744
1116
  cancel?: string | undefined;
745
1117
  } | undefined;
746
1118
  disabled?: boolean | undefined;
1119
+ hidden_for?: string[] | undefined;
1120
+ visible_for?: string[] | undefined;
1121
+ disabled_reason?: string | undefined;
747
1122
  }, {
748
1123
  text: string;
749
1124
  action_id: string;
@@ -756,6 +1131,9 @@ export declare const OverflowBlockSchema: z.ZodObject<{
756
1131
  cancel?: string | undefined;
757
1132
  } | undefined;
758
1133
  disabled?: boolean | undefined;
1134
+ hidden_for?: string[] | undefined;
1135
+ visible_for?: string[] | undefined;
1136
+ disabled_reason?: string | undefined;
759
1137
  }>, "many">;
760
1138
  }, "strip", z.ZodTypeAny, {
761
1139
  type: "overflow";
@@ -771,6 +1149,9 @@ export declare const OverflowBlockSchema: z.ZodObject<{
771
1149
  cancel?: string | undefined;
772
1150
  } | undefined;
773
1151
  disabled?: boolean | undefined;
1152
+ hidden_for?: string[] | undefined;
1153
+ visible_for?: string[] | undefined;
1154
+ disabled_reason?: string | undefined;
774
1155
  }[];
775
1156
  label?: string | undefined;
776
1157
  }, {
@@ -787,10 +1168,45 @@ export declare const OverflowBlockSchema: z.ZodObject<{
787
1168
  cancel?: string | undefined;
788
1169
  } | undefined;
789
1170
  disabled?: boolean | undefined;
1171
+ hidden_for?: string[] | undefined;
1172
+ visible_for?: string[] | undefined;
1173
+ disabled_reason?: string | undefined;
790
1174
  }[];
791
1175
  label?: string | undefined;
792
1176
  }>;
793
1177
  export type OverflowBlock = z.infer<typeof OverflowBlockSchema>;
1178
+ /**
1179
+ * **액션 줄의 원소**(0.9.0 부터 셋) — 버튼 · 링크 버튼 · ⋯ 메뉴.
1180
+ *
1181
+ * 🔴 `overflow` 가 여기 들어온 이유는 배치다(감사 문서 D). 최상위 블록으로만 둘 수 있던 시절엔
1182
+ * 세로 flex 인 `.cob-blocks` 안에서 **제 줄을 통째로 먹었다** — 버튼 넷 아래에 ⋯ 하나가 두 번째
1183
+ * 줄에 혼자 서는 모양이다. 액션 줄 안으로 들어오면 그 줄의 끝에 선다.
1184
+ *
1185
+ * ⚠️ **옛 클라에는 이 원소가 안 보인다.** 유니온이 닫혀 있어 모르는 원소 하나가 배열 전체를
1186
+ * 실패시키고 → `dropUnknownBlocks` 가 그 **actions 블록을 통째로** 떨군다(0.9.0 의
1187
+ * `dropUnknownBlocks` 는 원소 단위로 거르지만 그건 *새* 클라 이야기다). 그래서 빌더
1188
+ * (`card.actions`)가 전환기 동안 **최상위 `overflow` 사본**을 같이 낸다 — `card.activity` 의
1189
+ * `legacy_for` 와 같은 규약이고, 새 렌더러는 사본을 알아보고 건너뛴다.
1190
+ */
1191
+ /**
1192
+ * 🔴 **타입을 손으로 적고 스키마에 주석을 단다** — `z.infer` 로 두면 TS 가 이 유니온을 통째로
1193
+ * 펼치는데, `overflow` 가 들어오면서 그 펼친 타입이 `surfaces.ts` 의 `AppSurfaceContentSchema`
1194
+ * (패널 → 서피스 바디 → 카드 → 블록 → 액션)까지 타고 올라가 **직렬화 한도를 넘는다**(TS7056).
1195
+ * 주석 한 줄이 그 자리에서 추론을 끊는다. 값의 모양은 그대로다.
1196
+ */
1197
+ export type ActionElement = ButtonBlock | LinkButtonBlock | OverflowBlock;
1198
+ export declare const ActionElementSchema: z.ZodType<ActionElement>;
1199
+ /** 버튼 한 줄 묶음 — 액션 버튼(button)·링크 버튼(linkButton)·⋯ 메뉴(overflow)를 섞어 배치 가능. */
1200
+ export declare const ActionsBlockSchema: z.ZodObject<{
1201
+ type: z.ZodLiteral<"actions">;
1202
+ elements: z.ZodArray<z.ZodType<ActionElement, z.ZodTypeDef, ActionElement>, "many">;
1203
+ }, "strip", z.ZodTypeAny, {
1204
+ type: "actions";
1205
+ elements: ActionElement[];
1206
+ }, {
1207
+ type: "actions";
1208
+ elements: ActionElement[];
1209
+ }>;
794
1210
  /**
795
1211
  * 진행률 바 (0~100). 에이전트가 m.replace 편집으로 갱신해 "스트리밍" 진행 표시 가능.
796
1212
  *
@@ -822,25 +1238,25 @@ export declare const StepsBlockSchema: z.ZodObject<{
822
1238
  note: z.ZodOptional<z.ZodString>;
823
1239
  }, "strip", z.ZodTypeAny, {
824
1240
  label: string;
825
- status?: "done" | "active" | "todo" | "error" | undefined;
1241
+ status?: "error" | "done" | "active" | "todo" | undefined;
826
1242
  note?: string | undefined;
827
1243
  }, {
828
1244
  label: string;
829
- status?: "done" | "active" | "todo" | "error" | undefined;
1245
+ status?: "error" | "done" | "active" | "todo" | undefined;
830
1246
  note?: string | undefined;
831
1247
  }>, "many">;
832
1248
  }, "strip", z.ZodTypeAny, {
833
1249
  type: "steps";
834
1250
  items: {
835
1251
  label: string;
836
- status?: "done" | "active" | "todo" | "error" | undefined;
1252
+ status?: "error" | "done" | "active" | "todo" | undefined;
837
1253
  note?: string | undefined;
838
1254
  }[];
839
1255
  }, {
840
1256
  type: "steps";
841
1257
  items: {
842
1258
  label: string;
843
- status?: "done" | "active" | "todo" | "error" | undefined;
1259
+ status?: "error" | "done" | "active" | "todo" | undefined;
844
1260
  note?: string | undefined;
845
1261
  }[];
846
1262
  }>;
@@ -1017,12 +1433,60 @@ export declare const AvatarBlockSchema: z.ZodObject<{
1017
1433
  initials: z.ZodOptional<z.ZodString>;
1018
1434
  src: z.ZodOptional<z.ZodString>;
1019
1435
  subtitle: z.ZodOptional<z.ZodString>;
1436
+ /**
1437
+ * 이 아바타가 가리키는 사람/엔티티 (0.8.0). 있으면 렌더러가 해석 결과(이름·사진)로 `name`/`src` 를
1438
+ * **덮어쓴다** — 방 상태가 정답이라 개명·프로필 변경이 즉시 반영된다.
1439
+ * 🔴 `name` 은 평문 사본으로 남긴다: 해석기가 없거나(외부 임베더) 옛 클라면 그 문자열이 유일한 답이다.
1440
+ */
1441
+ ref: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
1442
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
1443
+ user: z.ZodString;
1444
+ }, "strip", z.ZodTypeAny, {
1445
+ user: string;
1446
+ }, {
1447
+ user: string;
1448
+ }>, z.ZodObject<{
1449
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
1450
+ entity: z.ZodObject<{
1451
+ type: z.ZodString;
1452
+ id: z.ZodString;
1453
+ }, "strip", z.ZodTypeAny, {
1454
+ type: string;
1455
+ id: string;
1456
+ }, {
1457
+ type: string;
1458
+ id: string;
1459
+ }>;
1460
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
1461
+ url: z.ZodOptional<z.ZodString>;
1462
+ }, "strip", z.ZodTypeAny, {
1463
+ entity: {
1464
+ type: string;
1465
+ id: string;
1466
+ };
1467
+ url?: string | undefined;
1468
+ }, {
1469
+ entity: {
1470
+ type: string;
1471
+ id: string;
1472
+ };
1473
+ url?: string | undefined;
1474
+ }>]>>;
1020
1475
  /** 우하단 상태점 — 네 상태가 각자 색을 갖는다(`--cob-color-presence-*`). 색만으로 안 나르도록 `aria-label` 이 상태를 병기한다. */
1021
1476
  status: z.ZodOptional<z.ZodEnum<["online", "away", "busy", "offline"]>>;
1022
1477
  }, "strip", z.ZodTypeAny, {
1023
1478
  type: "avatar";
1024
1479
  name: string;
1025
1480
  status?: "online" | "away" | "busy" | "offline" | undefined;
1481
+ ref?: {
1482
+ user: string;
1483
+ } | {
1484
+ entity: {
1485
+ type: string;
1486
+ id: string;
1487
+ };
1488
+ url?: string | undefined;
1489
+ } | undefined;
1026
1490
  initials?: string | undefined;
1027
1491
  src?: string | undefined;
1028
1492
  subtitle?: string | undefined;
@@ -1030,6 +1494,15 @@ export declare const AvatarBlockSchema: z.ZodObject<{
1030
1494
  type: "avatar";
1031
1495
  name: string;
1032
1496
  status?: "online" | "away" | "busy" | "offline" | undefined;
1497
+ ref?: {
1498
+ user: string;
1499
+ } | {
1500
+ entity: {
1501
+ type: string;
1502
+ id: string;
1503
+ };
1504
+ url?: string | undefined;
1505
+ } | undefined;
1033
1506
  initials?: string | undefined;
1034
1507
  src?: string | undefined;
1035
1508
  subtitle?: string | undefined;
@@ -1163,15 +1636,15 @@ export declare const EntityRefBlockSchema: z.ZodObject<{
1163
1636
  }, "strip", z.ZodTypeAny, {
1164
1637
  type: "entityRef";
1165
1638
  label: string;
1166
- tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1167
- url?: string | undefined;
1168
1639
  entity?: string | undefined;
1640
+ url?: string | undefined;
1641
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1169
1642
  }, {
1170
1643
  type: "entityRef";
1171
1644
  label: string;
1172
- tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1173
- url?: string | undefined;
1174
1645
  entity?: string | undefined;
1646
+ url?: string | undefined;
1647
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1175
1648
  }>;
1176
1649
  export type EntityRefBlock = z.infer<typeof EntityRefBlockSchema>;
1177
1650
  /**
@@ -1202,8 +1675,8 @@ export declare const KanbanBlockSchema: z.ZodObject<{
1202
1675
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1203
1676
  }>>;
1204
1677
  }, "strip", z.ZodTypeAny, {
1205
- title: string;
1206
1678
  id: string;
1679
+ title: string;
1207
1680
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1208
1681
  badge?: {
1209
1682
  label: string;
@@ -1211,8 +1684,8 @@ export declare const KanbanBlockSchema: z.ZodObject<{
1211
1684
  } | undefined;
1212
1685
  meta?: string[] | undefined;
1213
1686
  }, {
1214
- title: string;
1215
1687
  id: string;
1688
+ title: string;
1216
1689
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1217
1690
  badge?: {
1218
1691
  label: string;
@@ -1221,10 +1694,11 @@ export declare const KanbanBlockSchema: z.ZodObject<{
1221
1694
  meta?: string[] | undefined;
1222
1695
  }>, "many">;
1223
1696
  }, "strip", z.ZodTypeAny, {
1697
+ id: string;
1224
1698
  title: string;
1225
1699
  cards: {
1226
- title: string;
1227
1700
  id: string;
1701
+ title: string;
1228
1702
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1229
1703
  badge?: {
1230
1704
  label: string;
@@ -1232,13 +1706,13 @@ export declare const KanbanBlockSchema: z.ZodObject<{
1232
1706
  } | undefined;
1233
1707
  meta?: string[] | undefined;
1234
1708
  }[];
1235
- id: string;
1236
1709
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1237
1710
  }, {
1711
+ id: string;
1238
1712
  title: string;
1239
1713
  cards: {
1240
- title: string;
1241
1714
  id: string;
1715
+ title: string;
1242
1716
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1243
1717
  badge?: {
1244
1718
  label: string;
@@ -1246,17 +1720,17 @@ export declare const KanbanBlockSchema: z.ZodObject<{
1246
1720
  } | undefined;
1247
1721
  meta?: string[] | undefined;
1248
1722
  }[];
1249
- id: string;
1250
1723
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1251
1724
  }>, "many">;
1252
1725
  caption: z.ZodOptional<z.ZodString>;
1253
1726
  }, "strip", z.ZodTypeAny, {
1254
1727
  type: "kanban";
1255
1728
  columns: {
1729
+ id: string;
1256
1730
  title: string;
1257
1731
  cards: {
1258
- title: string;
1259
1732
  id: string;
1733
+ title: string;
1260
1734
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1261
1735
  badge?: {
1262
1736
  label: string;
@@ -1264,17 +1738,17 @@ export declare const KanbanBlockSchema: z.ZodObject<{
1264
1738
  } | undefined;
1265
1739
  meta?: string[] | undefined;
1266
1740
  }[];
1267
- id: string;
1268
1741
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1269
1742
  }[];
1270
1743
  caption?: string | undefined;
1271
1744
  }, {
1272
1745
  type: "kanban";
1273
1746
  columns: {
1747
+ id: string;
1274
1748
  title: string;
1275
1749
  cards: {
1276
- title: string;
1277
1750
  id: string;
1751
+ title: string;
1278
1752
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1279
1753
  badge?: {
1280
1754
  label: string;
@@ -1282,7 +1756,6 @@ export declare const KanbanBlockSchema: z.ZodObject<{
1282
1756
  } | undefined;
1283
1757
  meta?: string[] | undefined;
1284
1758
  }[];
1285
- id: string;
1286
1759
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1287
1760
  }[];
1288
1761
  caption?: string | undefined;
@@ -1327,6 +1800,27 @@ export declare const CollapsibleBlockSchema: z.ZodObject<{
1327
1800
  /** 처음부터 펼쳐둘지(기본 접힘). */
1328
1801
  open: z.ZodOptional<z.ZodBoolean>;
1329
1802
  tone: z.ZodOptional<z.ZodEnum<["neutral", "success", "warning", "danger", "info"]>>;
1803
+ /**
1804
+ * **옛 클라용 사본이라는 표식**(0.8.0). 빌더가 새 블록을 낼 때 같은 내용을 이 접기 블록으로 병기하고
1805
+ * 여기에 원본 블록 타입을 적는다.
1806
+ *
1807
+ * 왜 필요한가: 새 *블록 타입*은 `dropUnknownBlocks` 에서 **통째로 떨어진다**(키 추가와 달리 degrade
1808
+ * 경로가 없다). 그래서 `activity` 는 빌더가 사본을 같이 내고, **새 렌더러는 원본을 아니까 사본을
1809
+ * 안 그린다** — 안 그러면 새 클라에서 같은 이력이 두 번 보인다.
1810
+ * 이 키를 모르는 옛 클라는 strip 하고 평범한 접기 블록으로 그린다(그게 목적이다).
1811
+ *
1812
+ * 전환기가 끝나 클라 배포가 충분히 퍼지면 빌더의 `legacy` 기본값을 false 로 바꾼다(이 시리즈 밖).
1813
+ */
1814
+ legacy_for: z.ZodOptional<z.ZodEnum<["activity"]>>;
1815
+ /**
1816
+ * **접힌 채로도 보이는 한 줄**(0.9.0) — 제목 오른쪽에 흐리게 선다. 펼치면 숨는다(본문이 답이다).
1817
+ *
1818
+ * 왜 필요한가(감사 문서 D): 접기는 "카드 높이를 안 먹는 상세"인데, 지금은 접힌 상태에서 **정보가
1819
+ * 0** 이라 사용자가 펼쳐 봐야 안에 뭐가 있는지 안다. 마지막 한 줄만 보여 주면 대개 펼칠 필요가 없다
1820
+ * ("마지막: 희태 박에게 전달 · 6:12").
1821
+ * ⚠️ 본문의 요약이지 본문의 **대체**가 아니다 — 여기만 읽고 끝나도 되는 내용이면 접지 말 것.
1822
+ */
1823
+ summary: z.ZodOptional<z.ZodString>;
1330
1824
  /**
1331
1825
  * 펼치면 보이는 중첩 블록(재귀). 런타임은 z.lazy 로 BlockSchema 를 지연 참조해 재귀 검증하지만,
1332
1826
  * 정적 타입은 z.ZodTypeAny 로 끊는다 — Block 이 z.infer 기반이라 재귀 타입 별칭이 conditional type
@@ -1339,20 +1833,220 @@ export declare const CollapsibleBlockSchema: z.ZodObject<{
1339
1833
  blocks: any[];
1340
1834
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1341
1835
  open?: boolean | undefined;
1836
+ legacy_for?: "activity" | undefined;
1837
+ summary?: string | undefined;
1342
1838
  }, {
1343
1839
  type: "collapsible";
1344
1840
  title: string;
1345
1841
  blocks: any[];
1346
1842
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1347
1843
  open?: boolean | undefined;
1844
+ legacy_for?: "activity" | undefined;
1845
+ summary?: string | undefined;
1348
1846
  }>;
1349
1847
  export type CollapsibleBlock = {
1350
1848
  type: "collapsible";
1351
1849
  title: string;
1352
1850
  open?: boolean;
1353
1851
  tone?: Tone;
1852
+ legacy_for?: "activity";
1853
+ summary?: string;
1354
1854
  blocks: Block[];
1355
1855
  };
1856
+ /**
1857
+ * **처리 이력**(0.8.0) — 참조가 주어인 시간순 목록. 이 시리즈의 **유일한 새 블록**이다.
1858
+ *
1859
+ * 왜 블록인가(감사 문서 C): "누가 · 무엇을 · 언제"는 지금 `collapsible` 안의 마크다운 텍스트로 산다.
1860
+ * 그래서 접힌 상태에선 정보가 0이고, 펼쳐도 사람·시각에 구조가 없어 아바타도 상대 시각도 못 붙는다.
1861
+ * 기존 블록의 새 축으로는 표현할 수 없는 모양이라("주어가 참조인 행의 목록") 블록이 정당하다.
1862
+ *
1863
+ * 🔴 **새 블록은 `dropUnknownBlocks` 에서 통째로 떨어진다** — 키 추가와 달리 degrade 경로가 없다.
1864
+ * 그래서 빌더(`card.activity`)가 옛 클라용 `collapsible` 사본을 **같이** 낸다(`legacy_for: "activity"`).
1865
+ *
1866
+ * 항목은 **최신순**이다(맨 앞이 가장 최근). `maxVisible` 을 넘는 나머지는 렌더러가 접는다.
1867
+ */
1868
+ export declare const ActivityBlockSchema: z.ZodObject<{
1869
+ type: z.ZodLiteral<"activity">;
1870
+ label: z.ZodOptional<z.ZodString>;
1871
+ /** 펼쳐 둘 최근 항목 수(기본 3). 나머지는 "이전 N건 더 보기"로 접힌다. */
1872
+ maxVisible: z.ZodOptional<z.ZodNumber>;
1873
+ items: z.ZodArray<z.ZodObject<{
1874
+ /** 행위의 주어 — 참조면 아바타·이름으로, 문자열이면 그대로. */
1875
+ who: z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodObject<{
1876
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
1877
+ user: z.ZodString;
1878
+ }, "strip", z.ZodTypeAny, {
1879
+ user: string;
1880
+ }, {
1881
+ user: string;
1882
+ }>, z.ZodObject<{
1883
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
1884
+ entity: z.ZodObject<{
1885
+ type: z.ZodString;
1886
+ id: z.ZodString;
1887
+ }, "strip", z.ZodTypeAny, {
1888
+ type: string;
1889
+ id: string;
1890
+ }, {
1891
+ type: string;
1892
+ id: string;
1893
+ }>;
1894
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
1895
+ url: z.ZodOptional<z.ZodString>;
1896
+ }, "strip", z.ZodTypeAny, {
1897
+ entity: {
1898
+ type: string;
1899
+ id: string;
1900
+ };
1901
+ url?: string | undefined;
1902
+ }, {
1903
+ entity: {
1904
+ type: string;
1905
+ id: string;
1906
+ };
1907
+ url?: string | undefined;
1908
+ }>]>]>;
1909
+ /** 무엇을 했나 — 인라인 마크다운 허용(`text` 블록의 인라인 규칙과 같다). */
1910
+ what: z.ZodString;
1911
+ /** 언제 — ISO 8601 타임스탬프 문자열. 렌더러가 상대 시각으로 그린다. */
1912
+ at: z.ZodString;
1913
+ tone: z.ZodOptional<z.ZodEnum<["neutral", "success", "warning", "danger", "info"]>>;
1914
+ /** 대상(선택) — "A 가 **B 에게** 전달" 의 B. */
1915
+ to: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodObject<{
1916
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
1917
+ user: z.ZodString;
1918
+ }, "strip", z.ZodTypeAny, {
1919
+ user: string;
1920
+ }, {
1921
+ user: string;
1922
+ }>, z.ZodObject<{
1923
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
1924
+ entity: z.ZodObject<{
1925
+ type: z.ZodString;
1926
+ id: z.ZodString;
1927
+ }, "strip", z.ZodTypeAny, {
1928
+ type: string;
1929
+ id: string;
1930
+ }, {
1931
+ type: string;
1932
+ id: string;
1933
+ }>;
1934
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
1935
+ url: z.ZodOptional<z.ZodString>;
1936
+ }, "strip", z.ZodTypeAny, {
1937
+ entity: {
1938
+ type: string;
1939
+ id: string;
1940
+ };
1941
+ url?: string | undefined;
1942
+ }, {
1943
+ entity: {
1944
+ type: string;
1945
+ id: string;
1946
+ };
1947
+ url?: string | undefined;
1948
+ }>]>]>>;
1949
+ }, "strip", z.ZodTypeAny, {
1950
+ at: string;
1951
+ who: string | {
1952
+ user: string;
1953
+ } | {
1954
+ entity: {
1955
+ type: string;
1956
+ id: string;
1957
+ };
1958
+ url?: string | undefined;
1959
+ };
1960
+ what: string;
1961
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1962
+ to?: string | {
1963
+ user: string;
1964
+ } | {
1965
+ entity: {
1966
+ type: string;
1967
+ id: string;
1968
+ };
1969
+ url?: string | undefined;
1970
+ } | undefined;
1971
+ }, {
1972
+ at: string;
1973
+ who: string | {
1974
+ user: string;
1975
+ } | {
1976
+ entity: {
1977
+ type: string;
1978
+ id: string;
1979
+ };
1980
+ url?: string | undefined;
1981
+ };
1982
+ what: string;
1983
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1984
+ to?: string | {
1985
+ user: string;
1986
+ } | {
1987
+ entity: {
1988
+ type: string;
1989
+ id: string;
1990
+ };
1991
+ url?: string | undefined;
1992
+ } | undefined;
1993
+ }>, "many">;
1994
+ }, "strip", z.ZodTypeAny, {
1995
+ type: "activity";
1996
+ items: {
1997
+ at: string;
1998
+ who: string | {
1999
+ user: string;
2000
+ } | {
2001
+ entity: {
2002
+ type: string;
2003
+ id: string;
2004
+ };
2005
+ url?: string | undefined;
2006
+ };
2007
+ what: string;
2008
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2009
+ to?: string | {
2010
+ user: string;
2011
+ } | {
2012
+ entity: {
2013
+ type: string;
2014
+ id: string;
2015
+ };
2016
+ url?: string | undefined;
2017
+ } | undefined;
2018
+ }[];
2019
+ label?: string | undefined;
2020
+ maxVisible?: number | undefined;
2021
+ }, {
2022
+ type: "activity";
2023
+ items: {
2024
+ at: string;
2025
+ who: string | {
2026
+ user: string;
2027
+ } | {
2028
+ entity: {
2029
+ type: string;
2030
+ id: string;
2031
+ };
2032
+ url?: string | undefined;
2033
+ };
2034
+ what: string;
2035
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2036
+ to?: string | {
2037
+ user: string;
2038
+ } | {
2039
+ entity: {
2040
+ type: string;
2041
+ id: string;
2042
+ };
2043
+ url?: string | undefined;
2044
+ } | undefined;
2045
+ }[];
2046
+ label?: string | undefined;
2047
+ maxVisible?: number | undefined;
2048
+ }>;
2049
+ export type ActivityBlock = z.infer<typeof ActivityBlockSchema>;
1356
2050
  /**
1357
2051
  * 탈출구(escape hatch): A2UI/UI Blocks로 표현하기 어려운 무거운 UI(차트·대형 그리드·지도)는
1358
2052
  * Matrix Widget으로. 클라이언트가 신뢰 경계 안에서 sandboxed iframe으로 렌더한다.
@@ -1449,6 +2143,54 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1449
2143
  text: string;
1450
2144
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1451
2145
  }>, "many">>;
2146
+ /**
2147
+ * 이 값이 가리키는 사람/엔티티 (0.8.0). 있으면 렌더러가 칩(아바타+이름 / 종류+라벨)으로 그린다.
2148
+ * 🔴 **`value` 는 평문 사본으로 남긴다** — `parts` 와 같은 규칙이다(RefSchema 머리말).
2149
+ */
2150
+ ref: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
2151
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
2152
+ user: z.ZodString;
2153
+ }, "strip", z.ZodTypeAny, {
2154
+ user: string;
2155
+ }, {
2156
+ user: string;
2157
+ }>, z.ZodObject<{
2158
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
2159
+ entity: z.ZodObject<{
2160
+ type: z.ZodString;
2161
+ id: z.ZodString;
2162
+ }, "strip", z.ZodTypeAny, {
2163
+ type: string;
2164
+ id: string;
2165
+ }, {
2166
+ type: string;
2167
+ id: string;
2168
+ }>;
2169
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
2170
+ url: z.ZodOptional<z.ZodString>;
2171
+ }, "strip", z.ZodTypeAny, {
2172
+ entity: {
2173
+ type: string;
2174
+ id: string;
2175
+ };
2176
+ url?: string | undefined;
2177
+ }, {
2178
+ entity: {
2179
+ type: string;
2180
+ id: string;
2181
+ };
2182
+ url?: string | undefined;
2183
+ }>]>>;
2184
+ /**
2185
+ * **이 항목은 문단이다**(0.9.0) — 값이 아니라 본문. 전체폭으로 서고 값 서체(600)를 풀며
2186
+ * 인라인 마크다운을 그린다.
2187
+ *
2188
+ * 왜 필요한가(감사 문서 D): "막힌 일: ㅁㄴㄹ…" 같은 자유 서술이 지금은 굵은 값 서체로 서서
2189
+ * 숫자·상태와 같은 무게로 읽힌다. 작성자가 `short` 로 열 수를 강제하던 것과 같은 자리 —
2190
+ * 작성자는 "이건 문단이다"만 말하고 폭·서체는 렌더러가 정한다.
2191
+ * ⚠️ `short` 와 같이 주면 `long` 이 이긴다(반폭 문단은 없다).
2192
+ */
2193
+ long: z.ZodOptional<z.ZodBoolean>;
1452
2194
  }, "strip", z.ZodTypeAny, {
1453
2195
  value: string;
1454
2196
  label: string;
@@ -1457,6 +2199,16 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1457
2199
  text: string;
1458
2200
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1459
2201
  }[] | undefined;
2202
+ ref?: {
2203
+ user: string;
2204
+ } | {
2205
+ entity: {
2206
+ type: string;
2207
+ id: string;
2208
+ };
2209
+ url?: string | undefined;
2210
+ } | undefined;
2211
+ long?: boolean | undefined;
1460
2212
  }, {
1461
2213
  value: string;
1462
2214
  label: string;
@@ -1465,7 +2217,26 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1465
2217
  text: string;
1466
2218
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1467
2219
  }[] | undefined;
2220
+ ref?: {
2221
+ user: string;
2222
+ } | {
2223
+ entity: {
2224
+ type: string;
2225
+ id: string;
2226
+ };
2227
+ url?: string | undefined;
2228
+ } | undefined;
2229
+ long?: boolean | undefined;
1468
2230
  }>, "many">;
2231
+ /**
2232
+ * 열 수 **명시 오버라이드**(0.9.0). 생략이 기본이고, 기본은 폭이 정하는 auto-fit 이다
2233
+ * (그리고 `short` 넷이면 2×2 로 묶인다 — 0.7.0 에서 이미 들어간 규칙).
2234
+ *
2235
+ * 🔴 **기본을 되돌리지 않는다.** 이 키는 auto-fit 이 틀리는 드문 경우(라벨이 길어 3열이 찢어지는
2236
+ * 표 같은 fields)를 위한 탈출구다 — 늘 주면 좁은 화면에서 열이 안 줄어 값이 짜부라진다.
2237
+ * `"auto"` 는 명시적으로 기본을 고르는 값이다(작성자가 "여긴 렌더러에 맡긴다"를 적을 수 있게).
2238
+ */
2239
+ columns: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<"auto">]>>;
1469
2240
  }, "strip", z.ZodTypeAny, {
1470
2241
  type: "fields";
1471
2242
  items: {
@@ -1476,7 +2247,18 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1476
2247
  text: string;
1477
2248
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1478
2249
  }[] | undefined;
2250
+ ref?: {
2251
+ user: string;
2252
+ } | {
2253
+ entity: {
2254
+ type: string;
2255
+ id: string;
2256
+ };
2257
+ url?: string | undefined;
2258
+ } | undefined;
2259
+ long?: boolean | undefined;
1479
2260
  }[];
2261
+ columns?: 2 | 3 | "auto" | undefined;
1480
2262
  }, {
1481
2263
  type: "fields";
1482
2264
  items: {
@@ -1487,7 +2269,18 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1487
2269
  text: string;
1488
2270
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1489
2271
  }[] | undefined;
2272
+ ref?: {
2273
+ user: string;
2274
+ } | {
2275
+ entity: {
2276
+ type: string;
2277
+ id: string;
2278
+ };
2279
+ url?: string | undefined;
2280
+ } | undefined;
2281
+ long?: boolean | undefined;
1490
2282
  }[];
2283
+ columns?: 2 | 3 | "auto" | undefined;
1491
2284
  }>, z.ZodObject<{
1492
2285
  type: z.ZodLiteral<"image">;
1493
2286
  /** https URL 또는 mxc:// (둘 중 하나 권장). 클라이언트가 출처를 검증한다. */
@@ -1506,7 +2299,6 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1506
2299
  alt?: string | undefined;
1507
2300
  }>, z.ZodObject<{
1508
2301
  type: z.ZodLiteral<"context">;
1509
- /** 작은 보조 텍스트/아이콘 줄 */
1510
2302
  elements: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
1511
2303
  icon: z.ZodString;
1512
2304
  }, "strip", z.ZodTypeAny, {
@@ -1579,25 +2371,25 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1579
2371
  note: z.ZodOptional<z.ZodString>;
1580
2372
  }, "strip", z.ZodTypeAny, {
1581
2373
  label: string;
1582
- status?: "done" | "active" | "todo" | "error" | undefined;
2374
+ status?: "error" | "done" | "active" | "todo" | undefined;
1583
2375
  note?: string | undefined;
1584
2376
  }, {
1585
2377
  label: string;
1586
- status?: "done" | "active" | "todo" | "error" | undefined;
2378
+ status?: "error" | "done" | "active" | "todo" | undefined;
1587
2379
  note?: string | undefined;
1588
2380
  }>, "many">;
1589
2381
  }, "strip", z.ZodTypeAny, {
1590
2382
  type: "steps";
1591
2383
  items: {
1592
2384
  label: string;
1593
- status?: "done" | "active" | "todo" | "error" | undefined;
2385
+ status?: "error" | "done" | "active" | "todo" | undefined;
1594
2386
  note?: string | undefined;
1595
2387
  }[];
1596
2388
  }, {
1597
2389
  type: "steps";
1598
2390
  items: {
1599
2391
  label: string;
1600
- status?: "done" | "active" | "todo" | "error" | undefined;
2392
+ status?: "error" | "done" | "active" | "todo" | undefined;
1601
2393
  note?: string | undefined;
1602
2394
  }[];
1603
2395
  }>, z.ZodObject<{
@@ -1674,12 +2466,60 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1674
2466
  initials: z.ZodOptional<z.ZodString>;
1675
2467
  src: z.ZodOptional<z.ZodString>;
1676
2468
  subtitle: z.ZodOptional<z.ZodString>;
2469
+ /**
2470
+ * 이 아바타가 가리키는 사람/엔티티 (0.8.0). 있으면 렌더러가 해석 결과(이름·사진)로 `name`/`src` 를
2471
+ * **덮어쓴다** — 방 상태가 정답이라 개명·프로필 변경이 즉시 반영된다.
2472
+ * 🔴 `name` 은 평문 사본으로 남긴다: 해석기가 없거나(외부 임베더) 옛 클라면 그 문자열이 유일한 답이다.
2473
+ */
2474
+ ref: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
2475
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
2476
+ user: z.ZodString;
2477
+ }, "strip", z.ZodTypeAny, {
2478
+ user: string;
2479
+ }, {
2480
+ user: string;
2481
+ }>, z.ZodObject<{
2482
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
2483
+ entity: z.ZodObject<{
2484
+ type: z.ZodString;
2485
+ id: z.ZodString;
2486
+ }, "strip", z.ZodTypeAny, {
2487
+ type: string;
2488
+ id: string;
2489
+ }, {
2490
+ type: string;
2491
+ id: string;
2492
+ }>;
2493
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
2494
+ url: z.ZodOptional<z.ZodString>;
2495
+ }, "strip", z.ZodTypeAny, {
2496
+ entity: {
2497
+ type: string;
2498
+ id: string;
2499
+ };
2500
+ url?: string | undefined;
2501
+ }, {
2502
+ entity: {
2503
+ type: string;
2504
+ id: string;
2505
+ };
2506
+ url?: string | undefined;
2507
+ }>]>>;
1677
2508
  /** 우하단 상태점 — 네 상태가 각자 색을 갖는다(`--cob-color-presence-*`). 색만으로 안 나르도록 `aria-label` 이 상태를 병기한다. */
1678
2509
  status: z.ZodOptional<z.ZodEnum<["online", "away", "busy", "offline"]>>;
1679
2510
  }, "strip", z.ZodTypeAny, {
1680
2511
  type: "avatar";
1681
2512
  name: string;
1682
2513
  status?: "online" | "away" | "busy" | "offline" | undefined;
2514
+ ref?: {
2515
+ user: string;
2516
+ } | {
2517
+ entity: {
2518
+ type: string;
2519
+ id: string;
2520
+ };
2521
+ url?: string | undefined;
2522
+ } | undefined;
1683
2523
  initials?: string | undefined;
1684
2524
  src?: string | undefined;
1685
2525
  subtitle?: string | undefined;
@@ -1687,6 +2527,15 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1687
2527
  type: "avatar";
1688
2528
  name: string;
1689
2529
  status?: "online" | "away" | "busy" | "offline" | undefined;
2530
+ ref?: {
2531
+ user: string;
2532
+ } | {
2533
+ entity: {
2534
+ type: string;
2535
+ id: string;
2536
+ };
2537
+ url?: string | undefined;
2538
+ } | undefined;
1690
2539
  initials?: string | undefined;
1691
2540
  src?: string | undefined;
1692
2541
  subtitle?: string | undefined;
@@ -1805,15 +2654,15 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1805
2654
  }, "strip", z.ZodTypeAny, {
1806
2655
  type: "entityRef";
1807
2656
  label: string;
1808
- tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1809
- url?: string | undefined;
1810
2657
  entity?: string | undefined;
2658
+ url?: string | undefined;
2659
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1811
2660
  }, {
1812
2661
  type: "entityRef";
1813
2662
  label: string;
1814
- tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1815
- url?: string | undefined;
1816
2663
  entity?: string | undefined;
2664
+ url?: string | undefined;
2665
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1817
2666
  }>, z.ZodObject<{
1818
2667
  type: z.ZodLiteral<"kanban">;
1819
2668
  columns: z.ZodArray<z.ZodObject<{
@@ -1837,8 +2686,8 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1837
2686
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1838
2687
  }>>;
1839
2688
  }, "strip", z.ZodTypeAny, {
1840
- title: string;
1841
2689
  id: string;
2690
+ title: string;
1842
2691
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1843
2692
  badge?: {
1844
2693
  label: string;
@@ -1846,8 +2695,8 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1846
2695
  } | undefined;
1847
2696
  meta?: string[] | undefined;
1848
2697
  }, {
1849
- title: string;
1850
2698
  id: string;
2699
+ title: string;
1851
2700
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1852
2701
  badge?: {
1853
2702
  label: string;
@@ -1856,10 +2705,11 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1856
2705
  meta?: string[] | undefined;
1857
2706
  }>, "many">;
1858
2707
  }, "strip", z.ZodTypeAny, {
2708
+ id: string;
1859
2709
  title: string;
1860
2710
  cards: {
1861
- title: string;
1862
2711
  id: string;
2712
+ title: string;
1863
2713
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1864
2714
  badge?: {
1865
2715
  label: string;
@@ -1867,13 +2717,13 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1867
2717
  } | undefined;
1868
2718
  meta?: string[] | undefined;
1869
2719
  }[];
1870
- id: string;
1871
2720
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1872
2721
  }, {
2722
+ id: string;
1873
2723
  title: string;
1874
2724
  cards: {
1875
- title: string;
1876
2725
  id: string;
2726
+ title: string;
1877
2727
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1878
2728
  badge?: {
1879
2729
  label: string;
@@ -1881,17 +2731,17 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1881
2731
  } | undefined;
1882
2732
  meta?: string[] | undefined;
1883
2733
  }[];
1884
- id: string;
1885
2734
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1886
2735
  }>, "many">;
1887
2736
  caption: z.ZodOptional<z.ZodString>;
1888
2737
  }, "strip", z.ZodTypeAny, {
1889
2738
  type: "kanban";
1890
2739
  columns: {
2740
+ id: string;
1891
2741
  title: string;
1892
2742
  cards: {
1893
- title: string;
1894
2743
  id: string;
2744
+ title: string;
1895
2745
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1896
2746
  badge?: {
1897
2747
  label: string;
@@ -1899,17 +2749,17 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1899
2749
  } | undefined;
1900
2750
  meta?: string[] | undefined;
1901
2751
  }[];
1902
- id: string;
1903
2752
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1904
2753
  }[];
1905
2754
  caption?: string | undefined;
1906
2755
  }, {
1907
2756
  type: "kanban";
1908
2757
  columns: {
2758
+ id: string;
1909
2759
  title: string;
1910
2760
  cards: {
1911
- title: string;
1912
2761
  id: string;
2762
+ title: string;
1913
2763
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1914
2764
  badge?: {
1915
2765
  label: string;
@@ -1917,7 +2767,6 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1917
2767
  } | undefined;
1918
2768
  meta?: string[] | undefined;
1919
2769
  }[];
1920
- id: string;
1921
2770
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1922
2771
  }[];
1923
2772
  caption?: string | undefined;
@@ -1941,6 +2790,186 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1941
2790
  label?: string | undefined;
1942
2791
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1943
2792
  expiredText?: string | undefined;
2793
+ }>, z.ZodObject<{
2794
+ type: z.ZodLiteral<"activity">;
2795
+ label: z.ZodOptional<z.ZodString>;
2796
+ /** 펼쳐 둘 최근 항목 수(기본 3). 나머지는 "이전 N건 더 보기"로 접힌다. */
2797
+ maxVisible: z.ZodOptional<z.ZodNumber>;
2798
+ items: z.ZodArray<z.ZodObject<{
2799
+ /** 행위의 주어 — 참조면 아바타·이름으로, 문자열이면 그대로. */
2800
+ who: z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodObject<{
2801
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
2802
+ user: z.ZodString;
2803
+ }, "strip", z.ZodTypeAny, {
2804
+ user: string;
2805
+ }, {
2806
+ user: string;
2807
+ }>, z.ZodObject<{
2808
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
2809
+ entity: z.ZodObject<{
2810
+ type: z.ZodString;
2811
+ id: z.ZodString;
2812
+ }, "strip", z.ZodTypeAny, {
2813
+ type: string;
2814
+ id: string;
2815
+ }, {
2816
+ type: string;
2817
+ id: string;
2818
+ }>;
2819
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
2820
+ url: z.ZodOptional<z.ZodString>;
2821
+ }, "strip", z.ZodTypeAny, {
2822
+ entity: {
2823
+ type: string;
2824
+ id: string;
2825
+ };
2826
+ url?: string | undefined;
2827
+ }, {
2828
+ entity: {
2829
+ type: string;
2830
+ id: string;
2831
+ };
2832
+ url?: string | undefined;
2833
+ }>]>]>;
2834
+ /** 무엇을 했나 — 인라인 마크다운 허용(`text` 블록의 인라인 규칙과 같다). */
2835
+ what: z.ZodString;
2836
+ /** 언제 — ISO 8601 타임스탬프 문자열. 렌더러가 상대 시각으로 그린다. */
2837
+ at: z.ZodString;
2838
+ tone: z.ZodOptional<z.ZodEnum<["neutral", "success", "warning", "danger", "info"]>>;
2839
+ /** 대상(선택) — "A 가 **B 에게** 전달" 의 B. */
2840
+ to: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodObject<{
2841
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
2842
+ user: z.ZodString;
2843
+ }, "strip", z.ZodTypeAny, {
2844
+ user: string;
2845
+ }, {
2846
+ user: string;
2847
+ }>, z.ZodObject<{
2848
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
2849
+ entity: z.ZodObject<{
2850
+ type: z.ZodString;
2851
+ id: z.ZodString;
2852
+ }, "strip", z.ZodTypeAny, {
2853
+ type: string;
2854
+ id: string;
2855
+ }, {
2856
+ type: string;
2857
+ id: string;
2858
+ }>;
2859
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
2860
+ url: z.ZodOptional<z.ZodString>;
2861
+ }, "strip", z.ZodTypeAny, {
2862
+ entity: {
2863
+ type: string;
2864
+ id: string;
2865
+ };
2866
+ url?: string | undefined;
2867
+ }, {
2868
+ entity: {
2869
+ type: string;
2870
+ id: string;
2871
+ };
2872
+ url?: string | undefined;
2873
+ }>]>]>>;
2874
+ }, "strip", z.ZodTypeAny, {
2875
+ at: string;
2876
+ who: string | {
2877
+ user: string;
2878
+ } | {
2879
+ entity: {
2880
+ type: string;
2881
+ id: string;
2882
+ };
2883
+ url?: string | undefined;
2884
+ };
2885
+ what: string;
2886
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2887
+ to?: string | {
2888
+ user: string;
2889
+ } | {
2890
+ entity: {
2891
+ type: string;
2892
+ id: string;
2893
+ };
2894
+ url?: string | undefined;
2895
+ } | undefined;
2896
+ }, {
2897
+ at: string;
2898
+ who: string | {
2899
+ user: string;
2900
+ } | {
2901
+ entity: {
2902
+ type: string;
2903
+ id: string;
2904
+ };
2905
+ url?: string | undefined;
2906
+ };
2907
+ what: string;
2908
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2909
+ to?: string | {
2910
+ user: string;
2911
+ } | {
2912
+ entity: {
2913
+ type: string;
2914
+ id: string;
2915
+ };
2916
+ url?: string | undefined;
2917
+ } | undefined;
2918
+ }>, "many">;
2919
+ }, "strip", z.ZodTypeAny, {
2920
+ type: "activity";
2921
+ items: {
2922
+ at: string;
2923
+ who: string | {
2924
+ user: string;
2925
+ } | {
2926
+ entity: {
2927
+ type: string;
2928
+ id: string;
2929
+ };
2930
+ url?: string | undefined;
2931
+ };
2932
+ what: string;
2933
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2934
+ to?: string | {
2935
+ user: string;
2936
+ } | {
2937
+ entity: {
2938
+ type: string;
2939
+ id: string;
2940
+ };
2941
+ url?: string | undefined;
2942
+ } | undefined;
2943
+ }[];
2944
+ label?: string | undefined;
2945
+ maxVisible?: number | undefined;
2946
+ }, {
2947
+ type: "activity";
2948
+ items: {
2949
+ at: string;
2950
+ who: string | {
2951
+ user: string;
2952
+ } | {
2953
+ entity: {
2954
+ type: string;
2955
+ id: string;
2956
+ };
2957
+ url?: string | undefined;
2958
+ };
2959
+ what: string;
2960
+ tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2961
+ to?: string | {
2962
+ user: string;
2963
+ } | {
2964
+ entity: {
2965
+ type: string;
2966
+ id: string;
2967
+ };
2968
+ url?: string | undefined;
2969
+ } | undefined;
2970
+ }[];
2971
+ label?: string | undefined;
2972
+ maxVisible?: number | undefined;
1944
2973
  }>, z.ZodObject<{
1945
2974
  type: z.ZodLiteral<"code">;
1946
2975
  code: z.ZodString;
@@ -2011,6 +3040,27 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2011
3040
  /** 처음부터 펼쳐둘지(기본 접힘). */
2012
3041
  open: z.ZodOptional<z.ZodBoolean>;
2013
3042
  tone: z.ZodOptional<z.ZodEnum<["neutral", "success", "warning", "danger", "info"]>>;
3043
+ /**
3044
+ * **옛 클라용 사본이라는 표식**(0.8.0). 빌더가 새 블록을 낼 때 같은 내용을 이 접기 블록으로 병기하고
3045
+ * 여기에 원본 블록 타입을 적는다.
3046
+ *
3047
+ * 왜 필요한가: 새 *블록 타입*은 `dropUnknownBlocks` 에서 **통째로 떨어진다**(키 추가와 달리 degrade
3048
+ * 경로가 없다). 그래서 `activity` 는 빌더가 사본을 같이 내고, **새 렌더러는 원본을 아니까 사본을
3049
+ * 안 그린다** — 안 그러면 새 클라에서 같은 이력이 두 번 보인다.
3050
+ * 이 키를 모르는 옛 클라는 strip 하고 평범한 접기 블록으로 그린다(그게 목적이다).
3051
+ *
3052
+ * 전환기가 끝나 클라 배포가 충분히 퍼지면 빌더의 `legacy` 기본값을 false 로 바꾼다(이 시리즈 밖).
3053
+ */
3054
+ legacy_for: z.ZodOptional<z.ZodEnum<["activity"]>>;
3055
+ /**
3056
+ * **접힌 채로도 보이는 한 줄**(0.9.0) — 제목 오른쪽에 흐리게 선다. 펼치면 숨는다(본문이 답이다).
3057
+ *
3058
+ * 왜 필요한가(감사 문서 D): 접기는 "카드 높이를 안 먹는 상세"인데, 지금은 접힌 상태에서 **정보가
3059
+ * 0** 이라 사용자가 펼쳐 봐야 안에 뭐가 있는지 안다. 마지막 한 줄만 보여 주면 대개 펼칠 필요가 없다
3060
+ * ("마지막: 희태 박에게 전달 · 6:12").
3061
+ * ⚠️ 본문의 요약이지 본문의 **대체**가 아니다 — 여기만 읽고 끝나도 되는 내용이면 접지 말 것.
3062
+ */
3063
+ summary: z.ZodOptional<z.ZodString>;
2014
3064
  /**
2015
3065
  * 펼치면 보이는 중첩 블록(재귀). 런타임은 z.lazy 로 BlockSchema 를 지연 참조해 재귀 검증하지만,
2016
3066
  * 정적 타입은 z.ZodTypeAny 로 끊는다 — Block 이 z.infer 기반이라 재귀 타입 별칭이 conditional type
@@ -2023,12 +3073,16 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2023
3073
  blocks: any[];
2024
3074
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2025
3075
  open?: boolean | undefined;
3076
+ legacy_for?: "activity" | undefined;
3077
+ summary?: string | undefined;
2026
3078
  }, {
2027
3079
  type: "collapsible";
2028
3080
  title: string;
2029
3081
  blocks: any[];
2030
3082
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2031
3083
  open?: boolean | undefined;
3084
+ legacy_for?: "activity" | undefined;
3085
+ summary?: string | undefined;
2032
3086
  }>, z.ZodObject<{
2033
3087
  type: z.ZodLiteral<"widget">;
2034
3088
  url: z.ZodString;
@@ -2075,26 +3129,68 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2075
3129
  * 단일 업로드로 동작한다(기능 축소일 뿐 파손 없음).
2076
3130
  */
2077
3131
  multiple: z.ZodOptional<z.ZodBoolean>;
3132
+ /**
3133
+ * 하한/상한 (0.7.0) — number/date/datetime/time 공용. **문자열**이다: 날짜·시각은 그 타입의 값
3134
+ * 형식(`2026-09-22`·`18:15`)이고, number 면 숫자를 적은 문자열이다(와이어 canonical JSON 은
3135
+ * 소수를 허용하지 않아 숫자 축을 열 수 없다 — `slider` 가 int 만 받는 것과 같은 제약).
3136
+ *
3137
+ * `"today"` 리터럴을 허용한다 — "기한은 오늘 이후"는 카드를 **보낸 날**이 아니라 **보는 날** 기준이라야
3138
+ * 맞다(카드는 타임라인에 남고 며칠 뒤에도 눌린다). 렌더러가 그릴 때 해석한다.
3139
+ *
3140
+ * 🔴 **UX 다, 진실은 서버**(`hidden_for` 와 같은 자세). 클라가 미리 잠그는 건 헛걸음을 줄이려는
3141
+ * 것뿐이고, 진짜 판정은 언제나 핸들러·게이트가 한다. 이 키를 모르는 옛 클라는 strip 하고 지금처럼
3142
+ * 아무 제약 없이 제출한다 — 그러면 서버가 사람이 읽을 이유와 함께 거절한다(`action.result`).
3143
+ */
3144
+ min: z.ZodOptional<z.ZodString>;
3145
+ max: z.ZodOptional<z.ZodString>;
3146
+ /** 글자 수 하한/상한 (0.7.0) — 텍스트 계열 전용. 🔴 UX 다, 진실은 서버. */
3147
+ minLength: z.ZodOptional<z.ZodNumber>;
3148
+ maxLength: z.ZodOptional<z.ZodNumber>;
3149
+ /**
3150
+ * 값이 맞아야 하는 정규식 **소스**(0.7.0, 예: `"^[A-Z]{2}-\\d{4}$"`). 플래그·구분자 없이 패턴만 적는다.
3151
+ *
3152
+ * 🔴 렌더러는 `new RegExp` 를 **try/catch 로 감싼다** — 작성자가 자바스크립트가 아닌 방언(파이썬
3153
+ * `(?P<x>…)` 등)을 보내면 던지는데, 그걸로 카드 전체가 죽으면 안 된다. 못 읽는 패턴은 무시한다
3154
+ * (= 제약 없음). 진짜 판정은 여전히 서버다.
3155
+ */
3156
+ pattern: z.ZodOptional<z.ZodString>;
3157
+ /**
3158
+ * 제약 위반 시 보여 줄 **작성자 소유 문장**(0.7.0). 없으면 렌더러 크롬 문구를 쓴다
3159
+ * (`LabelContext` — "누구의 문자열인가"가 경계선이고, 도메인 사정을 아는 문장은 작성자 것이다).
3160
+ */
3161
+ error: z.ZodOptional<z.ZodString>;
2078
3162
  }, "strip", z.ZodTypeAny, {
2079
3163
  type: "input";
2080
3164
  name: string;
2081
3165
  value?: string | undefined;
2082
3166
  label?: string | undefined;
2083
- input?: "number" | "text" | "date" | "url" | "textarea" | "datetime" | "time" | "email" | "file" | undefined;
3167
+ input?: "number" | "date" | "url" | "text" | "textarea" | "datetime" | "time" | "email" | "file" | undefined;
2084
3168
  placeholder?: string | undefined;
2085
3169
  required?: boolean | undefined;
2086
3170
  accept?: string | undefined;
2087
3171
  multiple?: boolean | undefined;
3172
+ min?: string | undefined;
3173
+ max?: string | undefined;
3174
+ minLength?: number | undefined;
3175
+ maxLength?: number | undefined;
3176
+ pattern?: string | undefined;
3177
+ error?: string | undefined;
2088
3178
  }, {
2089
3179
  type: "input";
2090
3180
  name: string;
2091
3181
  value?: string | undefined;
2092
3182
  label?: string | undefined;
2093
- input?: "number" | "text" | "date" | "url" | "textarea" | "datetime" | "time" | "email" | "file" | undefined;
3183
+ input?: "number" | "date" | "url" | "text" | "textarea" | "datetime" | "time" | "email" | "file" | undefined;
2094
3184
  placeholder?: string | undefined;
2095
3185
  required?: boolean | undefined;
2096
3186
  accept?: string | undefined;
2097
3187
  multiple?: boolean | undefined;
3188
+ min?: string | undefined;
3189
+ max?: string | undefined;
3190
+ minLength?: number | undefined;
3191
+ maxLength?: number | undefined;
3192
+ pattern?: string | undefined;
3193
+ error?: string | undefined;
2098
3194
  }>, z.ZodObject<{
2099
3195
  type: z.ZodLiteral<"toggle">;
2100
3196
  name: z.ZodString;
@@ -2167,6 +3263,10 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2167
3263
  }>, "many">;
2168
3264
  value: z.ZodOptional<z.ZodString>;
2169
3265
  style: z.ZodOptional<z.ZodEnum<["cards", "segmented"]>>;
3266
+ /** 고르지 않으면 제출을 잠근다 (0.7.0). 🔴 UX 다, 진실은 서버 — `input.required` 와 같은 자세. */
3267
+ required: z.ZodOptional<z.ZodBoolean>;
3268
+ /** 미선택 시 보여 줄 작성자 소유 문장 (0.7.0). 없으면 렌더러 크롬 문구. */
3269
+ error: z.ZodOptional<z.ZodString>;
2170
3270
  }, "strip", z.ZodTypeAny, {
2171
3271
  options: {
2172
3272
  value: string;
@@ -2177,6 +3277,8 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2177
3277
  name: string;
2178
3278
  value?: string | undefined;
2179
3279
  label?: string | undefined;
3280
+ required?: boolean | undefined;
3281
+ error?: string | undefined;
2180
3282
  style?: "cards" | "segmented" | undefined;
2181
3283
  }, {
2182
3284
  options: {
@@ -2188,46 +3290,230 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2188
3290
  name: string;
2189
3291
  value?: string | undefined;
2190
3292
  label?: string | undefined;
3293
+ required?: boolean | undefined;
3294
+ error?: string | undefined;
2191
3295
  style?: "cards" | "segmented" | undefined;
2192
3296
  }>, z.ZodObject<{
2193
3297
  type: z.ZodLiteral<"select">;
2194
3298
  name: z.ZodString;
2195
3299
  label: z.ZodOptional<z.ZodString>;
2196
3300
  placeholder: z.ZodOptional<z.ZodString>;
3301
+ /**
3302
+ * 후보 목록. `ref`(0.8.0)를 주면 렌더러가 행을 칩(아바타·이름·MXID)으로 그린다 —
3303
+ * 🔴 `label` 은 평문 사본으로 남긴다(RefSchema 머리말).
3304
+ * `hint`(0.9.0)는 라벨 아래 한 줄 보조 설명 — `radio` 의 같은 이름 키와 같은 뜻이다.
3305
+ */
2197
3306
  options: z.ZodArray<z.ZodObject<{
2198
3307
  value: z.ZodString;
2199
3308
  label: z.ZodString;
3309
+ hint: z.ZodOptional<z.ZodString>;
3310
+ ref: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
3311
+ /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
3312
+ user: z.ZodString;
3313
+ }, "strip", z.ZodTypeAny, {
3314
+ user: string;
3315
+ }, {
3316
+ user: string;
3317
+ }>, z.ZodObject<{
3318
+ /** 도메인 엔티티 — `entityRef` **블록**이 이미 쓰는 종류/식별자 짝이 값 안으로 들어온 것. */
3319
+ entity: z.ZodObject<{
3320
+ type: z.ZodString;
3321
+ id: z.ZodString;
3322
+ }, "strip", z.ZodTypeAny, {
3323
+ type: string;
3324
+ id: string;
3325
+ }, {
3326
+ type: string;
3327
+ id: string;
3328
+ }>;
3329
+ /** 클릭 시 이동할 https URL(선택). 출처는 클라가 검증한다. */
3330
+ url: z.ZodOptional<z.ZodString>;
3331
+ }, "strip", z.ZodTypeAny, {
3332
+ entity: {
3333
+ type: string;
3334
+ id: string;
3335
+ };
3336
+ url?: string | undefined;
3337
+ }, {
3338
+ entity: {
3339
+ type: string;
3340
+ id: string;
3341
+ };
3342
+ url?: string | undefined;
3343
+ }>]>>;
2200
3344
  }, "strip", z.ZodTypeAny, {
2201
3345
  value: string;
2202
3346
  label: string;
3347
+ ref?: {
3348
+ user: string;
3349
+ } | {
3350
+ entity: {
3351
+ type: string;
3352
+ id: string;
3353
+ };
3354
+ url?: string | undefined;
3355
+ } | undefined;
3356
+ hint?: string | undefined;
2203
3357
  }, {
2204
3358
  value: string;
2205
3359
  label: string;
3360
+ ref?: {
3361
+ user: string;
3362
+ } | {
3363
+ entity: {
3364
+ type: string;
3365
+ id: string;
3366
+ };
3367
+ url?: string | undefined;
3368
+ } | undefined;
3369
+ hint?: string | undefined;
2206
3370
  }>, "many">;
2207
3371
  value: z.ZodOptional<z.ZodString>;
2208
3372
  multi: z.ZodOptional<z.ZodBoolean>;
3373
+ /** 후보가 어디서 오나 (0.9.0). 생략 = `options` 배열. 위 `SelectSourceSchema` 머리말 참조. */
3374
+ source: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
3375
+ /** 이 방의 멤버가 후보다. 값은 MXID 배열이고, 이름·아바타는 클라가 방 상태로 해석한다. */
3376
+ kind: z.ZodLiteral<"room">;
3377
+ /** 보는 사람 자신을 후보에서 뺀다(기본 false). "받을 사람"처럼 나를 고를 일이 없는 자리. */
3378
+ exclude_self: z.ZodOptional<z.ZodBoolean>;
3379
+ /** 후보에서 뺄 MXID 목록 — 이미 담당인 사람, 퇴사 처리 중인 계정 등. */
3380
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
3381
+ /** 봇·에이전트 계정도 후보에 넣는다(기본 false — 사람을 고르는 자리가 대부분이다). */
3382
+ include_bots: z.ZodOptional<z.ZodBoolean>;
3383
+ }, "strip", z.ZodTypeAny, {
3384
+ kind: "room";
3385
+ exclude_self?: boolean | undefined;
3386
+ exclude?: string[] | undefined;
3387
+ include_bots?: boolean | undefined;
3388
+ }, {
3389
+ kind: "room";
3390
+ exclude_self?: boolean | undefined;
3391
+ exclude?: string[] | undefined;
3392
+ include_bots?: boolean | undefined;
3393
+ }>, z.ZodObject<{
3394
+ /** 타이핑할 때마다 서버에 묻는다 — 답은 `org.corp.ui.action.result` 의 `kind: "options"`. */
3395
+ kind: z.ZodLiteral<"query">;
3396
+ /**
3397
+ * 질의를 받을 액션. 클라는 `action_type: "query"` 로 `{ q, name }` 을 실어 보낸다.
3398
+ * 🔴 사람이 누른 게 아니므로 앱은 **부작용 없이** `ctx.result({ kind: "options", name, options })`
3399
+ * 로만 답해야 한다(같은 핸들러가 제출도 처리한다면 `action_type` 으로 갈라야 한다).
3400
+ */
3401
+ action_id: z.ZodString;
3402
+ /** 몇 글자부터 묻나(기본 1). 한 글자에 전체 스캔이 도는 백엔드라면 올린다. */
3403
+ min_chars: z.ZodOptional<z.ZodNumber>;
3404
+ /** 타이핑이 멎고 몇 ms 뒤에 묻나(기본 300). */
3405
+ debounce_ms: z.ZodOptional<z.ZodNumber>;
3406
+ }, "strip", z.ZodTypeAny, {
3407
+ kind: "query";
3408
+ action_id: string;
3409
+ min_chars?: number | undefined;
3410
+ debounce_ms?: number | undefined;
3411
+ }, {
3412
+ kind: "query";
3413
+ action_id: string;
3414
+ min_chars?: number | undefined;
3415
+ debounce_ms?: number | undefined;
3416
+ }>]>>;
3417
+ /**
3418
+ * 표현 힌트 (0.9.0) — **능력이 아니라 룩이다.** 생략하면 렌더러가 후보 수·`multi`·`source` 로 고른다.
3419
+ * · `list`/`segmented` — `radio` 의 같은 이름 표현과 **같은 뜻**(펼친 목록 / 한 줄 세그먼트).
3420
+ * `multi` 와 같이 쓰면 그릴 수 있는 컨트롤이 없어 칩 콤보박스로 떨어진다.
3421
+ * · `dropdown` — 트리거 + 떠 있는 목록(콤보박스). 네이티브 `<select>` 가 아니다.
3422
+ * · `chips` — 고른 것이 트리거 안에서 칩으로 선다(`multi` 의 기본 표현).
3423
+ */
3424
+ style: z.ZodOptional<z.ZodEnum<["list", "segmented", "dropdown", "chips"]>>;
3425
+ /**
3426
+ * 목록 안 검색창 (0.9.0). 생략하면 렌더러가 켠다 — 후보가 8 개를 넘거나, 공급원이 방/질의일 때.
3427
+ * 🔴 이건 "검색하기 **버튼**"이 아니다. 타이핑이 곧 필터이고, 왕복은 `source: query` 일 때만 돈다.
3428
+ */
3429
+ searchable: z.ZodOptional<z.ZodBoolean>;
3430
+ /** 고르지 않으면 제출을 잠근다 (0.7.0). 🔴 UX 다, 진실은 서버. */
3431
+ required: z.ZodOptional<z.ZodBoolean>;
3432
+ /**
3433
+ * `multi: true` 전용 — **고른 개수**의 하한/상한 (0.7.0). 단일 선택에선 무시한다.
3434
+ * (`input` 의 `min`/`max` 는 값의 크기라 문자열인데, 여기는 개수라 정수다.)
3435
+ * 🔴 UX 다, 진실은 서버.
3436
+ */
3437
+ min: z.ZodOptional<z.ZodNumber>;
3438
+ max: z.ZodOptional<z.ZodNumber>;
3439
+ /** 제약 위반 시 보여 줄 작성자 소유 문장 (0.7.0). 없으면 렌더러 크롬 문구. */
3440
+ error: z.ZodOptional<z.ZodString>;
2209
3441
  }, "strip", z.ZodTypeAny, {
2210
3442
  options: {
2211
3443
  value: string;
2212
3444
  label: string;
3445
+ ref?: {
3446
+ user: string;
3447
+ } | {
3448
+ entity: {
3449
+ type: string;
3450
+ id: string;
3451
+ };
3452
+ url?: string | undefined;
3453
+ } | undefined;
3454
+ hint?: string | undefined;
2213
3455
  }[];
2214
3456
  type: "select";
2215
3457
  name: string;
2216
3458
  value?: string | undefined;
2217
3459
  label?: string | undefined;
2218
3460
  placeholder?: string | undefined;
3461
+ required?: boolean | undefined;
3462
+ min?: number | undefined;
3463
+ max?: number | undefined;
3464
+ error?: string | undefined;
3465
+ style?: "segmented" | "list" | "dropdown" | "chips" | undefined;
2219
3466
  multi?: boolean | undefined;
3467
+ source?: {
3468
+ kind: "room";
3469
+ exclude_self?: boolean | undefined;
3470
+ exclude?: string[] | undefined;
3471
+ include_bots?: boolean | undefined;
3472
+ } | {
3473
+ kind: "query";
3474
+ action_id: string;
3475
+ min_chars?: number | undefined;
3476
+ debounce_ms?: number | undefined;
3477
+ } | undefined;
3478
+ searchable?: boolean | undefined;
2220
3479
  }, {
2221
3480
  options: {
2222
3481
  value: string;
2223
3482
  label: string;
3483
+ ref?: {
3484
+ user: string;
3485
+ } | {
3486
+ entity: {
3487
+ type: string;
3488
+ id: string;
3489
+ };
3490
+ url?: string | undefined;
3491
+ } | undefined;
3492
+ hint?: string | undefined;
2224
3493
  }[];
2225
3494
  type: "select";
2226
3495
  name: string;
2227
3496
  value?: string | undefined;
2228
3497
  label?: string | undefined;
2229
3498
  placeholder?: string | undefined;
3499
+ required?: boolean | undefined;
3500
+ min?: number | undefined;
3501
+ max?: number | undefined;
3502
+ error?: string | undefined;
3503
+ style?: "segmented" | "list" | "dropdown" | "chips" | undefined;
2230
3504
  multi?: boolean | undefined;
3505
+ source?: {
3506
+ kind: "room";
3507
+ exclude_self?: boolean | undefined;
3508
+ exclude?: string[] | undefined;
3509
+ include_bots?: boolean | undefined;
3510
+ } | {
3511
+ kind: "query";
3512
+ action_id: string;
3513
+ min_chars?: number | undefined;
3514
+ debounce_ms?: number | undefined;
3515
+ } | undefined;
3516
+ searchable?: boolean | undefined;
2231
3517
  }>, z.ZodObject<{
2232
3518
  type: z.ZodLiteral<"checkbox">;
2233
3519
  name: z.ZodString;
@@ -2311,6 +3597,36 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2311
3597
  * 보여 줘도 안전하다(누르면 서버가 사람이 읽을 이유와 함께 거절한다).
2312
3598
  */
2313
3599
  hidden_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
3600
+ /**
3601
+ * `hidden_for` 의 **짝**(0.7.0) — 이 MXID 들에게만 버튼을 보인다(화이트리스트).
3602
+ *
3603
+ * 왜 둘 다 있나: 두 축은 아는 것이 다르다. `hidden_for` 는 "이 사람은 절대 못 누른다"를 아는 경우고
3604
+ * (자기 PR 자기 승인), `visible_for` 는 "이 사람만 누를 수 있다"를 아는 경우다(현재 수신자). 후자를
3605
+ * `hidden_for` 로 쓰려면 방 멤버 전원을 열거해야 하고, 그 목록은 카드를 만든 **순간**에 굳는다 —
3606
+ * 나중에 들어온 사람에게 버튼이 그냥 보인다.
3607
+ *
3608
+ * 🔴 **둘 다 있으면 `hidden_for` 가 이긴다.** "못 누른다"가 "누를 수 있다"보다 강한 진술이라서다
3609
+ * (겹치는 경우는 보통 작성자의 실수이고, 그때 안전한 쪽은 감추는 쪽이다).
3610
+ * 🔴 **권한이 아니다** — `hidden_for` 와 똑같이 UX 고, 진짜 게이트는 언제나 서버다.
3611
+ * 이 키를 모르는 옛 클라는 strip 하고 **전원에게** 버튼을 보인다 → 누르면 서버가 거절한다.
3612
+ */
3613
+ visible_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
3614
+ /**
3615
+ * 버튼이 잠기거나 감춰진 **이유 한 줄**(0.7.0) — 사람이 읽을 문장(작성자 소유).
3616
+ * `disabled` 면 버튼 옆 보조 텍스트로, `visible_for` 로 감춰졌으면 버튼 자리에 이 줄만 남는다.
3617
+ * "눌러 봐야 안다"를 없애는 것이 요점이다. 🔴 UX 다, 진실은 서버.
3618
+ */
3619
+ disabled_reason: z.ZodOptional<z.ZodString>;
3620
+ /**
3621
+ * **중요도**(0.9.0) — 배치가 아니라 의도다. `"secondary"` 는 "이건 부차적이다"라는 말이고,
3622
+ * 액션 줄이 좁아 한 줄에 못 들어갈 때 렌더러가 **먼저 ⋯ 메뉴로 접는** 대상이 된다.
3623
+ *
3624
+ * 🔴 **`style` 과 다른 축이다.** `style` 은 *생김새*(기본/강조/위험)이고 이것은 *중요도*다 —
3625
+ * `style: "danger"` 인 "보고 취소"가 부차적일 수 있다(위험하지만 주 동작은 아니다). 둘을 한
3626
+ * 축으로 묶으면 그 카드를 표현할 수 없다.
3627
+ * ⚠️ 생략하면 지금과 **완전히 같다**(안 접힌다). 접기는 `"secondary"` 를 선언한 것에만 일어난다.
3628
+ */
3629
+ priority: z.ZodOptional<z.ZodEnum<["primary", "secondary"]>>;
2314
3630
  }, "strip", z.ZodTypeAny, {
2315
3631
  type: "button";
2316
3632
  text: string;
@@ -2325,6 +3641,9 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2325
3641
  } | undefined;
2326
3642
  disabled?: boolean | undefined;
2327
3643
  hidden_for?: string[] | undefined;
3644
+ visible_for?: string[] | undefined;
3645
+ disabled_reason?: string | undefined;
3646
+ priority?: "primary" | "secondary" | undefined;
2328
3647
  }, {
2329
3648
  type: "button";
2330
3649
  text: string;
@@ -2339,6 +3658,9 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2339
3658
  } | undefined;
2340
3659
  disabled?: boolean | undefined;
2341
3660
  hidden_for?: string[] | undefined;
3661
+ visible_for?: string[] | undefined;
3662
+ disabled_reason?: string | undefined;
3663
+ priority?: "primary" | "secondary" | undefined;
2342
3664
  }>, z.ZodObject<{
2343
3665
  type: z.ZodLiteral<"linkButton">;
2344
3666
  text: z.ZodString;
@@ -2347,153 +3669,31 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2347
3669
  style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
2348
3670
  /** 새 탭으로 열기(기본 true). */
2349
3671
  external: z.ZodOptional<z.ZodBoolean>;
3672
+ /** 중요도 (0.9.0) — `ButtonBlockSchema.priority` 와 같은 뜻. 좁으면 ⋯ 로 접힌다. */
3673
+ priority: z.ZodOptional<z.ZodEnum<["primary", "secondary"]>>;
2350
3674
  }, "strip", z.ZodTypeAny, {
2351
3675
  type: "linkButton";
2352
- text: string;
2353
3676
  url: string;
3677
+ text: string;
2354
3678
  style?: "danger" | "default" | "primary" | undefined;
3679
+ priority?: "primary" | "secondary" | undefined;
2355
3680
  external?: boolean | undefined;
2356
3681
  }, {
2357
3682
  type: "linkButton";
2358
- text: string;
2359
3683
  url: string;
3684
+ text: string;
2360
3685
  style?: "danger" | "default" | "primary" | undefined;
3686
+ priority?: "primary" | "secondary" | undefined;
2361
3687
  external?: boolean | undefined;
2362
3688
  }>, z.ZodObject<{
2363
3689
  type: z.ZodLiteral<"actions">;
2364
- elements: z.ZodArray<z.ZodUnion<[z.ZodObject<{
2365
- type: z.ZodLiteral<"button">;
2366
- /** 어떤 액션인지 식별. 클릭 시 org.corp.ui.action.action_id 로 회신됨. */
2367
- action_id: z.ZodString;
2368
- text: z.ZodString;
2369
- style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
2370
- /** 버튼 고유 페이로드 (폼 값과 별개로 함께 전송) */
2371
- value: z.ZodOptional<z.ZodString>;
2372
- confirm: z.ZodOptional<z.ZodObject<{
2373
- title: z.ZodString;
2374
- text: z.ZodString;
2375
- ok: z.ZodOptional<z.ZodString>;
2376
- cancel: z.ZodOptional<z.ZodString>;
2377
- }, "strip", z.ZodTypeAny, {
2378
- title: string;
2379
- text: string;
2380
- ok?: string | undefined;
2381
- cancel?: string | undefined;
2382
- }, {
2383
- title: string;
2384
- text: string;
2385
- ok?: string | undefined;
2386
- cancel?: string | undefined;
2387
- }>>;
2388
- disabled: z.ZodOptional<z.ZodBoolean>;
2389
- /**
2390
- * 이 MXID 들에게는 버튼을 **감춘다**(뷰어별 어포던스).
2391
- *
2392
- * 왜 필요한가: 카드 한 장은 방 전체가 같이 본다. 그런데 "이 사람만 절대 못 누르는 버튼"이 있다 —
2393
- * Forgejo 는 **자기 PR 자기 승인**을 422 로 거절한다(`approve your own pull is not allowed`).
2394
- * 그래서 작성자에게 Approve 를 보여 주면 눌러도 실패 카드만 쌓인다. 카드 전체에서 버튼을 빼면
2395
- * 남들이 승인을 못 하므로, 판정은 **보는 사람별**이어야 한다.
2396
- *
2397
- * 🔴 **권한이 아니다.** 진짜 게이트는 언제나 서버다(disabled/confirm 과 같은 자세) — 이건 없는
2398
- * 어포던스를 안 보여 주기 위한 것뿐이다. 그래서 이 키를 모르는 옛 클라이언트가 버튼을 그대로
2399
- * 보여 줘도 안전하다(누르면 서버가 사람이 읽을 이유와 함께 거절한다).
2400
- */
2401
- hidden_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
2402
- }, "strip", z.ZodTypeAny, {
2403
- type: "button";
2404
- text: string;
2405
- action_id: string;
2406
- value?: string | undefined;
2407
- style?: "danger" | "default" | "primary" | undefined;
2408
- confirm?: {
2409
- title: string;
2410
- text: string;
2411
- ok?: string | undefined;
2412
- cancel?: string | undefined;
2413
- } | undefined;
2414
- disabled?: boolean | undefined;
2415
- hidden_for?: string[] | undefined;
2416
- }, {
2417
- type: "button";
2418
- text: string;
2419
- action_id: string;
2420
- value?: string | undefined;
2421
- style?: "danger" | "default" | "primary" | undefined;
2422
- confirm?: {
2423
- title: string;
2424
- text: string;
2425
- ok?: string | undefined;
2426
- cancel?: string | undefined;
2427
- } | undefined;
2428
- disabled?: boolean | undefined;
2429
- hidden_for?: string[] | undefined;
2430
- }>, z.ZodObject<{
2431
- type: z.ZodLiteral<"linkButton">;
2432
- text: z.ZodString;
2433
- /** 이동할 https URL. 클라이언트가 출처를 검증(아니면 비활성 표시). */
2434
- url: z.ZodString;
2435
- style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
2436
- /** 새 탭으로 열기(기본 true). */
2437
- external: z.ZodOptional<z.ZodBoolean>;
2438
- }, "strip", z.ZodTypeAny, {
2439
- type: "linkButton";
2440
- text: string;
2441
- url: string;
2442
- style?: "danger" | "default" | "primary" | undefined;
2443
- external?: boolean | undefined;
2444
- }, {
2445
- type: "linkButton";
2446
- text: string;
2447
- url: string;
2448
- style?: "danger" | "default" | "primary" | undefined;
2449
- external?: boolean | undefined;
2450
- }>]>, "many">;
3690
+ elements: z.ZodArray<z.ZodType<ActionElement, z.ZodTypeDef, ActionElement>, "many">;
2451
3691
  }, "strip", z.ZodTypeAny, {
2452
3692
  type: "actions";
2453
- elements: ({
2454
- type: "button";
2455
- text: string;
2456
- action_id: string;
2457
- value?: string | undefined;
2458
- style?: "danger" | "default" | "primary" | undefined;
2459
- confirm?: {
2460
- title: string;
2461
- text: string;
2462
- ok?: string | undefined;
2463
- cancel?: string | undefined;
2464
- } | undefined;
2465
- disabled?: boolean | undefined;
2466
- hidden_for?: string[] | undefined;
2467
- } | {
2468
- type: "linkButton";
2469
- text: string;
2470
- url: string;
2471
- style?: "danger" | "default" | "primary" | undefined;
2472
- external?: boolean | undefined;
2473
- })[];
3693
+ elements: ActionElement[];
2474
3694
  }, {
2475
3695
  type: "actions";
2476
- elements: ({
2477
- type: "button";
2478
- text: string;
2479
- action_id: string;
2480
- value?: string | undefined;
2481
- style?: "danger" | "default" | "primary" | undefined;
2482
- confirm?: {
2483
- title: string;
2484
- text: string;
2485
- ok?: string | undefined;
2486
- cancel?: string | undefined;
2487
- } | undefined;
2488
- disabled?: boolean | undefined;
2489
- hidden_for?: string[] | undefined;
2490
- } | {
2491
- type: "linkButton";
2492
- text: string;
2493
- url: string;
2494
- style?: "danger" | "default" | "primary" | undefined;
2495
- external?: boolean | undefined;
2496
- })[];
3696
+ elements: ActionElement[];
2497
3697
  }>, z.ZodObject<{
2498
3698
  type: z.ZodLiteral<"overflow">;
2499
3699
  /** 트리거 접근성 라벨(기본 "More actions"). */
@@ -2521,6 +3721,12 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2521
3721
  cancel?: string | undefined;
2522
3722
  }>>;
2523
3723
  disabled: z.ZodOptional<z.ZodBoolean>;
3724
+ /** 이 MXID 들에게만 항목을 보인다 (0.7.0) — `ButtonBlockSchema.visible_for` 와 같은 규칙. 🔴 UX 다, 진실은 서버. */
3725
+ visible_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
3726
+ /** 이 MXID 들에게 항목을 감춘다 (0.7.0) — 둘 다 있으면 이쪽이 이긴다(버튼과 같은 규칙). */
3727
+ hidden_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
3728
+ /** 잠기거나 감춰진 이유 한 줄 (0.7.0, 작성자 소유 문장). 🔴 UX 다, 진실은 서버. */
3729
+ disabled_reason: z.ZodOptional<z.ZodString>;
2524
3730
  }, "strip", z.ZodTypeAny, {
2525
3731
  text: string;
2526
3732
  action_id: string;
@@ -2533,6 +3739,9 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2533
3739
  cancel?: string | undefined;
2534
3740
  } | undefined;
2535
3741
  disabled?: boolean | undefined;
3742
+ hidden_for?: string[] | undefined;
3743
+ visible_for?: string[] | undefined;
3744
+ disabled_reason?: string | undefined;
2536
3745
  }, {
2537
3746
  text: string;
2538
3747
  action_id: string;
@@ -2545,6 +3754,9 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2545
3754
  cancel?: string | undefined;
2546
3755
  } | undefined;
2547
3756
  disabled?: boolean | undefined;
3757
+ hidden_for?: string[] | undefined;
3758
+ visible_for?: string[] | undefined;
3759
+ disabled_reason?: string | undefined;
2548
3760
  }>, "many">;
2549
3761
  }, "strip", z.ZodTypeAny, {
2550
3762
  type: "overflow";
@@ -2560,6 +3772,9 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2560
3772
  cancel?: string | undefined;
2561
3773
  } | undefined;
2562
3774
  disabled?: boolean | undefined;
3775
+ hidden_for?: string[] | undefined;
3776
+ visible_for?: string[] | undefined;
3777
+ disabled_reason?: string | undefined;
2563
3778
  }[];
2564
3779
  label?: string | undefined;
2565
3780
  }, {
@@ -2576,6 +3791,9 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2576
3791
  cancel?: string | undefined;
2577
3792
  } | undefined;
2578
3793
  disabled?: boolean | undefined;
3794
+ hidden_for?: string[] | undefined;
3795
+ visible_for?: string[] | undefined;
3796
+ disabled_reason?: string | undefined;
2579
3797
  }[];
2580
3798
  label?: string | undefined;
2581
3799
  }>]>;