Files
Gnuboard7/tests/scenarios/layout-editor-action-flex-condition.yaml
HeuJung 71abdeaf60 fix(security): KVE-2026-1914/1915/1919 remediation 전건
위임 관리자(부관리자)가 권한·역할·표현식·비밀 콘텐츠 경계를 우회하던
결함군을 계층 대칭성 원칙으로 전건 차단한다. 약한 경로가 정상 응답을
내보내는 것이 유일한 증상이라, 게이트를 생산 지점 한 곳(SSoT)에 두고
같은 데이터를 내보내는 소비 경로 전부가 그 게이트를 경유하도록 맞췄다.

- 등급 상한(rank ceiling): 슈퍼관리자 보호·역할/사용자 역할 배정(추가·제거
 대칭)·일괄 상태변경·순서변경을 상세 경로와 동일 강도로 재적용. 가드는
 DB 쓰기에 선행하여 거부 시 상태 불변.
- 레이아웃 표현식: new Function/with 실행을 AST 화이트리스트 평가기로 교체.
 비-문자열 computed 키 정규화(normalizeKey)·Object facade(리플렉션 static
 제거)·legacy 접근자 차단. 저장측 검증·정적 검사와 3계층 동형.
- secret 게이트: 비밀글의 댓글·첨부·문의 독립 경로 재적용, hash 파일서빙
 소유권·비밀·발행 상태 검사 통일.
- 신뢰 스크립트 호스트: 확장 선언 기반 + same-origin 브라우저 정규화를
 런타임·저장측·정적검사 3층 동형화.
- 회귀 감지: 단위·Feature·E2E·시나리오 매니페스트 전축 + audit 룰 4종 신설.
2026-08-17 01:45:09 +09:00

109 lines
6.5 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
feature: 레이아웃 편집기 액션 편집 · flex 편집 · 표시 조건
phase: 5
session: S7
issue: 383
# axis 의미:
# 본 매니페스트가 묶는 세 가지(액션 편집 / flex 편집 / 표시 조건)는 편집기 속성 패널의
# 서로 다른 탭이며 상호작용하지 않는다. flex 방향이 액션 레시피 조립을 바꾸지 않고,
# 조건 조합자가 flex 정렬을 바꾸지 않는다. 세 도메인의 축을 곱하면 134만 조합이 되지만
# 그중 실재하는 판정은 도메인 내부의 것뿐이다.
#
# axes 로 남긴 것: 액션 레시피 × 후속 체인.
# 레시피 종류에 따라 후속 체인이 성립하는지가 갈리므로(openModal 은 체인 없음)
# 이 둘만 실제로 교차한다.
axes:
action_recipe: [goToPage, showMessage, changeState, refreshData, callServerThen, openModal_lazy_id, custom_extension_recipe]
followup_chain: [none, success_and_error_both]
exclusions:
- { action_recipe: openModal_lazy_id, followup_chain: success_and_error_both,
reason: "openModal 은 onSuccess/onError 체인 의미 없음 — 즉시 모달 오픈" }
- { action_recipe: goToPage, followup_chain: success_and_error_both,
reason: "페이지 이동은 응답이 없어 후속 체인이 성립하지 않음" }
- { action_recipe: showMessage, followup_chain: success_and_error_both,
reason: "토스트 표시는 응답이 없어 후속 체인이 성립하지 않음" }
- { action_recipe: changeState, followup_chain: success_and_error_both,
reason: "상태 변경은 동기 — 후속 체인 없음" }
- { action_recipe: refreshData, followup_chain: success_and_error_both,
reason: "refreshData 레시피의 build 에 onSuccess/onError 자리가 없다(refetchDataSource + dataSourceId 뿐) — 후속 체인을 갖는 레시피는 callServerThen 하나다" }
sub_flows:
- id: action_event_slot
description: |
액션이 걸리는 이벤트 슬롯. 레시피 조립 결과와 곱해지지 않는다 — 같은 레시피가
어느 슬롯에 걸리든 산출 JSON 은 동일하고, 슬롯은 스펙 선언 여부만 가른다.
축: event_kind(onClick·onHover·onComponentEvent·lifecycle_onMount·lifecycle_onUnmount)
effects:
- spec_undeclared_event_hides_action_slot
- nested_action_list_widget_assembles_recursive_actions
- action_recipe_reverse_matches_existing_action_to_recipe
- action_recipe_does_not_expose_handler_jargon_to_user
- id: flex_editing
description: |
flex 컨테이너/아이템 편집. 액션·조건과 무관한 스타일 축이다.
축: flex_role(container·item·auto_div_detected_as_flex·auto_div_detected_as_block) ×
flex_direction(row·column) × flex_wrap × flex_justify × flex_align × item_grow
effects:
- flex_container_classToken_emits_per_spec_apply_type
- flex_auto_detection_uses_computed_style_not_classname
- flex_auto_detection_works_across_tailwind_bootstrap_native_css
- flex_item_align_self_emits_correct_recipe
- flex_item_order_property_set
- flex_make_box_button_when_not_rendered_as_flex
- id: display_condition
description: |
표시 조건(if) 빌더. 조건 카테고리 × 조합자 × 파라미터 종류가 이 도메인 안에서 교차한다.
축: condition_category(A~H) × condition_combinator(single·and·or·mixed_and_or) ×
condition_param_kind(no_param·ds_id·state_key·field_name·value_literal·ability_key)
effects:
- condition_recipe_substitutes_params_into_expr_template
- condition_recipe_wraps_entire_combined_expression_in_single_braces
- condition_builder_does_not_emit_nested_interpolation_braces
- condition_recipe_uses_optional_chaining_for_null_safety
- condition_recipe_array_length_uses_length_nullish_zero_fallback
- condition_synthesized_expr_evaluates_via_condition_evaluator
- condition_builder_reverse_matches_single_preset
- condition_builder_preserves_advanced_handwritten_expr
- condition_param_widget_dispatches_via_widget_registry
effects:
- action_recipe_build_emits_correct_handler_name_and_top_level_target
- action_recipe_top_level_onSuccess_onError_keys_not_in_params
- action_recipe_handler_name_follows_claude_md_critical_rules
- action_recipe_navigate_uses_navigate_not_nav
- action_recipe_apiCall_target_outside_params_to_avoid_resolvedTarget_undefined
- action_recipe_refetchDataSource_uses_dataSourceId_key_not_id
- action_recipe_toast_handler_not_showToast
- action_recipe_setState_target_top_level_not_in_params
- nested_action_list_widget_assembles_recursive_actions
- action_recipe_does_not_expose_handler_jargon_to_user
- action_recipe_reverse_matches_existing_action_to_recipe
- flex_container_classToken_emits_per_spec_apply_type
- flex_auto_detection_uses_computed_style_not_classname
- flex_auto_detection_works_across_tailwind_bootstrap_native_css
- flex_item_align_self_emits_correct_recipe
- flex_item_order_property_set
- flex_make_box_button_when_not_rendered_as_flex
- condition_recipe_substitutes_params_into_expr_template
- condition_recipe_wraps_entire_combined_expression_in_single_braces
- condition_builder_does_not_emit_nested_interpolation_braces
- condition_recipe_uses_optional_chaining_for_null_safety
- condition_recipe_array_length_uses_length_nullish_zero_fallback
- condition_synthesized_expr_evaluates_via_condition_evaluator
- condition_builder_reverse_matches_single_preset
- condition_builder_preserves_advanced_handwritten_expr
- spec_undeclared_event_hides_action_slot
- condition_param_widget_dispatches_via_widget_registry
test_files:
- resources/js/core/template-engine/layout-editor/__tests__/spec/actionRecipeEngine.test.ts
- resources/js/core/template-engine/layout-editor/__tests__/spec/conditionRecipeEngine.test.ts
- resources/js/core/template-engine/layout-editor/__tests__/spec/flexModel.test.ts
- resources/js/core/template-engine/layout-editor/__tests__/components/s7-property-controls.test.tsx
- resources/js/core/template-engine/layout-editor/__tests__/layouts/condition-toggle-render.test.tsx
e2e_files:
- tests/Playwright/specs/layout-editor/action-flex-condition.spec.ts
notes: |
액션/조건 레시피 적용기는 Pure Logic DataProvider (친화 입력 → 핸들러/식 JSON).
ActionRecipeEditor/ConditionBuilder/FlexEditor 는 Component RTL.
합성 if 식의 실제 평가는 condition-toggle-render (ConditionEvaluator 라운드트립).
Chrome MCP drag 비호환(dnd-kit) 으로 캔버스 클릭 가로채기 axis 는 코드경로+RTL 로 대체.