fix(core,engine): OFFSET 순회 중 필터 컬럼 변경으로 인한 처리 누락 수정

Laravel chunk/each 는 OFFSET 기반이라, 콜백이 행의 필터 소속을 바꾸면
(필터 컬럼을 채우거나 매칭 행을 삭제하면) 다음 조회가 그만큼 앞으로 밀려
미처리 행을 조용히 건너뛴다. 250건/청크 100 이면 정확히 100건이 남는다.
코어·번들 확장 전수 조사로 확정한 6곳을 chunkById(키셋 순회)로 통일했다.

브라우저 검수(28축)에서 계획에 없던 결함 12건이 드러나 같은 사슬에서
수정했다. 이 중 layout_strategy=keep 무효화와 수정 감지 실패 시 "수정 없음"
오보는 사용자 작업 소실에 직결된다.

재발 방지로 audit 룰을 추가했고, 수정 6곳을 원복해 red 6건 / 복원 후 green
0건으로 판별력을 검증했다.
This commit is contained in:
HeuJung committed 2026-07-31 21:50:45 +09:00
1 parent 1866f0d566
commit 1eedbbdda1
55 files changed
+2764 -198

No files matched your search

+31 -4
View File
@@ -1064,11 +1064,38 @@ Authorization: Bearer {YOUR_TOKEN}
**응답 필드** (`data` 내부)
<!-- 실측 제외: unresolved-path-param — 응답 필드는 사람이 작성하세요. -->
| 필드 | 타입 | 설명 |
| --- | --- | --- |
| has_modified_layouts | boolean | 수정된 레이아웃 존재 여부 |
| modified_count | integer | 수정된 레이아웃 수 |
| modified_layouts | array | 수정된 레이아웃 목록 |
| modified_layouts[].id | integer | 레이아웃 ID |
| modified_layouts[].name | string | 레이아웃 이름 |
| modified_layouts[].updated_at | string\|null | 최종 수정 일시 (`Y-m-d H:i:s`) |
| modified_layouts[].size_diff | integer | 원본 대비 바이트 증감 (음수는 축소) |
**응답 예시**
<!-- 실측 제외: unresolved-path-param — 응답 예시는 사람이 작성하세요. -->
```json
{
"success": true,
"message": "수정된 레이아웃 확인이 완료되었습니다.",
"data": {
"has_modified_layouts": true,
"modified_count": 1,
"modified_layouts": [
{
"id": 47,
"name": "sirsoft-board.admin_board_index",
"updated_at": "2026-07-31 09:20:05",
"size_diff": 28
}
]
}
}
```
집계 범위는 해당 플러그인이 **소유한** 레이아웃으로 한정됩니다. 같은 템플릿에 등록된 다른 확장의 레이아웃은 포함되지 않습니다.
**에러 응답**
@@ -1076,7 +1103,7 @@ Authorization: Bearer {YOUR_TOKEN}
| --- | --- | --- |
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(`core.plugins.read`)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 404 | Not Found | 해당 식별자의 플러그인이 설치되어 있지 않은 경우 (레이아웃 0건과 구분됨) |
<!-- @generated:end -->
@@ -1219,7 +1246,7 @@ Content-Type: application/json
<!-- @generated:end -->
**설명** 특정 플러그인을 최신 버전으로 업데이트합니다. `core.plugins.install` 권한이 필요합니다. `layout_strategy` 로 레이아웃 처리 방식을(overwrite: 새 버전으로 교체, keep: 사용자 수정본 유지) 지정하며, `vendor_mode` 로 Composer 의존성 처리 방식을 선택합니다. 버전 제약·호환성 문제로 막힐 경우 `force: true` 로 강제 진행할 수 있습니다.
**설명** 특정 플러그인을 최신 버전으로 업데이트합니다. `core.plugins.install` 권한이 필요합니다. `layout_strategy` 로 레이아웃 처리 방식을(overwrite: 새 버전으로 교체, keep: 사용자 수정본 유지) 지정하며, `vendor_mode` 로 Composer 의존성 처리 방식을 선택합니다. 버전 제약·호환성 문제로 막힐 경우 `force: true` 로 강제 진행할 수 있습니다. `keep` 을 지정하면 사용자가 수정한 레이아웃(원본 해시와 현재 내용이 다른 레이아웃)은 갱신 대상에서 제외되어 현재 내용이 그대로 유지되고, 나머지 레이아웃만 파일 기준으로 갱신됩니다. 성공 응답 메시지에는 대상 식별자와 적용된 버전이 채워집니다.
### GET /api/plugins/assets/{identifier}/{path}