Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/security-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ jobs:
run: |
GITLEAKS_FILE="gitleaks_8.24.2_linux_x64.tar.gz"
curl -sSLo "$GITLEAKS_FILE" "https://github.com/gitleaks/gitleaks/releases/download/v8.24.2/$GITLEAKS_FILE"
curl -sSLo gitleaks_checksums.txt "https://github.com/gitleaks/gitleaks/releases/download/v8.24.2/gitleaks_8.24.2_checksums.txt"
curl -sSLo gitleaks_checksums.txt \
"https://github.com/gitleaks/gitleaks/releases/download/v8.24.2/gitleaks_8.24.2_checksums.txt"
grep "$GITLEAKS_FILE" gitleaks_checksums.txt | sha256sum -c -
tar -xzf "$GITLEAKS_FILE" gitleaks
chmod +x gitleaks
Expand All @@ -41,7 +42,8 @@ jobs:
ACTIONLINT_FILE="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
ACTIONLINT_BASE_URL="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}"
curl -sSLo "$ACTIONLINT_FILE" "${ACTIONLINT_BASE_URL}/${ACTIONLINT_FILE}"
curl -sSLo actionlint_checksums.txt "${ACTIONLINT_BASE_URL}/actionlint_${ACTIONLINT_VERSION}_checksums.txt"
curl -sSLo actionlint_checksums.txt \
"${ACTIONLINT_BASE_URL}/actionlint_${ACTIONLINT_VERSION}_checksums.txt"
grep "$ACTIONLINT_FILE" actionlint_checksums.txt | sha256sum -c -
tar -xzf "$ACTIONLINT_FILE" actionlint
chmod +x actionlint
Expand Down
13 changes: 13 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
# bolt.md

## 2024-07-04 - R μ–Έμ–΄μ—μ„œ 루프 λ‚΄ 데이터 ν”„λ ˆμž„ 탐색 병λͺ© μ΅œμ ν™”

**Learning:** Rμ—μ„œ 루프λ₯Ό λŒλ©΄μ„œ 맀번 데이터 ν”„λ ˆμž„μ„ μ„œλΈŒμ…‹νŒ…(subsetting)ν•˜λŠ” μž‘μ—…μ€ 볡사 μ˜€λ²„ν—€λ“œλ‘œ 인해 맀우 느렀질 수 μžˆμŠ΅λ‹ˆλ‹€. 특히 곡톡 λ¬Έν•­ μˆ˜κ°€ λ§Žμ•„μ§ˆ 경우 O(N^2)의 λΉ„νš¨μœ¨μ„ μ΄ˆλž˜ν•©λ‹ˆλ‹€.
**Action:** 루프 λ‚΄μ—μ„œ μˆ˜ν–‰ν•˜λ˜ 데이터 ν”„λ ˆμž„ 쑰회λ₯Ό 루프 μ™ΈλΆ€μ—μ„œ ν•œ λ²ˆμ— `as.character(unlist(...))`둜 μ²˜λ¦¬ν•˜λŠ” 벑터 μ—°μ‚°μœΌλ‘œ λ³€κ²½ν•˜μ—¬ νƒ€μž… λ³€ν™˜ 없이 O(1) μˆ˜μ€€μœΌλ‘œ μ„±λŠ₯을 크게 ν–₯μƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

## 2024-07-07 - R μ–Έμ–΄μ—μ„œ 데이터 ν”„λ ˆμž„μ˜ νŠΉμ • ν•­λͺ© 탐색을 μΊμ‹±ν•˜μ—¬ O(N) 검색 병λͺ© μ΅œμ ν™”

**Learning:** Rμ—μ„œ 반볡문 λ‚΄λΆ€μ—μ„œ νŠΉμ • 쑰건을 λ§Œμ‘±ν•˜λŠ” λ°μ΄ν„°μ˜ μœ„μΉ˜λ₯Ό μ°ΎκΈ° μœ„ν•΄ `which()`λ₯Ό μ—¬λŸ¬ 번 반볡 ν˜ΈμΆœν•˜λŠ” 것은 O(N) μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ Έ 맀번 λΆˆν•„μš”ν•œ λ°°μ—΄ μŠ€μΊ”μ„ μœ λ°œν•©λ‹ˆλ‹€. μ΄λŠ” λ£¨ν”„μ˜ 반볡 νšŸμˆ˜κ°€ 많고, 탐색해야할 데이터가 클 수둝 μ„±λŠ₯ μ €ν•˜μ˜ μ£Ό 원인이 λ©λ‹ˆλ‹€.
**Action:** 쑰건에 λ§žλŠ” 인덱슀λ₯Ό 졜초 탐색 μ‹œ λ³€μˆ˜μ— 캐싱(`newIdx`, `oldIdx` λ“±)ν•˜μ—¬ μ €μž₯ν•˜κ³  이후 λ™μΌν•œ 데이터 μ ‘κ·Ό μ‹œ μΊμ‹±λœ 인덱슀λ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ¨ O(1) μˆ˜μ€€μœΌλ‘œ μ„±λŠ₯을 ν–₯μƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. μΆ”κ°€λ‘œ 슀칼라 값에 λŒ€ν•œ λΆˆν•„μš”ν•œ `paste0()` ν•¨μˆ˜ ν˜ΈμΆœμ„ μ œκ±°ν•˜μ—¬ μ˜€λ²„ν—€λ“œλ₯Ό μ€„μž…λ‹ˆλ‹€.

## 2024-07-08 - R μ–Έμ–΄μ—μ„œ 루프 λ‚΄ 인덱슀 검색(which) O(N) 병λͺ© μ΅œμ ν™”

**Learning:** Rμ—μ„œ 반볡문 λ‚΄λΆ€μ—μ„œ νŠΉμ • 쑰건을 λ§Œμ‘±ν•˜λŠ” λ°μ΄ν„°μ˜ μœ„μΉ˜λ₯Ό μ°ΎκΈ° μœ„ν•΄ `which()`λ₯Ό μ—¬λŸ¬ 번 ν˜ΈμΆœν•˜λ©΄ 맀번 O(N)의 μ„ ν˜• 탐색(linear scan)이 λ°œμƒν•˜μ—¬ 데이터 크기가 클수둝 μ„±λŠ₯이 크게 μ €ν•˜λ©λ‹ˆλ‹€. λ˜ν•œ `paste0()`λ₯Ό μ΄μš©ν•œ λΆˆν•„μš”ν•œ λ°°μ—΄ λ‹¨μœ„ λ¬Έμžμ—΄ 생성은 반볡문 μ˜€λ²„ν—€λ“œλ₯Ό κ°€μ€‘μ‹œν‚΅λ‹ˆλ‹€.
**Action:** 쑰건에 λ§žλŠ” 인덱슀λ₯Ό 졜초 ν•œ 번 `split(seq_len(nrow(df)), df$column)`λ₯Ό 톡해 리슀트 ν˜•νƒœλ‘œ 캐싱(dictionary lookup)ν•˜μ—¬ 루프 μ™ΈλΆ€μ—μ„œ O(1) 검색 μ²΄κ³„λ‘œ λ§Œλ“€κ³ , 슀칼라 값에 λŒ€ν•œ λΆˆν•„μš”ν•œ `paste0()` ν•¨μˆ˜ ν˜ΈμΆœμ„ μ΅œμ ν™”(`paste(..., collapse=' ')`)ν•˜μ—¬ μ˜€λ²„ν—€λ“œλ₯Ό μ€„μž…λ‹ˆλ‹€.

## 2026-07-11 - R μ–Έμ–΄μ—μ„œ 루프 λ‚΄ 벑터 동적 ν™•μž₯ 및 쑰건뢀 탐색 μ΅œμ ν™”

**Learning:** Rμ—μ„œ for 루프 내에 λ™μ μœΌλ‘œ 벑터 크기λ₯Ό λŠ˜λ¦¬λ©΄μ„œ (`vector[i] <- value`) 쑰건을 κ²€μ‚¬ν•˜λŠ” 것은 O(N^2)의 볡사 μ˜€λ²„ν—€λ“œ(copy-on-modify)λ₯Ό λ°œμƒμ‹œν‚€λ©° λ§€ λ°˜λ³΅λ§ˆλ‹€ `match()` μŠ€μΊ”μ„ μˆ˜ν–‰ν•˜λ©΄ μ„±λŠ₯ μ €ν•˜λ₯Ό μ΄ˆλž˜ν•©λ‹ˆλ‹€.
**Action:** 루프 외뢀에 λ²‘ν„°ν™”λœ `match()`λ₯Ό ν•œ 번만 μˆ˜ν–‰ν•˜μ—¬ μœ νš¨ν•œ 인덱슀λ₯Ό μ°Ύκ³ , 벑터 인덱싱(`vector[idx]`)으둜 ν•œ λ²ˆμ— 데이터λ₯Ό μΆ”μΆœν•˜μ—¬ λΆˆν•„μš”ν•œ 루프 μ˜€λ²„ν—€λ“œ 및 동적 λ©”λͺ¨λ¦¬ μž¬ν• λ‹Ήμ„ λ°©μ§€ν•˜μ—¬ O(1) μˆ˜μ€€μœΌλ‘œ μ„±λŠ₯을 κ°œμ„ ν•΄μ•Ό ν•©λ‹ˆλ‹€.

## 2024-07-12 - R μ–Έμ–΄μ—μ„œ λ°μ΄ν„°ν”„λ ˆμž„ μ„œλΈŒμ…‹νŒ… μ‹œ λΆˆν•„μš”ν•œ which() 및 반볡 평가 제거

**Learning:** 데이터 ν”„λ ˆμž„μ˜ νŠΉμ • 둜우(row)λ₯Ό λ³€κ²½ν•  λ•Œ `df[which(df$col == "val"), ]`와 같이 `which()`λ₯Ό μ‚¬μš©ν•˜λ©΄ λ‚΄λΆ€μ μœΌλ‘œ μΆ”κ°€ ν•¨μˆ˜ 호좜 및 논리 벑터 평가 μ˜€λ²„ν—€λ“œκ°€ λ°œμƒν•©λ‹ˆλ‹€. λ˜ν•œ, μ—¬λŸ¬ 값을 μ—…λ°μ΄νŠΈν•˜κΈ° μœ„ν•΄ λ™μΌν•œ 쑰건식을 μ—°μ†μœΌλ‘œ μ‚¬μš©ν•˜λ©΄ 맀번 λ™μΌν•œ O(N) 논리 벑터 평가가 μ€‘λ³΅ν•΄μ„œ μΌμ–΄λ‚©λ‹ˆλ‹€. λΆˆν•„μš”ν•œ `paste0("GROUP")` ν˜ΈμΆœλ„ μ˜€λ²„ν—€λ“œλ₯Ό λ”ν•©λ‹ˆλ‹€.
**Action:** `which()`λ₯Ό μƒλž΅ν•˜κ³  직접 논리 인덱싱(`df$col == "val"`)을 μ‚¬μš©ν•˜λ©°, λ™μΌν•œ 쑰건식을 두 번 이상 μ—°μ†μœΌλ‘œ μ‚¬μš©ν•  경우 ν•΄λ‹Ή 논리 벑터λ₯Ό λ³€μˆ˜μ— 캐싱(`idx <- df$col == "val"`)ν•˜μ—¬ μ—¬λŸ¬ 번 μž¬μ‚¬μš©ν•¨μœΌλ‘œμ¨ μ€‘λ³΅λœ O(N) μ„ ν˜• μŠ€μΊ”μ„ ν”Όν•˜κ³  μ„±λŠ₯을 μ΅œμ ν™”ν•΄μ•Ό ν•©λ‹ˆλ‹€. λ˜ν•œ λΆˆν•„μš”ν•œ λ¬Έμžμ—΄ 연산을 μ œκ±°ν•©λ‹ˆλ‹€.

## 2025-02-12 - R μ–Έμ–΄μ—μ„œ 반볡적인 mirt λͺ¨λΈ 생성 μ‹œ λΆˆν•„μš”ν•œ λ°μ΄ν„°ν”„λ ˆμž„ λΆ€λΆ„μ§‘ν•© μΆ”μΆœ μ΅œμ ν™”

**Learning:** Rμ—μ„œ λ°μ΄ν„°ν”„λ ˆμž„μ˜ νŠΉμ • 열을 μΆ”μΆœν•˜λŠ” μž‘μ—…(`df[cols]`)은 O(N)의 λ©”λͺ¨λ¦¬ 볡사λ₯Ό μˆ˜λ°˜ν•©λ‹ˆλ‹€. `autoFIPC`μ—μ„œ `mirt` λͺ¨λΈμ˜ νŒŒλΌλ―Έν„°λ₯Ό μ„€μ •ν•˜κ±°λ‚˜ ν˜ΈμΆœν•˜λŠ” κ³Όμ • 쀑에 `newformXDataK[colnames(newFormModel@Data$data)]` μ½”λ“œκ°€ λ°˜λ³΅ν•΄μ„œ μ‚¬μš©λ˜μ—ˆκ³ , 심지어 `ncol()`을 μœ„ν•΄ λ‹¨μˆœνžˆ 개수λ₯Ό ꡬ할 λ•Œλ„ μ‚¬μš©λ˜μ–΄ λΆˆν•„μš”ν•œ λ©”λͺ¨λ¦¬ ν• λ‹Ήκ³Ό μ˜€λ²„ν—€λ“œλ₯Ό μ΄ˆλž˜ν–ˆμŠ΅λ‹ˆλ‹€.
**Action:** μ‘°κ±΄λ¬Έμ΄λ‚˜ 반볡문 λ‚΄λΆ€μ—μ„œ λΆˆν•„μš”ν•˜κ²Œ λ°μ΄ν„°ν”„λ ˆμž„ λΆ€λΆ„μ§‘ν•© 연산이 λ°˜λ³΅λ˜μ§€ μ•Šλ„λ‘ μ™ΈλΆ€μ—μ„œ ν•œ 번만 `linkedFormData <- newformXDataK[colnames(newFormModel@Data$data)]`둜 캐싱(caching)ν•œ λ’€, `ncol(linkedFormData)`와 `data = linkedFormData` ν˜•νƒœλ‘œ μž¬μ‚¬μš©ν•˜μ—¬ λ©”λͺ¨λ¦¬ 볡사와 O(N) μ˜€λ²„ν—€λ“œλ₯Ό λ°©μ§€ν•΄μ•Ό ν•©λ‹ˆλ‹€.
4 changes: 4 additions & 0 deletions .jules/palette.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# palette.md

## 2024-06-24 - Pure R Backend Package

**Learning:** The aFIPC repository is a pure R backend package without any frontend web components or UI. Therefore, standard micro-UX enhancements such as ARIA labels, loading states, and CSS styling cannot be applied.
**Action:** Stop and do not create a PR, as no suitable web UX enhancements can be identified.

## 2026-06-30 - No Frontend Surface

**Learning:** The package contains R calibration code and package metadata, not HTML, React, CSS, or other UI surfaces.
**Action:** Palette tasks should stop after recording that no UX enhancement applies unless a future frontend artifact is introduced.
9 changes: 9 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# sentinel.md

## 2024-07-12 - Fix missing parameter validations

**Vulnerability:** Unvalidated inputs passed to `if()` statements can cause process crashes (`condition has length > 1`) or unexpected coercion vulnerabilities.
**Learning:** In R, optional boolean parameters that default to `NULL` should be validated using explicit runtime type validation (e.g., `if (!is.null(flag) && (!is.logical(flag) || length(flag) != 1 || is.na(flag)))`).
**Prevention:** Always implement explicit runtime type validation for optional boolean parameters.

## 2024-08-10 - [Integer Overflow Coercion Vulnerability μˆ˜μ •]

**Vulnerability:** `readline()` μž…λ ₯κ°’ 검증 μ‹œ `^[0-9]+$` μ •κ·œν‘œν˜„μ‹μ„ μ‚¬μš©ν•˜μ—¬ μˆ«μžν˜• λ¬Έμžμ—΄μ„ κ²€μ¦ν•˜κ³  `as.integer()`둜 λ³€ν™˜ν•˜λŠ” κ³Όμ •μ—μ„œ, μ§€λ‚˜μΉ˜κ²Œ 큰 μˆ«μžκ°€ μž…λ ₯되면 Rμ—μ„œ μ •μˆ˜ λ²”μœ„λ₯Ό μ΄ˆκ³Όν•˜μ—¬ `NA`λ₯Ό λ°˜ν™˜ν•˜λŠ” μ˜€λ²„ν”Œλ‘œμš° κ°•μ œ λ³€ν™˜(coercion) 취약점이 λ°œκ²¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
**Learning:** `^[0-9]+$`λŠ” 자릿수 μ œν•œμ΄ μ—†κΈ° λ•Œλ¬Έμ— μ˜λ„ν•˜μ§€ μ•Šμ€ 큰 μˆ˜κ°€ μž…λ ₯될 수 있으며, 이 값이 μ •μˆ˜λ‘œ λ³€ν™˜λ  λ•Œ `NA`κ°€ λ˜μ–΄ μ΄ν›„μ˜ 둜직(예: ν”„λ‘œμ„ΈμŠ€ ν¬λž˜μ‹œ)에 치λͺ…적인 영ν–₯을 λ―ΈμΉ  수 μžˆμŠ΅λ‹ˆλ‹€.
**Prevention:** 1κ³Ό 2 같은 μ œν•œμ μΈ 선택지λ₯Ό μš”κ΅¬ν•  λ•ŒλŠ” μ •ν™•νžˆ μΌμΉ˜ν•˜λŠ” λ²”μœ„λ§Œ ν—ˆμš©ν•˜λ„λ‘ `^[12]$` 와 같이 μ—„κ²©ν•œ μ •κ·œν‘œν˜„μ‹μ„ μ μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
6 changes: 2 additions & 4 deletions .yamllint.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
extends: default

rules:
line-length: disable
document-start: disable
line-length:
max: 140
truthy:
allowed-values: ["true", "false", "on", "off"]
truthy: disable
6 changes: 3 additions & 3 deletions R/aFIPC.R
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ autoFIPC <-
}
for (attempt in seq_len(3)) {
n <- readline(prompt = "Is it correct? (1: Yes 2: No) : ")
if (grepl("^[0-9]+$", n)) {
if (grepl("^[12]$", n)) {
return(as.integer(n))
}
}
Expand Down Expand Up @@ -171,7 +171,7 @@ autoFIPC <-
readline(
prompt = "Do you want to use default BILOG-MG priors for oldform Data? (1: Yes 2: No) : "
)
if (grepl("^[0-9]+$", n)) {
if (grepl("^[12]$", n)) {
return(as.integer(n))
}
}
Expand Down Expand Up @@ -390,7 +390,7 @@ autoFIPC <-
readline(
prompt = "Do you want to use default BILOG-MG priors for newform Data? (1: Yes 2: No) : "
)
if (grepl("^[0-9]+$", n)) {
if (grepl("^[12]$", n)) {
return(as.integer(n))
}
}
Expand Down
Binary file added actionlint
Binary file not shown.
Binary file added actionlint_1.7.10_linux_amd64.tar.gz
Binary file not shown.
11 changes: 11 additions & 0 deletions actionlint_checksums.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
16782c41f2af264db80f855ee5d09164ca98fc78edf3bcd0f46eecff279682ba actionlint_1.7.10_darwin_amd64.tar.gz
004ca87b367b37f4d75c55ab6cf80f9b8c043adbfbd440f31c604d417939c442 actionlint_1.7.10_darwin_arm64.tar.gz
31ec5ee4deef04edf3b9eb3bac5243d785b5dccf70688e02a022b0723bfae80a actionlint_1.7.10_freebsd_386.tar.gz
418461873e1f8eb7acc7524d70d4c33e99f9aab53da8625f4a3c50273612c930 actionlint_1.7.10_freebsd_amd64.tar.gz
b728a3c31f7bd37d3026a7cd87148da9ddf845b5d56213fcc410bb222523c7d0 actionlint_1.7.10_linux_386.tar.gz
f4c76b71db5755a713e6055cbb0857ed07e103e028bda117817660ebadb4386f actionlint_1.7.10_linux_amd64.tar.gz
cd3dfe5f66887ec6b987752d8d9614e59fd22f39415c5ad9f28374623f41773a actionlint_1.7.10_linux_arm64.tar.gz
7624bae3f6e41985f498de7b246a2334cd734b9f1a8f04a9748429cbcf99b750 actionlint_1.7.10_linux_armv6.tar.gz
1783f8a1dd59a67dae373e753a88592351e00128195bc9ddd2b836a0c31df71b actionlint_1.7.10_windows_386.zip
283467f9d6202a8cb8c00ad8dd0ee4e685b71fb86a6a56c68fcbb9ae8ed91237 actionlint_1.7.10_windows_amd64.zip
0c7242bca2f0ee4672a00ce7fa3c7185311fb94cb9e1e0f6bb57d5456e421d80 actionlint_1.7.10_windows_arm64.zip
Loading