Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a0ada6b
Harden npm release installation trust boundary
ictechgy Jun 21, 2026
2b7e965
Close npm release checksum verification loop
ictechgy Jun 21, 2026
0815644
Generate npm checksums from published release assets
ictechgy Jun 21, 2026
562e6af
Separate npm checksum generation from verification
ictechgy Jun 21, 2026
b56944c
Anchor release workflows to immutable tags
ictechgy Jun 21, 2026
d2a5896
Verify release tag identity and tarball installability
ictechgy Jun 21, 2026
0206e5a
Bind npm publish assets to release commit provenance
ictechgy Jun 21, 2026
cdcd534
Prevent stale Codex cache confidence
ictechgy Jun 21, 2026
175a958
Keep Codex cache hits scoped and cheap
ictechgy Jun 21, 2026
364ecef
Fail safe when stale Codex peers revive
ictechgy Jun 21, 2026
d2ffa33
Bound Codex date-tree discovery
ictechgy Jun 21, 2026
54948c0
Fail safe on partial Codex scans
ictechgy Jun 21, 2026
044d025
Fail safe on uncertain Codex rollout stats
ictechgy Jun 21, 2026
1e52f75
Reject unterminated Codex rollout headers
ictechgy Jun 21, 2026
a0ebb77
Preserve Codex uncertainty in fingerprints and headers
ictechgy Jun 21, 2026
fefd814
Recheck cached Codex rollout file type
ictechgy Jun 21, 2026
a7595af
Probe Codex scan completeness on cache hits
ictechgy Jun 21, 2026
0e17a72
Bound statusline hot-path work
ictechgy Jun 21, 2026
3d54543
Prove hot-path limits through render paths
ictechgy Jun 21, 2026
de88a5a
Align docs and env tests with current status paths
ictechgy Jun 21, 2026
5ff447e
Clarify docs before review handoff
ictechgy Jun 22, 2026
eb06dd6
Align docs wording from external proofreading
ictechgy Jun 22, 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
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,14 @@ jobs:

- name: cargo test
run: cargo test

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22.x'

- name: Upgrade npm for packlist parity
run: npm install -g npm@11.5.1

- name: npm test
run: npm test --prefix npm
80 changes: 77 additions & 3 deletions .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ on:
tag:
description: 'Tag to publish (e.g. v0.7.1)'
required: true
commit:
description: 'Full commit SHA that refs/tags/<tag> must point to'
required: true

permissions:
id-token: write # OIDC 토큰 발급에 필수
Expand All @@ -33,11 +36,37 @@ jobs:
# environment: release # npm 폼에 Environment name을 넣었다면 주석 해제(동일 값)
env:
TAG: ${{ github.event.inputs.tag || github.ref_name }}
EXPECTED_COMMIT: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.commit || github.sha }}
steps:
- name: Checkout (tag)
uses: actions/checkout@v6
with:
ref: ${{ github.event.inputs.tag || github.ref_name }}
ref: refs/tags/${{ github.event.inputs.tag || github.ref_name }}
fetch-depth: 0

- name: Verify checked out release tag
run: |
set -euo pipefail
if ! printf '%s' "$TAG" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'; then
echo "Invalid release tag: $TAG" >&2
exit 1
fi
if ! printf '%s' "$EXPECTED_COMMIT" | grep -Eq '^[0-9a-fA-F]{40}$'; then
echo "Invalid expected commit SHA: $EXPECTED_COMMIT" >&2
exit 1
fi
git fetch --force --tags origin "refs/tags/$TAG:refs/tags/$TAG"
head_commit="$(git rev-parse HEAD | tr '[:upper:]' '[:lower:]')"
tag_commit="$(git rev-parse "refs/tags/$TAG^{commit}" | tr '[:upper:]' '[:lower:]')"
expected_commit="$(printf '%s' "$EXPECTED_COMMIT" | tr '[:upper:]' '[:lower:]')"
if [ "$head_commit" != "$tag_commit" ]; then
echo "Checked out $head_commit but refs/tags/$TAG points to $tag_commit" >&2
exit 1
fi
if [ "$tag_commit" != "$expected_commit" ]; then
echo "refs/tags/$TAG points to $tag_commit but expected $expected_commit" >&2
exit 1
fi

- name: Setup Node + npm registry
uses: actions/setup-node@v4
Expand All @@ -46,8 +75,12 @@ jobs:
registry-url: 'https://registry.npmjs.org'

# Trusted Publishing(OIDC)은 npm CLI >= 11.5.1을 요구한다. Node 22 기본 npm은 10.x라 업그레이드.
# Keep packlist verification and publish on the same npm version.
- name: Upgrade npm (OIDC 요구 버전)
run: npm install -g npm@latest
run: npm install -g npm@11.5.1

- name: Verify release source contract
run: node npm/verify-release.js "${TAG#v}" --verify-packlist

# 릴리스 바이너리(arm64/x64 tarball)가 올라올 때까지 대기(최대 ~10분).
# release.yml과 같은 태그 push에 동시 트리거되므로, 보통 수십 초 내 충족된다.
Expand All @@ -60,7 +93,11 @@ jobs:
for i in $(seq 1 60); do
names="$(gh release view "$TAG" --json assets -q '.assets[].name' 2>/dev/null || true)"
if printf '%s\n' "$names" | grep -qx "understatus-${VER}-aarch64-apple-darwin.tar.gz" \
&& printf '%s\n' "$names" | grep -qx "understatus-${VER}-x86_64-apple-darwin.tar.gz"; then
&& printf '%s\n' "$names" | grep -qx "understatus-${VER}-aarch64-apple-darwin.tar.gz.sha256" \
&& printf '%s\n' "$names" | grep -qx "understatus-${VER}-aarch64-apple-darwin.tar.gz.provenance.json" \
&& printf '%s\n' "$names" | grep -qx "understatus-${VER}-x86_64-apple-darwin.tar.gz" \
&& printf '%s\n' "$names" | grep -qx "understatus-${VER}-x86_64-apple-darwin.tar.gz.sha256" \
&& printf '%s\n' "$names" | grep -qx "understatus-${VER}-x86_64-apple-darwin.tar.gz.provenance.json"; then
echo "릴리스 에셋 확인됨 ($TAG)"
exit 0
fi
Expand All @@ -70,6 +107,43 @@ jobs:
echo "릴리스 에셋을 시간 내 찾지 못함: $TAG" >&2
exit 1

# checksums.json is generated from the exact release assets for the npm tarball
# being published. A follow-up read-only verification keeps generation and
# manifest verification separate so --require-checksums cannot be neutralized.
- name: Verify release binary checksums
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
VER="${TAG#v}"
ASSET_DIR="${RUNNER_TEMP}/understatus-assets"
rm -rf "$ASSET_DIR"
mkdir -p "$ASSET_DIR"
for target in aarch64-apple-darwin x86_64-apple-darwin; do
gh release download "$TAG" \
--dir "$ASSET_DIR" \
--pattern "understatus-${VER}-${target}.tar.gz"
gh release download "$TAG" \
--dir "$ASSET_DIR" \
--pattern "understatus-${VER}-${target}.tar.gz.sha256"
gh release download "$TAG" \
--dir "$ASSET_DIR" \
--pattern "understatus-${VER}-${target}.tar.gz.provenance.json"
done
node npm/verify-release.js "$VER" \
--tarball-dir "$ASSET_DIR" \
--verify-sidecars \
--verify-provenance \
--expected-commit "$EXPECTED_COMMIT" \
--write-checksums \
--verify-packlist
node npm/verify-release.js "$VER" \
--tarball-dir "$ASSET_DIR" \
--verify-provenance \
--expected-commit "$EXPECTED_COMMIT" \
--require-checksums \
--verify-packlist

# 래퍼 서브디렉터리(./npm)를 publish. Trusted Publishing 사용 시 NODE_AUTH_TOKEN 불필요,
# provenance는 자동 생성된다. understatus는 unscoped 패키지라 기본 public.
- name: npm publish (./npm)
Expand Down
63 changes: 60 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ on:
workflow_dispatch:
inputs:
tag:
description: 'Tag to build and upload (e.g. v0.1.0)'
description: 'Tag to build and upload (e.g. v0.7.0)'
required: true
commit:
description: 'Full commit SHA that refs/tags/<tag> must point to'
required: true
default: 'v0.1.0'

permissions:
contents: write
Expand All @@ -28,11 +30,48 @@ jobs:
- x86_64-apple-darwin
env:
TAG: ${{ github.event.inputs.tag || github.ref_name }}
EXPECTED_COMMIT: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.commit || github.sha }}
steps:
- name: Checkout (tag)
uses: actions/checkout@v6
with:
ref: ${{ github.event.inputs.tag || github.ref_name }}
ref: refs/tags/${{ github.event.inputs.tag || github.ref_name }}
fetch-depth: 0

- name: Verify checked out release tag
run: |
set -euo pipefail
if ! printf '%s' "$TAG" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'; then
echo "Invalid release tag: $TAG" >&2
exit 1
fi
if ! printf '%s' "$EXPECTED_COMMIT" | grep -Eq '^[0-9a-fA-F]{40}$'; then
echo "Invalid expected commit SHA: $EXPECTED_COMMIT" >&2
exit 1
fi
git fetch --force --tags origin "refs/tags/$TAG:refs/tags/$TAG"
head_commit="$(git rev-parse HEAD | tr '[:upper:]' '[:lower:]')"
tag_commit="$(git rev-parse "refs/tags/$TAG^{commit}" | tr '[:upper:]' '[:lower:]')"
expected_commit="$(printf '%s' "$EXPECTED_COMMIT" | tr '[:upper:]' '[:lower:]')"
if [ "$head_commit" != "$tag_commit" ]; then
echo "Checked out $head_commit but refs/tags/$TAG points to $tag_commit" >&2
exit 1
fi
if [ "$tag_commit" != "$expected_commit" ]; then
echo "refs/tags/$TAG points to $tag_commit but expected $expected_commit" >&2
exit 1
fi

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22.x'

- name: Upgrade npm for packlist parity
run: npm install -g npm@11.5.1

- name: Verify release source contract
run: node npm/verify-release.js "${TAG#v}" --verify-packlist

- name: Rust toolchain (+ target)
uses: dtolnay/rust-toolchain@stable
Expand All @@ -48,6 +87,23 @@ jobs:
cd target/${{ matrix.target }}/release
tar czf understatus-${VERSION}-${{ matrix.target }}.tar.gz understatus
shasum -a 256 understatus-${VERSION}-${{ matrix.target }}.tar.gz > understatus-${VERSION}-${{ matrix.target }}.tar.gz.sha256
SHA256="$(cut -d ' ' -f 1 "understatus-${VERSION}-${{ matrix.target }}.tar.gz.sha256")"
COMMIT="$(git rev-parse HEAD | tr '[:upper:]' '[:lower:]')"
cat > understatus-${VERSION}-${{ matrix.target }}.tar.gz.provenance.json <<EOF
{
"tag": "${TAG}",
"commit": "${COMMIT}",
"target": "${{ matrix.target }}",
"asset": "understatus-${VERSION}-${{ matrix.target }}.tar.gz",
"sha256": "${SHA256}"
}
EOF

- name: Verify generated checksum sidecar
run: |
VERSION=${TAG#v}
cd target/${{ matrix.target }}/release
shasum -a 256 -c "understatus-${VERSION}-${{ matrix.target }}.tar.gz.sha256"

- name: Upload to GitHub Release
uses: softprops/action-gh-release@v3
Expand All @@ -56,4 +112,5 @@ jobs:
files: |
target/${{ matrix.target }}/release/understatus-*-${{ matrix.target }}.tar.gz
target/${{ matrix.target }}/release/understatus-*-${{ matrix.target }}.tar.gz.sha256
target/${{ matrix.target }}/release/understatus-*-${{ matrix.target }}.tar.gz.provenance.json
fail_on_unmatched_files: true
Loading
Loading