42 KiB
title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, branch, parent_branch, related_projects, governing_docs, tags, created, target_merge, status_label, contract_packet_sha256, imports
| title | source_type | status | id | kind | project | work_item | inherits | refines | overrides | depends_on | contract_packet | branch | parent_branch | related_projects | governing_docs | tags | created | target_merge | status_label | contract_packet_sha256 | imports | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| branch / feature-frontend-build-bundle-supply-chain-contract | branch-note | raw | BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-020 | project-work-item | ca-skeleton-frontend-operational-contract | WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-020 |
|
|
1 | feature-frontend-build-bundle-supply-chain-contract |
|
|
|
2026-07-18 | in-progress | 3dccf22904aa14c909b778cb3242f70be7a11dce4256b8fdaed40f5a1ad36035 |
|
branch: feature-frontend-build-bundle-supply-chain-contract
Layer:
raw/branch-notes/— TODO·결정·진행 기록. 구현 결과는 검증 뒤/ingest로만 추출한다.
부모 (필수)
raw/project-notes/ca-skeleton-frontend-operational-contract
브랜치 계약 패킷
- 생성 시 프로젝트 개정:
1 - 패킷 스키마:
contract_packet: 1 - 완료 조건: frozen build·inventory·scan·bundle report가 CI artifact로 생성된다
상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-BUILD-001@1 |
Vite client-only SPA를 build baseline으로 사용한다 | clean production build와 bundle report gate에 적용 | raw/project-notes/ca-skeleton-frontend-operational-contract |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SUPPLY-CHAIN-001@1 |
dependency lock, secret scan, vulnerability scan, license inventory, dependency review를 merge/release gate로 분리한다 | install·security·inventory·dependency review gate에 적용 | raw/project-notes/ca-skeleton-frontend-operational-contract |
브랜치 지역 결정
기존 branch-local 결정은 아래
## Decision Evidence Map / 결정-근거 매핑의 D-row가 소유하며 이 packet에서 복제하지 않는다.
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|
선언한 예외
| Override ID | Overrides | Reason | Approval | Status |
|---|
목표
이 브랜치는 project-wide 계약 FE-OC-018 (frozen lockfile · dependency review · secret scan · SBOM/dependency inventory 를 release gate 에 MUST 포함) 를 되묻지 않고 구현 착수 가능한 명세로 내린다. 근거 결정은 hub 의 raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 (supply-chain control 을 분리된 merge/release gate 로 운영 — control 열거는 hub 소유) 이며, hub §13.1 (supply-chain minimums), §12.1 (release artifact set), §14.3 (planned commands), §15.1 의 FE-GATE-001/FE-GATE-011/FE-GATE-012/FE-GATE-013 를 구현 blueprint 로 삼는다. 부수적으로 FE-OC-003 (frozen install), FE-OC-016 (release artifact), FE-OC-019 (secret-in-bundle 경계), FE-OC-020 (gate 분리), FE-OC-021 (bundle NFR) 에 기여한다. 현 시점 frontend 코드/CI 는 존재하지 않으므로 아래 모든 항목은 planned 등급이다 — "구현했다" 가 아니라 "이렇게 구현될 것이다" 의 사전 명세다.
- 이슈: 없음 (스캐폴딩 단계)
- PR: 없음
범위
포함 범위
- frozen-lockfile install gate — lockfile drift 없이 재현 가능한 install 을 merge+release 차단 gate 로 강제 (
FE-GATE-001,FE-OC-018). - clean production build gate — hashed immutable static asset + build-manifest 산출을 merge+release 차단 gate 로 강제 (
FE-GATE-011,FE-OC-018). - bundle report gate — release 시 app + lazy chunk 크기를 machine-readable report 로 산출 (
FE-GATE-012,FE-OC-018). (수치 threshold 자체는 아래 Out of scope.) - security gate — secret scan · vulnerability scan · license inventory · dependency review 를 하나의 차단 gate 로 묶어 SARIF/inventory/dependency-diff 산출 (
FE-GATE-013,FE-OC-018). - dependency review (dependency diff) — base↔head lockfile 을 direct + transitive 까지 diff 해 변경 집합을 산출하고, review 기록 없는 high-risk change 를 차단 gate 로 처리 (hub §13.1
dependency reviewrow,FE-OC-018). 본 브랜치가FE-OC-018소유자이며 sibling raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract 가 이 관심사를 본 브랜치로 명시 위임했다. - release supply-chain artifact set — dependency inventory · build-manifest(provenance metadata) · checksums 를 release artifact 로 명세 (hub §12.1, §13.1).
- vulnerability suppression policy — reason·owner·expiry·affected package·compensating control 을 강제하고 expiry 경과 suppression 을 gate failure 로 처리 (hub §13.3).
제외 범위
의도적으로 제외 — 다른 owner 브랜치의 결정 영역. "이건 범위에 없었습니다" 근거.
- package manager 선택 및 lockfile 형식 확정 — raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract (
FE-OC-003) 소유. 본 브랜치는 그 frozen-install 스크립트를 소비만 한다. - bundle 크기 threshold 수치 (
FE-NFR-001≤200 KiB,FE-NFR-002≤120 KiB) 와 측정 context — raw/branch-notes/feature-web-vitals-performance-budget-contract (FE-OC-021) 소유. 본 브랜치는 report 를 생성하고 pass/fail 판정은 위임. - browser security boundary 규칙 (CSP·
dangerouslySetInnerHTML금지·frame/referrer policy) — raw/branch-notes/feature-frontend-browser-security-boundary-contract (FE-OC-019) 소유. 본 브랜치는 secret scan 실행 gate 만 담당. - release manifest schema · cache policy · rollback drill — raw/branch-notes/feature-frontend-release-cache-rollback-contract (
FE-OC-016) 소유. 본 브랜치 artifact 는 그 release set 에 공급될 뿐이다. - CI gate orchestration · 실행 순서 · artifact retention 정책 — 배선은 raw/branch-notes/feature-frontend-ci-quality-gates-contract(어느
FE-OC-*의 owner 도 아닌 기여 브랜치), taxonomy 는 raw/branch-notes/feature-frontend-test-taxonomy-contract (FE-OC-020owner) 소유. 본 브랜치는 gate 를 제공, 배선은 위임. - scanner 도구·severity threshold·SBOM 형식 확정 — hub §13.1 이
deferred로 명시 (organization security policy 부재). 임의 확정 금지. - runtime config artifact (
dist/config.json,dist/config/runtime-config.schema.json) — hub §12.1 release artifact set 에 함께 나열되지만 소유는 raw/branch-notes/feature-frontend-env-runtime-config-contract (FE-OC-004). 본 브랜치의 release artifact 책임은 supply-chain 3종(inventory·build-manifest·checksums)뿐이며 config 산출/검증은 위임한다.
근거 (필수, 최소 1개+)
| Source | 정당화하는 결정 |
|---|---|
| raw/official-docs/supply-chain-slsa-provenance-framework | SLSA-FW-C1/C4/C5 — provenance = build platform/process/top-level input 을 기술하는 verifiable 정보. release build-manifest(buildId/commit) 를 provenance 최소선으로 두는 D7 의 공식 근거. signed attestation(L2+) 은 미채택 표지. |
| raw/official-docs/vite-build-tool-official | VITE-C2 — production build 가 optimized 정적 자산을 산출 (D3 clean build gate 근거). VITE-C3/C4/C5 — import.meta.env build-time 정적 치환 + VITE_ prefix 만 클라이언트 노출 + 비밀값 금지 (D6 built-asset secret scan 경계 근거). |
나머지 세부 (gate 분리·§13.1 control·§12.1 artifact·suppression policy) 의 근거는 외부 문서가 아니라 hub 자체의 project decision 이므로 Evidence Map 에서 raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 로 인용한다 (hub §3.2 가
accepted-documented-only로 명시).
TODO
- frozen-lockfile install gate (
FE-GATE-001) 명세 — command·drift 검출·install log artifact — 등급:planned - clean production build gate (
FE-GATE-011) 명세 — hashed asset + build-manifest 산출 — 등급:planned - bundle report gate (
FE-GATE-012) 명세 — machine-readable bundle report (threshold 판정은FE-OC-021위임) — 등급:planned - security gate (
FE-GATE-013) 명세 — secret/vuln/license/dependency-review fixture + SARIF/inventory/dependency-diff — 등급:planned - dependency review 명세 — base↔head lockfile direct+transitive diff · high-risk 분류축 · review 기록 · dependency diff report — 등급:
planned - release supply-chain artifact set (dependency inventory·checksums·build-manifest) + provenance metadata 정의 — 등급:
planned - vulnerability suppression policy (reason·owner·expiry·affected package·compensating control) 정의 — 등급:
planned - scanner/SBOM/threshold
deferred항목의 revisit trigger (organization security policy) 문서화 — 등급:planned
진행 중 메모
- scanner 도구명·severity threshold·SBOM 형식(CycloneDX/SPDX)·suppression expiry SLA 는 hub §13.1/§13.3 이
deferred로 명시 — 특정 도구를 썼다고 주장하지 않는다. - 모든 command(
pnpm install --frozen-lockfile·pnpm build·pnpm check:bundle·pnpm scan:security)와 artifact 경로는 hub §14.3/§12.1 의 planned contract 이며 실행/검증되지 않았다 (PLANNED_NOT_EXECUTED). - hub 내부 불일치 발견 → 해소 완료: hub §2.1 의
FE-OC-018과 §13.1 은dependency review를 요구하는데 §3.2FE-D024본문과 §15.1FE-GATE-013required fixtures 는 그것을 누락하고 있었다. 본 브랜치가 상위 계약을 따라 D9 로 편입했고, hub 도 정정됐다 — 현재FE-D024는 dependency review 를 포함해 열거하고(lock 은FE-GATE-001, 나머지 4개는FE-GATE-013), §15.1FE-GATE-013required fixtures 도secret/vulnerability/license/dependency-review다.
결정 사항
근거는 Sources 또는 hub project decision 을 가리킨다. FE-D### 인용은 hub 경로에 붙인다 (Evidence Map 과 mirror).
- 2026-07-18: supply-chain control 을 하나의 monolithic gate 가 아니라 dependency lock/secret/vuln/license 로 분리된 merge/release gate 로 운영 / 이유: 실패 지점을 구분해 blocking scope 를 정확히 하기 위함 / 검토한 대안: 단일 "security gate" 통합 / 근거: raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 (D1).
- 2026-07-18: frozen-lockfile install 을 merge+release 차단 gate 로 강제, drift = FAIL / 이유: 재현 가능한 install / 검토한 대안: 비-frozen install 후 사후 검증 / 근거: hub §13.1 install row +
FE-GATE-001(D2). - 2026-07-18: production build gate 는 hashed immutable asset + build-manifest 산출 / 이유: 정적 호스팅 배포 + release 식별 / 검토한 대안: unhashed asset / 근거:
raw/official-docs/vite-build-tool-official.md#VITE-C2+ hub §12.1 (D3). - 2026-07-18: bundle report 는 생성하되 수치 threshold 판정은
FE-OC-021에 위임 / 이유: NFR context/threshold 소유권 분리 / 근거: hub §14.2 (FE-NFR-001/FE-NFR-002) +FE-GATE-012(D4). - 2026-07-18: security gate 는 secret+vuln+license 를 묶고 scanner/threshold 는
deferred/ 이유: org policy 부재로 도구 확정이 불가 / 검토한 대안: 지금 특정 scanner 확정 / 근거: hub §13.1 (D5). - 2026-07-18: secret scan 은 source 뿐 아니라 built asset 까지 검사 / 이유: browser bundle 은 public artifact 이고
VITE_값은 build-time 에 정적 inline 되므로 / 근거:raw/official-docs/vite-build-tool-official.md#VITE-C4,#VITE-C5+ hub §13.2 (D6). - 2026-07-18: release 는 dependency inventory + build-manifest(buildId/commit provenance) + checksums 를 포함, mismatch = 차단; signed SLSA attestation 은 미채택 / 이유: provenance 최소선 확보 / 근거:
raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C1,#SLSA-FW-C4+ hub §12.1 (D7). - 2026-07-18: vulnerability suppression 은 reason·owner·expiry·affected package·compensating control 을 요구, expiry 경과 = gate failure / 이유: 무기한 예외 방지 / 근거: hub §13.3 (D8).
- 2026-07-20: dependency review 를
FE-GATE-013의 네 번째 control 로 편입 (별도 gate ID 신설 대신 기존 gate 범위 확장). base↔head lockfile 을 direct+transitive 까지 diff 하고, review 기록 없는 high-risk change = 차단, 산출물은 dependency diff report / 이유: hub §2.1FE-OC-018과 §13.1 이 dependency review 를 요구하는데 소유 gate 가 없었다. 새FE-GATE-027을 만들면 hub §15.1 의 "26개 row" registry 와 §15.3 promotion formula 를 동시에 고쳐야 하는데 그건 hub 소유 변경이라 본 브랜치 권한 밖이다.FE-GATE-013은 이미FE-OC-018을 covered 하고 blocking scope 도 merge+release 로 dependency review 요구와 일치한다 / 검토한 대안: (a) 신규 gate ID 신설 — hub registry 변경 필요로 기각, (b)FE-GATE-001(lockfile) 에 합류 — 그쪽은 drift 유무만 보는 결정론 검사라 "변경 내용의 위험도 심사"라는 성격이 다르고 실패 의미가 섞임 / 근거: raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 + hub §2.1FE-OC-018+ hub §13.1 dependency review row (D9).
결정-근거 매핑
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|---|
| D1 | supply-chain control 을 분리된 merge·release gate 로 운영 (FE-OC-018) — control 집합은 hub FE-D024 소유이며 dependency review 는 D9 로 편입됐다 |
이 분리가 project 최소선; organization security policy 가 더 강한 gate 를 지정하면 강화·재분할 | raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 | project-decision |
repo/CI 부재 → gate 배선 UNVERIFIED |
| D2 | frozen-lockfile install 을 merge+release 차단 gate, drift = FAIL (FE-GATE-001, FE-OC-018) |
frozen install 은 항상 필수; package manager/lockfile 형식은 FE-OC-003 (bootstrap) 소유 → 그쪽 변경 시 command 만 교체 |
raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 (hub §13.1 install row) | project-decision |
pnpm default 는 bootstrap 결정; org 가 npm/yarn 강제 시 install command 재확정 |
| D3 | production build gate = hashed immutable asset + build-manifest 산출 (FE-GATE-011, FE-OC-016/FE-OC-018) |
Vite client-only SPA build baseline 이 유지되는 한; SSR/edge rendering 이 requirement 가 되면 build 출력 형태 재검토 | raw/official-docs/vite-build-tool-official.md#VITE-C2 |
official-doc |
build 미존재 → artifact 이름/경로는 planned |
| D4 | bundle report 는 release gate 로 생성, 수치 threshold 판정은 위임 (FE-GATE-012, FE-OC-018/FE-OC-021) |
report 는 항상 release 에 산출; FE-NFR-001(≤200 KiB)/FE-NFR-002(≤120 KiB) 값과 FE-NFR-C04 context 는 web-vitals 브랜치가 소유·재검토 |
raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 (hub §14.2) | project-decision |
report↔threshold 소유 경계; threshold 변경은 FE-OC-021 에서 |
| D5 | security gate = secret+vuln+license 묶음(2026-07-20 D9 로 dependency review 가 4번째 control 로 편입), scanner/severity threshold 는 deferred (FE-GATE-013, FE-OC-018) |
이 구성이 최소선; repository/organization policy 가 생기면 특정 scanner·threshold 확정 | raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 (hub §13.1) | conditional-default |
지금 scanner 명시 = 날조 → deferred 유지 |
| D6 | secret scan 은 source + built asset 모두 검사 (FE-OC-018/FE-OC-019) |
browser bundle 을 public artifact 로 간주하는 한 항상; boundary 규칙(CSP·HTML injection) 자체는 FE-OC-019 소유 |
raw/official-docs/vite-build-tool-official.md#VITE-C4, #VITE-C5 (hub §13.2) |
official-doc |
scan 이 로그·debug 등 모든 유출 경로를 증명하진 못함 (VITE-C4 does-not-prove) |
| D7 | release 는 dependency inventory + build-manifest(buildId/commit provenance) + checksums 포함, mismatch 차단; signed attestation 미채택 (FE-OC-018, hub §12.1) |
최소선 = inventory + build metadata 를 provenance 로; org 가 더 강한 provenance 요구 시 signed SLSA(L2+) 채택 | raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C1, #SLSA-FW-C4, #SLSA-FW-C5 |
official-doc |
L1 provenance 는 "trivial to forge" (SLSA-FW-C1) — signing/SBOM 형식 deferred |
| D8 | vulnerability suppression 은 reason·owner·expiry·affected package·compensating control 필수, expiry 경과 = gate failure (FE-OC-018, hub §13.3) |
fix 즉시 불가한 accepted vuln 에 적용; org 가 더 엄격한 SLA 정의 시 재검토 | raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 (hub §13.3) | project-decision |
expiry SLA 수치 미정 → deferred |
| D9 | dependency review 를 FE-GATE-013 의 4번째 control 로 편입: base↔head lockfile direct+transitive diff, review 기록 없는 high-risk change = 차단, dependency diff report 산출 (FE-OC-018) |
hub §15.1 gate registry 가 26 row 로 고정된 동안은 기존 gate 확장; hub 가 registry+promotion formula 를 개정해 전용 gate 를 신설하면 그쪽으로 이관 | raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024 (hub §2.1 FE-OC-018 문구 + hub §13.1 dependency review row) |
project-decision |
hub FE-D024 가 dependency review 를 누락하던 불일치는 hub 정정으로 해소됨(현재 5개 control 열거, FE-GATE-013 fixtures 도 dependency-review 포함). "high-risk" 판정축·diff 도구는 hub 미지정 → UNSUPPORTED_IMPL_DECISION |
구현 가이드
plannedblueprint — frontend 코드/CI 는 아직 없다. 경로·command 는 hub §4.6/§12.1/§14.3 의 planned contract 에서 도출한 anchor 이며 repository 생성 시 확정된다. CLAUDE.md §15.5 R1(Trace)/R2(UNSUPPORTED_IMPL_DECISION)/R3(OUT_OF_BRANCH_SCOPE) 준수.
1. Gate topology — merge vs release 분리
Trace: D1 (raw/project-notes/ca-skeleton-frontend-operational-contract FE-D024), D2/D3/D4/D5/D9 — hub §15.1 gate registry +
FE-OC-018.
- UNSUPPORTED_IMPL_DECISION: 없음 — blocking scope·covered contract·artifact 는 hub §15.1 이 직접 명시.
FE-GATE-013의 control 4번째(dependency review) 편입은 D9 근거이며 gate ID 신설이 아니므로 hub registry row 수(26)를 바꾸지 않는다.
gate 의 blocking scope · Covered FE-OC · evidence artifact 는 hub §15.1 이 소유한다. 아래 표는 그 열을 옮겨 적지 않고, 본 브랜치가 각 gate 안에서 무엇을 명세하는지(control) 만 담는다. 값이 필요하면 raw/project-notes/ca-skeleton-frontend-operational-contract §15.1 을 본다.
| Gate ID | Control (본 브랜치 명세) |
|---|---|
FE-GATE-001 |
frozen install drift |
FE-GATE-011 |
clean production build |
FE-GATE-012 |
bundle report 생성 (판정은 FE-OC-021 owner 위임) |
FE-GATE-013 |
① secret scan ② vulnerability scan ③ license inventory ④ dependency review (D9) |
- 실패는 warning 으로 낮추지 않는다 (
FE-OC-020). 각 gate 는 최소 1개의 deliberately-failing negative fixture 로 "실제 동작"을 증명해야 한다 (hub §15.2).FE-GATE-013은 4개 control 각각이 독립 negative fixture 를 갖는다 (§5). - gate 는 4개지만 control 은 7개(install·build·bundle·secret·vuln·license·dependency review)다. D1 의 "분리" 원칙은 gate ID 개수가 아니라 실패 지점이 artifact 단위로 구분 가능한가로 만족시킨다 —
FE-GATE-013내부 4 control 은 서로 다른 artifact(SARIF · license inventory · dependency diff report)로 실패 원인을 구분한다.
2. Frozen-lockfile install gate
Trace: D2 — hub §13.1 install row + §14.3.
- UNSUPPORTED_IMPL_DECISION: 없음 — command·artifact 는 hub §14.3 이 명시. package manager 명(pnpm)은 본 브랜치 결정이 아님 → §OUT_OF_BRANCH_SCOPE 참조.
- command:
pnpm install --frozen-lockfile(hub §14.3,PLANNED_NOT_EXECUTED). - pass 조건: manifest ↔ lockfile drift 없음, exit 0.
- artifact:
artifacts/quality/install.txt(hub §14.3) /artifacts/quality/lockfile-check.txt(hub §13.1). - negative fixture: lockfile drift(수동 편집) → frozen install 이 exit≠0 로 실패해야 함.
- OUT_OF_BRANCH_SCOPE: package manager 선택·
packageManagerfield·pnpm-lock.yamlcommit 은 raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract (FE-OC-003) 소유. 본 gate 는 그 lockfile 을 frozen 으로 검증만 한다.
3. Clean production build gate
Trace: D3 —
raw/official-docs/vite-build-tool-official.md#VITE-C2+ hub §12.1 artifact set.
- UNSUPPORTED_IMPL_DECISION: 없음 — build command·artifact·hash 규칙은 hub §12.1/§14.3 + VITE-C2 에서 도출.
- command:
pnpm build(hub §14.3). - pass 조건: exit 0 + 기대 artifact 존재.
- 산출 artifact (hub §12.1):
dist/index.html,dist/assets/<content-hash>.*(immutable hashed),dist/release-manifest.json,artifacts/release/build-manifest.json,artifacts/release/checksums.txt. - hashed asset 의 immutable cache 정책 자체는 raw/branch-notes/feature-frontend-release-cache-rollback-contract (
FE-OC-016) 소유 — 여기서는 hash 산출까지만.
4. Bundle report gate
Trace: D4 — hub §14.3 (
pnpm check:bundle) + §14.2 (FE-NFR-001/FE-NFR-002).
- UNSUPPORTED_IMPL_DECISION: (a) bundle 분석 도구(rollup-plugin-visualizer / 자체 스크립트 등)는 hub 가 지정하지 않음 → 도구 선택은 repo 생성 시 결정. trade-off: 지금 도구명을 박으면 날조가 되므로 report 형식(machine-readable JSON)만 고정하고 도구는 미정. (b)
bundle.json의 필드명·구조는 2026-07-21 해소됨 — hub §2.1.3 이ART-FE-002@1로 등록하고bundle-report.schema.json이 정본이다. 아래 §schema 참조.
- command:
pnpm check:bundle(hub §14.3). - artifact:
artifacts/performance/bundle.json(machine-readable, hub §14.3). - 측정 대상: initial JS(app) + 각 lazy route chunk 의 gzip 크기.
- pass/fail 판정:
FE-NFR-001(initial JS gzip ≤ 200 KiB),FE-NFR-002(lazy chunk gzip ≤ 120 KiB), contextFE-NFR-C04. - schema =
ART-FE-002@1(hub §2.1.3 ·harness/source/artifact-schemas/ca-skeleton-frontend/bundle-report.schema.json). 이전 판은 이 스키마를 "공동 소유라 단독 결정 불가" 로 두고 필드 초안을 여기에 적었는데, 그래서 producer(runner.node)와 consumer(snake_case) 가 서로 다른 키 이름을 계약이라 부르는 상태가 됐다. 이제 Schema Owner 는 본 브랜치 단독이고 필드 추가·rename 은 스키마 파일을 고쳐 revision 을 올리는 것으로 하며, 소비 branch 는importspin 이 낡아 자동으로 잡힌다.context/runner는 hub §14.1 의 "context 없는 숫자는 evidence 로 인정하지 않는다" 요구 때문에 required 다 (FE-NFR-C04).buildId/commit은 §6 build-manifest(ART-FE-001@1)와 동일 값이어야 하며, 이 대조로 report 가 어느 build 의 것인지 식별된다.
- OPEN QUESTION — budget 이 JS-only 인가 CSS 포함인가: hub §14.2 는
FE-NFR-001을 "initial JS gzip",FE-NFR-002를 "any lazy route chunk gzip" 으로만 정의하고 CSS 전용 NFR ID 가 없다. 따라서 현재 계약은 JS-only 판정으로 읽는 것이 문언에 충실하다. 본 gate 는 CSS asset 의 gzip 크기도 report 에 기록은 하되 판정 대상으로 삼지 않는다. CSS 를 budget 에 포함할지, 별도 NFR ID 를 신설할지는FE-OC-021소유자와 hub §14.2 개정 사항이다. - OUT_OF_BRANCH_SCOPE: 위 threshold 수치·측정 context 정의는 raw/branch-notes/feature-web-vitals-performance-budget-contract (
FE-OC-021) 소유. 본 gate 는 report 를 생성하고 threshold 를 소비한다.
5. Security gate — secret · vulnerability · license · dependency review
Trace: D5/D6/D8/D9 — hub §13.1 (secret/vuln/license/dependency review row) + §13.3 (suppression) + §2.1
FE-OC-018+VITE-C4/C5.
- UNSUPPORTED_IMPL_DECISION: (a) scanner 도구(secret: gitleaks/trufflehog?, vuln: npm audit/osv-scanner/trivy?, license: 자체?) 미정, (b) severity threshold(어느 CVSS 등급부터 차단) 미정, (c) suppression expiry SLA(며칠) 미정. 모두 hub §13.1/§13.3 이
deferred로 명시 — 임의 확정 시 날조. trade-off: 지금은 gate 구조·fixture 계약만 고정하고 도구·수치는 organization security policy 확정 후 채운다.- UNSUPPORTED_IMPL_DECISION: (d) dependency diff 도구(GitHub Dependency Review Action /
pnpm why기반 자체 스크립트 / osv-scanner diff 등) 미정 — hub §13.1 은 "direct/transitive diff" 라는 대상만 규정하고 도구를 지정하지 않는다. trade-off: 도구명을 지금 박으면 날조이므로 입력(base↔head lockfile)·출력(dependency diff report)·차단 조건만 고정한다. (e) "high-risk change" 의 분류축(아래 R1~R5) 도 hub 미지정 — hub 는unreviewed high-risk change라는 차단 조건만 준다. trade-off: 분류축이 없으면 gate 가 판정 불가능해 구현 착수가 막히므로, fail-closed 기본값(분류 불가/미기록 = high-risk 취급)을 두고 축 목록은 org policy 확정 시 교체 가능한 것으로 표시한다. 축을 좁게 잡으면 위험 변경이 통과하고, 넓게 잡으면 모든 renovate PR 이 수동 리뷰를 요구해 마찰이 커지는 trade-off 를 인지하고 fail-closed 를 택했다.
- command:
pnpm scan:security(hub §14.3). dependency review 도 이 command 안에서 수행한다 — hub §14.3 planned command 표에 dependency-review 전용 script 가 없으므로 새 script 명을 만들면 hub 계약과 어긋난다. script 를 분리하려면 hub §14.3 + §15.1 artifact mapping 을 함께 갱신해야 한다 (hub §14.3 말미 규칙). - artifact:
artifacts/security/scan.sarif(hub §14.3) + license inventory +artifacts/release/dependency-inventory.*(hub §12.1) + dependency diff report (아래). - secret scan (D6): source + built asset(
dist/) 모두 검사. 이유:VITE_prefix 값은 build-time 에 정적 inline 되므로(VITE-C3) 유출은 built bundle 에서만 관측될 수 있음(VITE-C4/C5). browser bundle = public artifact (hub §13.2). - vulnerability scan (D5): severity policy 위반이 approved expiry 없이 존재하면 차단 (hub §13.1).
- license inventory: denied/unknown license 미해결 시 차단 (hub §13.1).
- suppression (D8): 각 suppression 은 reason·owner·expiry·affected package·compensating control 보유; expiry 경과 suppression = gate failure (hub §13.3).
5.1 Dependency review (control ④)
Trace: D9 — hub §2.1
FE-OC-018(frozen lockfile · dependency review · secret scan · SBOM/inventory 를 release gate 에 MUST 포함) + hub §13.1dependency reviewrow (direct/transitive diff/unreviewed high-risk change/dependency diff report).
-
무엇을 diff 하는가 (입력): PR 의 base commit lockfile ↔ head commit lockfile. 두 lockfile 을 각각 resolve 해 얻은 완전한 패키지 집합(direct + transitive, 즉 lockfile 에 기록된 모든 resolved entry)을 비교한다. manifest(
package.json) diff 만 보지 않는다 — hub §13.1 이 명시적으로direct/transitive를 요구하고, transitive 변경은 manifest 에 나타나지 않기 때문이다.- release 시점에는 base = 직전 release 의 lockfile(release token 기준)로 잡아 release 단위 누적 변경도 같은 방식으로 산출한다.
-
변경 분류 (출력 행): 각 diff row 는
{package, from, to, changeKind, depth, riskFlags[], reviewRef}를 갖는다.changeKind∈added | removed | version-changed | resolution-changed(같은 버전인데 resolved URL/integrity 가 바뀐 경우).depth∈direct | transitive.
-
무엇이 "unreviewed high-risk change" 인가 (차단 조건): 아래 두 조건을 동시에 만족하는 row 가 하나라도 있으면
FE-GATE-013FAIL.- high-risk 로 분류됨 — 아래 riskFlag 축 중 하나 이상에 해당. (축 목록 자체는 위
UNSUPPORTED_IMPL_DECISION(e).)R1 new-package— 이전 lockfile 에 없던 패키지 추가 (direct/transitive 무관; 새 코드가 신뢰 경계에 들어옴).R2 install-script— install/postinstall 등 lifecycle script 를 실행하는 패키지의 추가·변경.R3 major-bump— semver major 상승 (hub §13.3 이 major update 에FE-D*impact check + registry compatibility check 를 별도로 요구하므로 위험 등급이 다르다).R4 license-change— 해당 패키지의 license 식별자가 변경됨 (license inventory control 과 교차).R5 known-vuln— vulnerability scan 이 해당 패키지에 severity policy 위반을 보고함 (vulnerability control 과 교차).- fail-closed 기본값: riskFlag 산출에 필요한 metadata(license/lifecycle script/이전 버전)를 확보하지 못해 분류 자체가 불가능한 row 는 high-risk 로 간주한다. "정보 부족 = 통과" 는 gate 를 무력화하므로 채택하지 않는다.
- review 기록이 없음 — 해당 row 에 대응하는 review record(reviewer, 날짜, 대상 package@version, 승인 사유)가 없거나, 기록의
package@to가 실제 diff 와 불일치. review record 는 vulnerability suppression(D8, hub §13.3)과 별개 트랙이다: suppression 은 "알려진 취약점을 기한부로 감수", review 는 "이 의존성 변경을 사람이 보았다" 이며 후자는 expiry 를 갖지 않는 대신 해당 package@version 에만 유효하다(버전이 다시 바뀌면 재검토 대상).
- low-risk row(위 축 어디에도 해당 없음)는 review 없이 통과한다 — 그렇지 않으면 patch 단위 갱신마다 gate 가 막혀 정책이 실질적으로 우회된다.
- high-risk 로 분류됨 — 아래 riskFlag 축 중 하나 이상에 해당. (축 목록 자체는 위
-
evidence artifact (dependency diff report): hub §13.1 은 artifact 를
dependency diff report라고만 명명하고 경로를 주지 않는다. 본 브랜치는artifacts/security/dependency-diff.json을 anchor 로 둔다 — hub §14.3 이 security 계열 artifact 를artifacts/security/아래 두므로(scan.sarif) 그 규약을 따른 것이다.- UNSUPPORTED_IMPL_DECISION: 위 파일명·경로는 hub 가 지정하지 않은 명명 결정. trade-off: 경로를 비워두면 CI 배선(
FE-OC-020소유자)이 artifact 를 수집할 수 없어 gate 가 성립하지 않으므로, hub 의 기존 디렉터리 규약에서 가장 마찰이 적은 이름을 anchor 로 고정하고 repository 생성 시 확정한다. - report 최소 내용:
{baseRef, headRef, rows[], blocking[]}—rows[]는 위 diff row 전체,blocking[]은 차단 사유가 된 row 의 부분집합. 통과한 build 도 report 를 남긴다(변경 0건이면 빈rows[]) — 산출 자체가 hub §13.1 의 evidence 요구다.
- UNSUPPORTED_IMPL_DECISION: 위 파일명·경로는 hub 가 지정하지 않은 명명 결정. trade-off: 경로를 비워두면 CI 배선(
-
negative fixture: review record 없이
R1 new-package에 해당하는 transitive 의존성을 추가한 fixture 가FE-GATE-013을 FAIL 시켜야 한다. 대칭으로, 동일 변경에 유효한 review record 를 붙이면 PASS 해야 한다(가짜 PASS 방지). -
OUT_OF_BRANCH_SCOPE: review record 를 어디에 보관할지(PR label / repo 내 파일 / 외부 시스템)와 reviewer 권한 모델은 CI orchestration 영역으로 raw/branch-notes/feature-frontend-ci-quality-gates-contract 소유. 본 gate 는 "review record 가 조회 가능해야 한다"는 인터페이스 요구만 둔다. lockfile 형식·package manager 는 raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract (
FE-OC-003) 소유이며 본 control 은 그 lockfile 을 읽기만 한다. -
negative fixture 후보: (i)
VITE_-var 에 심은 가짜 secret 이dist/번들에서 탐지되어 실패, (ii) known-vuln 의존성이 approved expiry 없이 차단, (iii) 만료된 suppression 이 실패, (iv) denied license 가 실패, (v) review record 없는 신규 transitive 의존성 추가가 실패 (§5.1).
6. Release supply-chain artifact set & provenance
Trace: D7 — hub §12.1 artifact set + §13.1 provenance/SBOM row +
SLSA-FW-C1/C4/C5.
- UNSUPPORTED_IMPL_DECISION: SBOM 형식(CycloneDX vs SPDX)과 signed attestation(in-toto/DSSE, SLSA L2+) 채택 여부 미정 → hub §13.1 이 "tool selected by owner" 로
deferred. trade-off: 최소선(dependency inventory + build metadata)만 고정하고 signing 은 org 요구 시.
- release artifact (hub §12.1):
artifacts/release/dependency-inventory.*,artifacts/release/build-manifest.json,artifacts/release/checksums.txt. - provenance 최소선: build-manifest 에 buildId/commit 을 기록해 build platform/process/top-level input 을 기술(SLSA-FW-C1, C4). buildId/commit mismatch = 차단 (hub §13.1 provenance row).
- dependency inventory 는 SLSA
resolvedDependencies개념(build time 필요 artifact 의 collection, SLSA-FW-C5)에 대응하되 "완전성"을 주장하지 않는다("if known", SLSA-FW-C5 does-not-prove). - 미채택 표지: SLSA L1 provenance 는 "trivial to forge"(SLSA-FW-C1) — signed/authenticated attestation 은 별도 결정이며 현재 채택하지 않는다.
엣지·실패·의존
- 실패·엣지 경로:
- lockfile drift → frozen install exit≠0 →
FE-GATE-001FAIL. - production build 실패 또는 기대 artifact 누락 →
FE-GATE-011FAIL. - bundle threshold 초과 →
FE-GATE-012FAIL (판정 값은FE-OC-021소유). - built asset 에서 secret 패턴 hit →
FE-GATE-013FAIL. - severity threshold 위반이 approved expiry 없이 존재 / 만료된 suppression →
FE-GATE-013FAIL. - denied/unknown license 미해결 →
FE-GATE-013FAIL. - review record 없는 high-risk dependency 변경(신규 패키지·install script·major bump·license 변경·known-vuln) →
FE-GATE-013FAIL (§5.1). - dependency diff row 의 riskFlag 를 분류할 metadata 부재 → fail-closed 로 high-risk 취급 → review 없으면
FE-GATE-013FAIL (§5.1). - base lockfile 을 확정할 수 없음(base ref 소실·shallow clone) → dependency review 를 "통과" 로 처리하지 않고 gate ERROR 로 처리해 차단 (fail-closed).
- release inventory 누락 또는 buildId/commit mismatch → release 차단 (hub §12.1/§13.1).
- lockfile drift → frozen install exit≠0 →
- 다른 계약 의존 (sibling 링크는
FE-OC-###로만 표기):- raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract (
FE-OC-003) 에 의존 — package manager·lockfile·frozen-install 스크립트를 consume. 그 계약이 바뀌면 §2 install command 영향. - raw/branch-notes/feature-frontend-test-taxonomy-contract (
FE-OC-020) 에 의존 — 본 브랜치 gate 가 CI gate taxonomy/artifact 분리 규칙에 편입. - raw/branch-notes/feature-web-vitals-performance-budget-contract (
FE-OC-021) 에 기여/의존 — bundle threshold 값·NFR context 를 그쪽에서 consume.artifacts/performance/bundle.json스키마의 Schema Owner 는 본 브랜치(hub §2.1.3ART-FE-002@1) — 그쪽은 소비자로서imports로 pin 한다. - raw/branch-notes/feature-frontend-browser-security-boundary-contract (
FE-OC-019) 에 기여 — secret-in-bundle·untrusted-HTML 경계 규칙은 그쪽 소유, 본 브랜치는 scan gate 실행. - raw/branch-notes/feature-frontend-release-cache-rollback-contract (
FE-OC-016) 에 기여 — 본 브랜치 artifact(inventory·manifest·checksums)가 release set 에 공급. - raw/branch-notes/feature-frontend-ci-quality-gates-contract 에 의존 — gate orchestration·artifact retention 은 그쪽 소유(그 브랜치는
FE-OC-*owner 가 아니다).
- raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract (
검증해야 할 주장
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
| frozen install 이 lockfile drift 를 실제로 차단한다 | CI/repo 부재 | drift fixture 로 pnpm install --frozen-lockfile 이 exit≠0 → artifacts/quality/install.txt |
needs-confirmation |
| production build 가 기대 artifact set + hashed asset 을 산출한다 | build 미실행 | build gate fixture 로 pnpm build exit 0 + artifacts/release/build-manifest.json 존재 확인 |
needs-confirmation |
| bundle report 가 initial JS + lazy chunk gzip 을 machine-readable 로 기록한다 | 도구 미정 | pnpm check:bundle → artifacts/performance/bundle.json 스키마 검증 (threshold 판정은 FE-OC-021) |
needs-confirmation |
| secret scan 이 source 뿐 아니라 built asset 의 secret 을 탐지한다 | 코드/scanner 미정 | negative fixture: VITE_-var 의 가짜 secret 이 dist/ 번들에서 탐지되어 FE-GATE-013 FAIL |
needs-confirmation |
| vulnerability gate 가 known-vuln(무-expiry)과 만료된 suppression 을 차단한다 | scanner/threshold deferred |
negative fixture 로 pnpm scan:security 가 두 경우 FAIL → artifacts/security/scan.sarif |
needs-confirmation |
| license inventory 가 denied/unknown license 를 flag 한다 | 도구 미정 | fixture: denied license 의존성이 security gate FAIL | needs-confirmation |
| dependency review 가 base↔head lockfile 의 transitive 변경까지 잡아낸다 | diff 도구 미정, lockfile 미존재 | fixture: manifest 는 그대로 두고 transitive 만 바뀐 lockfile 로 pnpm scan:security → artifacts/security/dependency-diff.json 의 rows[] 에 해당 row 존재 |
needs-confirmation |
| review record 없는 high-risk 변경이 실제로 차단되고, record 를 붙이면 통과한다 | review record 저장 위치가 FE-OC-020 소유로 미확정 |
negative/positive 쌍 fixture: 신규 transitive 패키지 추가 → record 없으면 FAIL, 있으면 PASS | needs-confirmation |
bundle.json 이 소비자(FE-OC-021)가 FE-NFR-001/FE-NFR-002 를 판정하기에 충분한 필드를 담는다 |
스키마(ART-FE-002@1)는 확정됐으나 실제 report 생성이 미실행 |
스키마대로 report 생성 후 web-vitals 판정 로직이 추가 필드 요구 없이 동작하는지 대조 | needs-confirmation |
| release 가 dependency inventory + build-manifest(buildId/commit) + checksums 를 포함하고 mismatch 를 차단한다 | pipeline 부재 | release verification fixture 로 buildId/commit mismatch 차단 확인 | needs-confirmation |
관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
- 스캐폴딩 단계:
/coverage실행 전 수동 행을 만들지 않는다.
마주친 문제
- 없음 — 스캐폴딩 단계.
묶음 (이 branch에서 파생된 자료)
가져온 artifact 계약
| Artifact Ref | Owner | Producer | Schema Ref |
|---|---|---|---|
ART-FE-001@1 |
raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract | raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract | harness/source/artifact-schemas/ca-skeleton-frontend/build-manifest.schema.json |
가져온 프로젝트 계약
| Ref | Owner | 요약 | Branch 적용 |
|---|---|---|---|
FE-GATE-001@1 |
raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract | lockfile 이 manifest 와 어긋나면 merge·release 를 MUST 차단 | import 참조로 적용 |
FE-OC-003@1 |
raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract | package manager, engine, lockfile, source language, checkJs command를 한 곳에서 MUST 고정 | import 참조로 적용 |
FE-OC-016@1 |
raw/branch-notes/feature-frontend-release-cache-rollback-contract | HTML, asset, runtime config, release manifest cache policy를 MUST 구분 | import 참조로 적용 |
FE-OC-019@1 |
raw/branch-notes/feature-frontend-browser-security-boundary-contract | browser bundle에 secret을 넣지 않고 untrusted HTML injection을 기본 금지 | import 참조로 적용 |
FE-OC-020@1 |
raw/branch-notes/feature-frontend-test-taxonomy-contract | gate 종류별 책임·fixture·artifact를 분리하고 실패를 warning으로 낮추면 안 됨 | import 참조로 적용 |
FE-OC-021@1 |
raw/branch-notes/feature-web-vitals-performance-budget-contract | NFR은 device/network/cache/build context와 함께 MUST 측정 | import 참조로 적용 |
- 없음 — 자식 자료는 생성 후 controller가 parent Cluster와 함께 등록한다.
관련 일일 노트
- 없음 — daily note는 이 작업에서 수정하지 않는다.
완료 후 정리
- PR 링크: 없음
- 리뷰 메모: 없음
- 머지 결과 / 배포 환경:
planned - wiki 추출 대상 (verified만): 없음
- 추출하지 않을 항목 (planned / documented-only / abandoned): 현재 전체