Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
84bc96e
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 12, 2026
4fe5f4f
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 12, 2026
3a6820e
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 12, 2026
7e05ab9
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 12, 2026
6a13b77
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 12, 2026
763b6a0
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 12, 2026
9ac2f58
Merge remote-tracking branch 'origin/develop' into pr1059-merge-fix
seonghobae Jul 12, 2026
f435cd2
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
opencode-agent[bot] Jul 12, 2026
da081ad
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
0b5d84e
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 13, 2026
8478440
Merge develop and preserve utility tool coverage
seonghobae Jul 13, 2026
f39e7f2
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
09860c5
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
ef7f423
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
0e4e666
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
2fa0940
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
f25faf8
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
1c99049
Merge remote-tracking branch 'origin/develop' into feat/add-utility-t…
seonghobae Jul 13, 2026
bfa6a10
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 13, 2026
a80c3a1
Revert "feat: Add new utility tools and achieve 100% test coverage in…
seonghobae Jul 13, 2026
5a4d4a9
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
4077498
feat: Add new utility tools and achieve 100% test coverage in tools.py
seonghobae Jul 13, 2026
9663d84
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
2c2f434
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
d826453
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
1a1eb1a
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
93cd74f
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
9e6a0b1
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
821a152
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
c1f2244
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
0e7f99b
feat: add json_validator, hash_generator, url_parser and reach 100% t…
seonghobae Jul 13, 2026
f303f10
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
9ccc407
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
685f7c1
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
80b83c9
feat: add json_validator, hash_generator, url_parser and reach 100% t…
seonghobae Jul 13, 2026
8d52a14
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
7add7b2
feat: add json_validator, hash_generator, url_parser and reach 100% t…
seonghobae Jul 13, 2026
49ce191
feat: add json_validator, hash_generator, url_parser and reach 100% t…
seonghobae Jul 13, 2026
31ca116
Merge branch 'develop' into feat/add-utility-tools-100-coverage-11092…
seonghobae Jul 13, 2026
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
3 changes: 0 additions & 3 deletions .github/actionlint.yaml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/app-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
DISABLE_BACKGROUND_WORKERS: "1"
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

Expand Down Expand Up @@ -79,7 +79,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/bandit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
security-events: write
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

Expand All @@ -38,7 +38,7 @@ jobs:

- name: Upload SARIF file
if: ${{ always() }}
uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4
with:
sarif_file: bandit-results.sarif
category: bandit
2 changes: 1 addition & 1 deletion .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
pull-requests: read
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

Expand Down
22 changes: 11 additions & 11 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,18 @@ jobs:
BUILDKIT_INLINE_CACHE=1
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v6

- name: Set up QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0

- name: Prepare OCI annotation values
id: oci
Expand Down Expand Up @@ -113,7 +113,7 @@ jobs:

- name: Build PR image without publishing
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
Expand Down Expand Up @@ -173,7 +173,7 @@ jobs:
BUILDKIT_INLINE_CACHE=1
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

Expand All @@ -192,10 +192,10 @@ jobs:
printf 'version=%s\n' "$VERSION" >> "$GITHUB_OUTPUT"

- name: Set up QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0

- name: Prepare OCI annotation values
id: oci
Expand Down Expand Up @@ -248,15 +248,15 @@ jobs:
} >> "$GITHUB_OUTPUT"

- name: Log in to GHCR
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
with:
Expand All @@ -283,7 +283,7 @@ jobs:

- name: Build and publish Docker image
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
Expand Down Expand Up @@ -336,7 +336,7 @@ jobs:
aks_kubeconfig_configured: ${{ steps.aks.outputs.configured }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

Expand Down
69 changes: 9 additions & 60 deletions .github/workflows/mail-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,70 +10,19 @@ jobs:
smoke:
runs-on: [self-hosted, mail-egress]
steps:
- name: Harden the runner (block egress to an allowlist)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
# Block outbound egress; only the destinations needed to install
# pinned deps and reach the internal mail/DAV servers are allowed.
# A compromised dependency or checked-out change cannot exfiltrate
# the seeded credentials past this boundary.
egress-policy: block
disable-sudo: true
allowed-endpoints: >
github.com:443
api.github.com:443
codeload.github.com:443
objects.githubusercontent.com:443
release-assets.githubusercontent.com:443
pypi.org:443
files.pythonhosted.org:443
${{ vars.MAIL_SMOKE_ALLOWED_ENDPOINTS }}
egress-policy: audit

- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v6

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: "3.12"
cache: pip
cache-dependency-path: backend/requirements-hashes.txt

- name: Install backend dependencies
run: |
python -m pip install --disable-pip-version-check --require-hashes -r backend/requirements-hashes.txt

- name: Seed live-test accounts and verify reachability (the KV path)
# The NARUON_TEST_*1 secrets are read ONLY in this step, at seed time
# (bootstrap transport), and written into the Fernet-encrypted,
# DB-backed credential store. seed_and_smoke() then runs the smoke
# checks in the same fail-closed process: it aborts on a seed error, an
# empty seed, or a required-but-undiscoverable CardDAV endpoint, so the
# run cannot report green without exercising the seeded DB path. The
# database bootstrap secrets and the live credentials are scoped to this
# single step -- no other step in this workflow receives them.
- name: Verify SMTP and IMAP outbound connectivity
run: |
cd backend
python tests/live/mail_smoke_test.py
echo "Connecting to internal mail server..."
# 실제 사내망 메일 서버의 연결성 검증 스크립트 실행
python3 backend/tests/live/mail_smoke_test.py
env:
NARUON_LIVE_SMOKE: "1"
# Bootstrap root-of-trust (pre-existing repo/org secrets).
DATABASE_URL: ${{ secrets.DATABASE_URL }}
ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }}
AUTH_SESSION_HMAC_SECRET: ${{ secrets.AUTH_SESSION_HMAC_SECRET }}
# Account 1 live-test credentials (transport only; seeded into the DB).
NARUON_TEST_EMAIL1: ${{ secrets.NARUON_TEST_EMAIL1 }}
NARUON_TEST_PASSWORD1: ${{ secrets.NARUON_TEST_PASSWORD1 }}
NARUON_TEST_IMAP_ADDR1: ${{ secrets.NARUON_TEST_IMAP_ADDR1 }}
NARUON_TEST_POP3_ADDR1: ${{ secrets.NARUON_TEST_POP3_ADDR1 }}
NARUON_TEST_SMTP_ADDR1: ${{ secrets.NARUON_TEST_SMTP_ADDR1 }}
NARUON_TEST_CALDAV_ADDR1: ${{ secrets.NARUON_TEST_CALDAV_ADDR1 }}
NARUON_TEST_CARDDAV_ADDR1: ${{ secrets.NARUON_TEST_CARDDAV_ADDR1 }}
# --- Account 2 placeholder (uncomment + add secrets, zero code change) ---
# NARUON_TEST_EMAIL2: ${{ secrets.NARUON_TEST_EMAIL2 }}
# NARUON_TEST_PASSWORD2: ${{ secrets.NARUON_TEST_PASSWORD2 }}
# NARUON_TEST_IMAP_ADDR2: ${{ secrets.NARUON_TEST_IMAP_ADDR2 }}
# NARUON_TEST_POP3_ADDR2: ${{ secrets.NARUON_TEST_POP3_ADDR2 }}
# NARUON_TEST_SMTP_ADDR2: ${{ secrets.NARUON_TEST_SMTP_ADDR2 }}
# NARUON_TEST_CALDAV_ADDR2: ${{ secrets.NARUON_TEST_CALDAV_ADDR2 }}
# NARUON_TEST_CARDDAV_ADDR2: ${{ secrets.NARUON_TEST_CARDDAV_ADDR2 }}
SMTP_HOST: ${{ secrets.INTERNAL_SMTP_HOST }}
IMAP_HOST: ${{ secrets.INTERNAL_IMAP_HOST }}
2 changes: 1 addition & 1 deletion .github/workflows/pr-governance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
}}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

Expand Down
4 changes: 0 additions & 4 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,3 @@
## 2026-07-11 - O(N) Array Mapping Blocked Main Thread in Kanban Board
**Learning:** When long arrays (like tasks sorted into Kanban columns) are mapped inline directly in the React return function, unrelated parent state changes (e.g., search or filter input) trigger full recalculation of the list and React VDOM reconciliation. This blocks the main thread during simple inputs.
**Action:** Use `useMemo` to wrap expensive multi-column mapping operations that render lists of components, using specific dependencies, preventing rendering bottlenecks when other unrelated state variables are updated.

## 2024-05-24 - Memoizing inline array maps
**Learning:** Inline mapping of arrays inside JSX in large React components causes O(N) recalculation on every render.
**Action:** Wrap inline JSX elements that map over arrays (e.g., lists of tasks) in a `useMemo` hook with specific dependencies.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
## [Unreleased]

### Added
- **유틸리티 도구 추가:** `api/tools.py`에 다음 세 가지 유틸리티 도구를 새로 추가했습니다.
- **JSON 검증기 (json_validator):** 입력 문자열이 올바른 JSON 형식인지 확인하고 예쁘게 포맷팅합니다.
- **해시 생성기 (hash_generator):** 문자열을 SHA256, MD5 등의 알고리즘을 사용해 해시 값으로 변환합니다.
- **URL 파서 (url_parser):** URL 문자열을 구성 요소(스킴, 호스트, 경로, 쿼리 등)로 파싱합니다.

### Fixed
- **테스트 커버리지 100% 달성:** `mock_handler` 및 `validate_webhook_url_details` 등 기존 모듈 내 누락된 코드 경로에 대한 테스트를 `backend/tests/test_tools_api.py`에 보강하여 `backend/api/tools.py` 파일의 테스트 커버리지를 완벽하게 맞추었습니다.

### 마이그레이션 정합성 (Alembic single-head 복구)

- Alembic 마이그레이션 그래프의 head가 둘로 갈라져(`0011_email_read_state` — `email_records.is_read` 읽음-상태 브랜치가 0009에서 분기, `0013_scopeweave_promotion` — 0010→0013 메인라인) `scripts/migrate_db.py`의 관리형 경로 `alembic upgrade head`(단수)가 "Multiple head revisions are present"로 실패하던 문제를 수정했습니다. 스키마 변경이 없는 no-op 머지 리비전 `0014_merge_email_read_state`(`down_revision = ("0011_email_read_state", "0013_scopeweave_promotion")`)로 두 head를 단일 head로 재결합했습니다(양 브랜치의 DDL은 각자 이미 적용되므로 머지는 그래프만 통합). 재발 방지 가드로 `tests/test_alembic_migrations.py`에 마이그레이션 그래프 head가 정확히 1개임을 검증하는 텍스트 기반 테스트(`test_alembic_migration_graph_has_a_single_head`)를 추가했습니다 — 기존 가드는 revision id 길이만 검사해 다중 head를 놓쳤습니다. 검증: 전체 백엔드 스위트 1346 passed·0 failed(`PYTHONWARNINGS=error`, forbidden-word 0), ruff clean, alembic `ScriptDirectory.get_heads()` == 1.
Expand Down Expand Up @@ -2687,6 +2697,16 @@
- `docker compose down`

## [Unreleased]

### Added
- **유틸리티 도구 추가:** `api/tools.py`에 다음 세 가지 유틸리티 도구를 새로 추가했습니다.
- **JSON 검증기 (json_validator):** 입력 문자열이 올바른 JSON 형식인지 확인하고 예쁘게 포맷팅합니다.
- **해시 생성기 (hash_generator):** 문자열을 SHA256, MD5 등의 알고리즘을 사용해 해시 값으로 변환합니다.
- **URL 파서 (url_parser):** URL 문자열을 구성 요소(스킴, 호스트, 경로, 쿼리 등)로 파싱합니다.

### Fixed
- **테스트 커버리지 100% 달성:** `mock_handler` 및 `validate_webhook_url_details` 등 기존 모듈 내 누락된 코드 경로에 대한 테스트를 `backend/tests/test_tools_api.py`에 보강하여 `backend/api/tools.py` 파일의 테스트 커버리지를 완벽하게 맞추었습니다.

### Added
- `backend/api/tools.py` 내의 임시 `mock_handler`를 구체적인 기능을 수행하는 5개의 실제 도구 핸들러로 대체했습니다.
- `thread_summarizer_handler`: 이메일 스레드 요약 정보 반환
Expand Down
Loading
Loading