feat(lifecycle): add durable artifact-deletion receipt ledger - #277
feat(lifecycle): add durable artifact-deletion receipt ledger#277seonghobae wants to merge 34 commits into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthrough불변 artifact 삭제 영수증 모델과 저장소 계약을 추가했습니다. 메모리 및 restart-replay 파일 ledger가 상태 전이, 멱등성, 실패 재시도, strict UTF-8 영속화를 처리합니다. 실제 삭제와 원자적 tombstone 통합은 포함하지 않습니다. ChangesArtifact deletion receipts
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant ArtifactDeletionLedger
participant ArtifactDeletionReceipt
participant FileChannel
Caller->>ArtifactDeletionLedger: 요청 또는 상태 전이
ArtifactDeletionLedger->>ArtifactDeletionReceipt: 식별자와 다음 상태 검증
ArtifactDeletionReceipt-->>ArtifactDeletionLedger: 새 영수증 snapshot 반환
ArtifactDeletionLedger->>FileChannel: UTF-8 레코드 append 및 force(true)
FileChannel-->>ArtifactDeletionLedger: durable write 결과 반환
Possibly related issues
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
cdb3465 to
2f6bc8d
Compare
|
@coderabbitai review @opencode-agent @cwl-noema-review Independently review exact current head Verify the eight-file Slice B foundation only: Confirm there is no endpoint/controller/repository-delete/artifact-delete/worker/scheduler/workflow/dependency/release change and that the PR does not claim to resolve the still-open incomplete-cleanup finding. Report exact-head actionable findings or a no-blocker advisory conclusion after independent inspection. Keep Draft and do not infer counted independent approval. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
head='2f6bc8ddada68d73c7b35641d005a7fe02ee9c0a'
base='3e98e6fbf8af006f08e50463974468e89daf168d'
printf '%s\n' '== Revision verification =='
git rev-parse HEAD
git cat-file -t "$head"
git cat-file -t "$base"
git merge-base "$head" "$base"
git rev-list --left-right --count "$base...$head"
printf '%s\n' '== Parent-relative changed paths and status =='
git diff --name-status "$base" "$head"
git diff --stat "$base" "$head"
printf '%s\n' '== Java source/test outlines =='
for f in \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java \
src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java
do
if [ -f "$f" ]; then
echo "-- $f"
ast-grep outline "$f" --items all || true
fi
done
printf '%s\n' '== Relevant changed file contents =='
for f in \
CHANGELOG.md \
docs/security/2026-08-06-durable-artifact-deletion-receipts.md \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java \
src/main/resources/application.yml \
src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java
do
if [ -f "$f" ]; then
echo "-- $f"
cat -n "$f"
fi
done
printf '%s\n' '== Parent-relative diff =='
git diff --find-renames --find-copies --unified=50 "$base" "$head" -- \
CHANGELOG.md \
docs/security/2026-08-06-durable-artifact-deletion-receipts.md \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java \
src/main/resources/application.yml \
src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java
printf '%s\n' '== Lifecycle usage and missing-tenant hash lookup contexts =='
rg -n -C 4 --glob '*.java' \
'(ArtifactDeletionReceiptStore|ArtifactDeletionLedger|ArtifactDeletionReceipt|ArtifactDeletionState|contentHash|content_hash|tenantId|tenant_id)' \
src/main/java || trueLength of output: 194841 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='2f6bc8ddada68d73c7b35641d005a7fe02ee9c0a'
base='3e98e6fbf8af006f08e50463974468e89daf168d'
log='/tmp/coderabbit-shell-logs/shell-output-nyZMKE'
printf '%s\n' '== Exact revision and changed paths =='
git rev-parse HEAD
printf 'merge-base: '; git merge-base "$head" "$base"
printf 'parent-relative commits: '; git rev-list --count "$base..$head"
git diff --name-status "$base" "$head"
printf '%s\n' '== Ledger and receipt source with line numbers =='
cat -n src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java
cat -n src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java
printf '%s\n' '== Store, state, ADR, and changelog =='
cat -n src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java
cat -n src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java
cat -n docs/security/2026-08-06-durable-artifact-deletion-receipts.md
git diff --unified=20 "$base" "$head" -- CHANGELOG.md src/main/resources/application.yml
printf '%s\n' '== Receipt ledger references outside the new package =='
rg -n -C 3 --glob '*.java' \
'(new\s+ArtifactDeletionLedger\s*\(|ArtifactDeletionReceiptStore|ArtifactDeletionLedger)' \
src/main/java src/test/java || true
printf '%s\n' '== Parent hardening preservation =='
git diff --unified=30 "$base" "$head" -- \
src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/service/DefaultDocumentConversionService.java
printf '%s\n' '== Changed production path categories =='
git diff --name-only "$base" "$head" | \
awk '
/\/controller\// { print "controller: " $0 }
/\/repository\// { print "repository: " $0 }
/\/artifact\// { print "artifact: " $0 }
/\/service\// { print "service: " $0 }
/scheduler|workflow|pom\.xml|build\.gradle|package\.json|Dockerfile|\.github\// { print "excluded-category: " $0 }
' || true
printf '%s\n' '== Prior output revision/document excerpts, if available =='
if [ -f "$log" ]; then
rg -n -C 3 'Revision verification|Parent-relative changed paths|CHANGELOG|durable-artifact-deletion-receipts|^[0-9a-f]{40}$|^[AM]\s' "$log" || true
fiLength of output: 76230
I also verified the following:
This remains a Draft. I did not infer CI success or counted independent approval. ✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java (2)
285-299: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value채널 재사용을 검토하십시오(선택).
append는 전이마다createDirectories를 호출하고 채널을 새로 열고 닫습니다. 현재 슬라이스의 쓰기 빈도는 낮으므로 동작상 문제는 없습니다.cleanup worker가 통합되어 재시도 쓰기가 늘어나면, 채널을 한 번 열어 보관하고
force(true)만 반복하는 방식이 syscall을 줄입니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java` around lines 285 - 299, Optionally optimize append in ArtifactDeletionLedger by reusing a single open FileChannel across repeated writes instead of creating directories and opening/closing the channel for every transition. Preserve the existing ByteBuffer write loop and invoke force(true) after each append; retain safe channel lifecycle management for cleanup.
281-283: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
append의 도달 불가 oversized 검사를 제거하거나 테스트 가능하게 변경하십시오.유효한
ArtifactDeletionReceipt의 직렬화 결과는MAX_LEDGER_LINE_BYTES보다 작습니다. 현재 테스트는load경로만 검증하므로append의 true 분기는 실행할 수 없습니다. 상한 검사는 replay 경로에 유지하고,append검사에는 테스트 가능한 경계를 제공하십시오.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java` around lines 281 - 283, ArtifactDeletionLedger의 append 경로에서 유효한 ArtifactDeletionReceipt로는 도달할 수 없는 MAX_LEDGER_LINE_BYTES 초과 검사를 제거하십시오. oversizedLine() 검사는 replay를 수행하는 load 경로에만 유지하고, append는 정상적인 직렬화 결과를 그대로 기록하도록 하십시오.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/security/2026-08-06-durable-artifact-deletion-receipts.md`:
- Around line 19-21: 문서의 해당 문단을 다시 줄바꿈하여 `#263`이 줄의 첫 토큰이 되지 않도록 수정하십시오. `MD018`
위반만 해결하고, 기존 문구와 의미는 유지하십시오.
In `@src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java`:
- Line 284: Update the serialization write in ArtifactDeletionLedger to append a
fixed "\n" record terminator instead of System.lineSeparator(). Keep UTF-8
encoding unchanged so durable ledger files are host-independent and remain
compatible with replayBytes/readBoundedLines.
- Around line 241-243: load()의 파일 재생 로직을 수정하여 마지막 레코드가 개행으로 종결된 경우에만
replayBytes로 재생하십시오. 개행 없는 마지막 바이트열은 discardTornRecord로 마지막 \n 위치까지 truncate하고
Log4j2 warning을 기록한 뒤 무시하며, 완전한 레코드의 기존 재생 동작은 유지하십시오.
In
`@src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java`:
- Around line 222-246: Expand ArtifactDeletionLedgerTest with
direct-ledger-input failure tests covering strictUtf8 invalid-byte rejection,
replayLine immutable-identity conflicts, validateReplayTransition non-monotonic
timestamps and illegal subsequent states, and decodeRequired whitespace fields.
Assert each case throws IllegalStateException with the corresponding validation
message, while preserving the existing malformed-line and oversized-line tests.
---
Nitpick comments:
In `@src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java`:
- Around line 285-299: Optionally optimize append in ArtifactDeletionLedger by
reusing a single open FileChannel across repeated writes instead of creating
directories and opening/closing the channel for every transition. Preserve the
existing ByteBuffer write loop and invoke force(true) after each append; retain
safe channel lifecycle management for cleanup.
- Around line 281-283: ArtifactDeletionLedger의 append 경로에서 유효한
ArtifactDeletionReceipt로는 도달할 수 없는 MAX_LEDGER_LINE_BYTES 초과 검사를 제거하십시오.
oversizedLine() 검사는 replay를 수행하는 load 경로에만 유지하고, append는 정상적인 직렬화 결과를 그대로 기록하도록
하십시오.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 4b6a3a0f-e979-4ee2-ae3e-0707f6820a3f
📒 Files selected for processing (8)
CHANGELOG.mddocs/security/2026-08-06-durable-artifact-deletion-receipts.mdsrc/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.javasrc/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.javasrc/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.javasrc/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.javasrc/main/resources/application.ymlsrc/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java
|
@coderabbitai review @opencode-agent @cwl-noema-review Please independently review exact current head Verify the complete Exact-head fuzz run |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
head='0a447f1dc9cc0afaeb846ddd42999e9319e18d4e'
base='3e98e6fbf8af006f08e50463974468e89daf168d'
echo '== Exact revision topology =='
printf 'HEAD: '; git rev-parse HEAD
printf 'head type: '; git cat-file -t "$head"
printf 'base type: '; git cat-file -t "$base"
printf 'merge-base: '; git merge-base "$head" "$base"
printf 'ahead/behind: '; git rev-list --left-right --count "$base...$head"
printf 'commits in range:\n'; git rev-list --reverse --oneline "$base..$head"
echo '== Parent-relative changed files =='
git diff --name-status "$base" "$head"
git diff --stat "$base" "$head"
echo '== Candidate file map =='
fd -t f . src/main/java/com/clearfolio/viewer/lifecycle src/test/java/com/clearfolio/viewer/lifecycle docs/security 2>/dev/null || true
for f in \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java \
src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java
do
if [ -f "$f" ]; then
echo "-- outline: $f"
ast-grep outline "$f" --items all || true
fi
done
echo '== Parent-relative diff: receipt implementation and tests =='
git diff --unified=35 "$base" "$head" -- \
src/main/java/com/clearfolio/viewer/lifecycle \
src/test/java/com/clearfolio/viewer/lifecycle \
docs/security \
CHANGELOG.md \
src/main/resources/application.yml
echo '== Focused replay, append, validation, and test contexts =='
rg -n -C 12 --glob '*.java' \
'(replay|readLine|EOF|unterminated|newline|\\n|force\s*\(|FileChannel|RECEIPT_V1|validateStateFields|attemptCount|lastAttemptAt|failureCode|hasSameIdentity|request\s*\()' \
src/main/java/com/clearfolio/viewer/lifecycle \
src/test/java/com/clearfolio/viewer/lifecycle || true
echo '== Receipt references outside lifecycle package =='
rg -n -C 4 --glob '*.java' \
'(ArtifactDeletionReceiptStore|ArtifactDeletionLedger|ArtifactDeletionReceipt|ArtifactDeletionState)' \
src/main/java src/test/java || true
echo '== Changed prohibited-category paths and parent hardening diff =='
git diff --name-only "$base" "$head" | rg -n \
'(^|/)(controller|repository|worker|scheduler|workflow|artifact)(/|$)|pom\.xml$|build\.gradle|package\.json$|(^|/)Dockerfile$|^\.github/|release' || true
git diff --unified=20 "$base" "$head" -- \
src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/service/DefaultDocumentConversionService.java || trueLength of output: 203309 🏁 Script executed: #!/bin/bash
set -euo pipefail
log='/tmp/coderabbit-shell-logs/shell-output-F74lpv'
head='0a447f1dc9cc0afaeb846ddd42999e9319e18d4e'
base='3e98e6fbf8af006f08e50463974468e89daf168d'
echo '== Revision and changed-file evidence from full log =='
sed -n '1,180p' "$log"
echo '== Exact changed paths =='
git diff --name-status "$base" "$head"
echo '== Full receipt state validation =='
sed -n '35,225p' src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java
echo '== Full crash-tail test =='
sed -n '1,130p' src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCrashTailTest.java
echo '== Attempt-evidence test cases and replay mutations =='
rg -n -C 8 --glob '*.java' \
'(lastAttemptAt|attemptCount|replayRejects|invalidFirst|unterminated|truncate|setLength|deleteCharAt)' \
src/test/java/com/clearfolio/viewer/lifecycle
echo '== Append/replay boundary implementation =='
sed -n '214,410p' src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java
echo '== Documentation scope claims and references =='
rg -n -C 3 \
'(atomic|outbox|worker|signed-link|incomplete|complete cleanup|RECEIPT_V1|References|APA|tombstone)' \
CHANGELOG.md docs/security/2026-08-06-durable-artifact-deletion-receipts.md || true
echo '== Exact parent-hardening source status =='
git diff --name-status "$base" "$head" -- \
src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/service/DefaultDocumentConversionService.javaLength of output: 66190 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='0a447f1dc9cc0afaeb846ddd42999e9319e18d4e'
checkout='50d7b25058fe0419e0a3a886c6238ec124332695'
echo '== Relationship between sandbox checkout and requested head =='
printf 'requested head: '; git rev-parse "$head"
printf 'checkout head: '; git rev-parse "$checkout"
printf 'merge-base: '; git merge-base "$head" "$checkout"
printf 'requested-head..checkout commits:\n'
git log --oneline "$head..$checkout" || true
printf 'checkout..requested-head commits:\n'
git log --oneline "$checkout..$head" || true
echo '== Exact requested-head receipt validation =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java" | sed -n '35,225p'
echo '== Exact requested-head replay and append implementation =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java" | sed -n '214,410p'
echo '== Exact requested-head crash-tail test =='
git show "$head:src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCrashTailTest.java" | sed -n '1,130p'
echo '== Exact requested-head attempt-evidence test coverage =='
git grep -n -E \
'(lastAttemptAt|attemptCount|unterminatedFinalRecord|replayRejects)' \
"$head" -- src/test/java/com/clearfolio/viewer/lifecycle || true
echo '== Exact requested-head implementation references outside lifecycle =='
git grep -n -E \
'(ArtifactDeletionReceiptStore|ArtifactDeletionLedger|ArtifactDeletionReceipt|ArtifactDeletionState)' \
"$head" -- ':!src/main/java/com/clearfolio/viewer/lifecycle' ':!src/test/java/com/clearfolio/viewer/lifecycle' || trueLength of output: 22516
I found one actionable finding.
I also verified the following by reading the requested commit object directly. The sandbox checkout had one later commit, so I did not use it as exact-head evidence.
This PR remains Draft. I did not infer success from the pending fuzz run or from any absent CI, security, review, coverage, or approval evidence. I did not resolve the incomplete-cleanup finding. You are interacting with an AI system. |
|
@opencode-agent Fix only the deterministic setup bug in The current write-failure setup constructs
Do not alter production code, other tests, workflow files, dependencies, PR metadata, or the Draft state. Run the focused test if the environment permits and report the exact resulting head. |
|
@coderabbitai review @opencode-agent @cwl-noema-review Re-review exact current head The previously reported replay-validation defect is addressed in Independently verify the current 11-file parent-relative slice, strict bounded Exact-head fuzz run |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
head='8c8cd53a102ac923ea862f6e7ea33e6f9da7b3c8'
base='3e98e6fbf8af006f08e50463974468e89daf168d'
echo '== Exact revision topology =='
printf 'requested head: '; git rev-parse "$head"
printf 'parent: '; git rev-parse "$base"
printf 'merge-base: '; git merge-base "$head" "$base"
printf 'ahead/behind: '; git rev-list --left-right --count "$base...$head"
echo '== Changed paths =='
git diff --name-status "$base" "$head"
echo '== Changed Java file map =='
git diff --name-only "$base" "$head" -- '*.java' |
while IFS= read -r file; do
echo "-- $file"
git show "$head:$file" > "/tmp/$(basename "$file")"
ast-grep outline "/tmp/$(basename "$file")" --items all || true
done
echo '== Receipt model validation and transitions =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java" |
nl -ba | sed -n '1,330p'
echo '== Ledger append, encoding, and replay =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java" |
nl -ba | sed -n '1,520p'
echo '== Public contract and state =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java" |
nl -ba | sed -n '1,260p'
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java" |
nl -ba | sed -n '1,160p'
echo '== Exact-head lifecycle tests and crash-tail test =='
git ls-tree -r --name-only "$head" src/test/java/com/clearfolio/viewer/lifecycle |
rg 'ArtifactDeletion(Ledger|Receipt).*Test\.java$' |
while IFS= read -r file; do
echo "-- $file"
git show "$head:$file" | nl -ba
done
echo '== Exact-head diff for docs/config/changelog =='
git diff --unified=30 "$base" "$head" -- \
CHANGELOG.md \
docs/security/2026-08-06-durable-artifact-deletion-receipts.md \
src/main/resources/application.yml
echo '== Scope and parent-hardening preservation =='
git diff --name-only "$base" "$head" |
rg '(^|/)(controller|repository|worker|scheduler|workflow|artifact)(/|$)|(^|/)(pom\.xml|build\.gradle|package\.json|Dockerfile)$|^\.github/|release' || true
git diff --name-status "$base" "$head" -- \
src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/service/DefaultDocumentConversionService.java
echo '== Receipt integration references outside lifecycle =='
git grep -n -E '(ArtifactDeletionReceiptStore|ArtifactDeletionLedger|ArtifactDeletionReceipt|ArtifactDeletionState)' \
"$head" -- ':!src/main/java/com/clearfolio/viewer/lifecycle' ':!src/test/java/com/clearfolio/viewer/lifecycle' || trueLength of output: 11193 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='8c8cd53a102ac923ea862f6e7ea33e6f9da7b3c8'
base='3e98e6fbf8af006f08e50463974468e89daf168d'
numbered() { awk '{ printf "%6d\t%s\n", NR, $0 }'; }
echo '== Receipt model validation and transitions =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java" | numbered
echo '== Ledger implementation =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java" | numbered
echo '== Contract and state =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java" | numbered
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java" | numbered
echo '== Replay validation tests =='
git show "$head:src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerReplayValidationTest.java" | numbered
echo '== Crash-tail test =='
git show "$head:src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCrashTailTest.java" | numbered
echo '== Main ledger tests =='
git show "$head:src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java" | numbered
echo '== Coverage and I/O tests =='
git show "$head:src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCoverageTest.java" | numbered
echo '== Documentation, changelog, and configuration diff =='
git diff --unified=20 "$base" "$head" -- \
CHANGELOG.md \
docs/security/2026-08-06-durable-artifact-deletion-receipts.md \
src/main/resources/application.yml
echo '== Scope exclusions and parent hardening =='
printf 'prohibited changed paths:\n'
git diff --name-only "$base" "$head" |
grep -E '(^|/)(controller|repository|worker|scheduler|workflow|artifact)(/|$)|(^|/)(pom\.xml|build\.gradle|package\.json|Dockerfile)$|^\.github/|release' || true
printf 'parent hardening paths changed:\n'
git diff --name-status "$base" "$head" -- \
src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/service/DefaultDocumentConversionService.java
printf 'receipt references outside lifecycle package:\n'
git grep -n -E '(ArtifactDeletionReceiptStore|ArtifactDeletionLedger|ArtifactDeletionReceipt|ArtifactDeletionState)' \
"$head" -- ':!src/main/java/com/clearfolio/viewer/lifecycle' ':!src/test/java/com/clearfolio/viewer/lifecycle' || trueLength of output: 107007
I found one actionable finding.
The previously reported replay-validation defect is fixed. I also verified these items:
This PR remains Draft. I did not infer success from the cancelled fuzz run or from absent CI, security, SAST, coverage, Javadoc, review, or approval evidence. You are interacting with an AI system. |
|
@coderabbitai review @opencode-agent @cwl-noema-review Please independently review exact current head Re-evaluate all predecessor feedback against the current source. In particular, verify:
Exact-head fuzz run |
|
@coderabbitai review @opencode-agent @cwl-noema-review Re-evaluate exact ledger head Fresh comparison is 14 commits ahead, 1 behind, with merge base Review the receipt ledger’s immutable identity binding, monotonic/non-reversible lifecycle, attempt-count/time invariants, exact duplicate idempotency, same-job identity-conflict rejection, strict UTF-8 and bounded replay, fixed LF commit delimiter, fail-closed preservation of unterminated/corrupt evidence, controlled failure codes, standalone/MSA adapter boundary, complete public Javadocs, and 100% production line/branch evidence. All current inline CodeRabbit threads are resolved; do not reopen the rejected automatic-truncation proposal unless new evidence shows that preserving corrupt audit bytes is unsafe. Exact-head fuzz run |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
head='4e67e2aff953a9547fb284eb5e15aa3b3c7d334a'
parent='d57f1aa8153aa092607a147c9587c683f009ea06'
merge_base='3e98e6fbf8af006f08e50463974468e89daf168d'
echo '== Exact topology =='
printf 'checkout: '; git rev-parse HEAD
printf 'ledger head: '; git rev-parse "$head"
printf 'current parent: '; git rev-parse "$parent"
printf 'merge base: '; git merge-base "$head" "$parent"
printf 'ahead/behind: '; git rev-list --left-right --count "$parent...$head"
printf 'ledger range commits: '; git rev-list --count "$merge_base..$head"
printf 'parent-only commits: '; git rev-list --count "$merge_base..$parent"
echo '== Three-way path comparison =='
echo '-- ledger slice versus merge base'
git diff --name-status "$merge_base" "$head"
echo '-- parent-only changes versus merge base'
git diff --name-status "$merge_base" "$parent"
echo '-- current parent versus ledger head'
git diff --name-status "$parent" "$head"
echo '== Receipt source outlines at exact ledger head =='
for f in \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java
do
echo "-- $f"
git show "$head:$f" > "/tmp/$(basename "$f")"
ast-grep outline "/tmp/$(basename "$f")" --items all || true
done
echo '== Receipt and ledger implementation =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java" | nl -ba
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java" | nl -ba
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java" | nl -ba
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java" | nl -ba
echo '== Exact ledger-head lifecycle tests =='
git ls-tree -r --name-only "$head" src/test/java/com/clearfolio/viewer/lifecycle |
rg 'ArtifactDeletion.*Test\.java$' |
while IFS= read -r f; do
echo "-- $f"
git show "$head:$f" | nl -ba
done
echo '== Parent-only tenant hardening diff =='
git diff --unified=40 "$merge_base" "$parent" -- \
src/test/java \
src/main/java/com/clearfolio/viewer/repository \
src/main/java/com/clearfolio/viewer/service || true
echo '== Ledger changes relative to merge base and external references =='
git diff --unified=25 "$merge_base" "$head" -- \
src/main/java/com/clearfolio/viewer/lifecycle \
src/test/java/com/clearfolio/viewer/lifecycle \
docs/security \
CHANGELOG.md \
src/main/resources/application.yml
git grep -n -E '(ArtifactDeletionReceiptStore|ArtifactDeletionLedger|ArtifactDeletionReceipt|ArtifactDeletionState)' \
"$head" -- ':!src/main/java/com/clearfolio/viewer/lifecycle' ':!src/test/java/com/clearfolio/viewer/lifecycle' || true
echo '== Coverage and build configuration references at exact ledger head =='
git ls-tree -r --name-only "$head" | rg '(^|/)(pom\.xml|build\.gradle|build\.gradle\.kts)$' |
while IFS= read -r f; do
echo "-- $f"
git show "$head:$f" | rg -n -C 5 '(jacoco|coverage|javadoc|maven-surefire|maven-failsafe)' || true
doneLength of output: 8432 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='4e67e2aff953a9547fb284eb5e15aa3b3c7d334a'
parent='d57f1aa8153aa092607a147c9587c683f009ea06'
base='3e98e6fbf8af006f08e50463974468e89daf168d'
numbered() { awk '{ printf "%6d\t%s\n", NR, $0 }'; }
echo '== Exact receipt model =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java" | numbered
echo '== Exact ledger implementation =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java" | numbered
echo '== Exact contract and state enum =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java" | numbered
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java" | numbered
echo '== Exact ledger-head tests =='
for f in \
src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java \
src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerReplayValidationTest.java \
src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCrashTailTest.java \
src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCoverageTest.java
do
echo "-- $f"
git show "$head:$f" | numbered
done
echo '== Parent-only tenant lookup hardening =='
git diff --unified=35 "$base" "$parent" -- \
src/test/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepositoryTest.java
echo '== Ledger source has no integration outside lifecycle package =='
git grep -n -E '(ArtifactDeletionReceiptStore|ArtifactDeletionLedger|ArtifactDeletionReceipt|ArtifactDeletionState)' \
"$head" -- ':!src/main/java/com/clearfolio/viewer/lifecycle' ':!src/test/java/com/clearfolio/viewer/lifecycle' || true
echo '== Build coverage configuration at ledger head =='
git ls-tree -r --name-only "$head" |
grep -E '(^|/)(pom\.xml|build\.gradle|build\.gradle\.kts)$' |
while IFS= read -r f; do
echo "-- $f"
git show "$head:$f" |
grep -n -E -C 5 '(jacoco|coverage|javadoc|maven-surefire|maven-failsafe)' || true
done
echo '== Documentation scope and replay claims =='
git show "$head:docs/security/2026-08-06-durable-artifact-deletion-receipts.md" |
grep -n -E -C 3 '(LF|UTF-8|unterminated|corrupt|force|atomic|outbox|worker|incomplete|References)' || true
git show "$head:CHANGELOG.md" | grep -n -E -C 2 '(receipt|cleanup|tombstone|outbox)' || trueLength of output: 109836
I found one actionable finding.
Static inspection confirmed the following:
The This PR remains Draft. The successful fuzz run does not provide current-parent compatibility evidence. I did not infer CI, security, SAST, Strix, full Maven, coverage, Javadoc, review, or independent approval success. The incomplete artifact-cleanup finding remains open. ✏️ Learnings added
You are interacting with an AI system. |
1861049 to
8448fdd
Compare
|
@coderabbitai review @opencode-agent @cwl-noema-review Please independently review exact current head Verify immutable receipt identity, tenant and permanently reserved job binding, idempotency, monotonic and non-reversible lifecycle transitions, strict UTF-8 bounded replay, fixed-LF commit delimiters, |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
head='8448fdd98d4a6c58f4e5407fcfcce903785abaa8'
parent='d57f1aa8153aa092607a147c9587c683f009ea06'
numbered() { awk '{ printf "%6d\t%s\n", NR, $0 }'; }
echo '== Exact revision topology =='
printf 'sandbox checkout: '; git rev-parse HEAD
printf 'requested head: '; git rev-parse "$head"
printf 'requested parent: '; git rev-parse "$parent"
printf 'merge-base: '; git merge-base "$head" "$parent"
printf 'ahead/behind: '; git rev-list --left-right --count "$parent...$head"
echo 'commits:'
git rev-list --reverse --oneline "$parent..$head"
echo '== Parent-relative changed paths =='
git diff --name-status "$parent" "$head"
git diff --stat "$parent" "$head"
echo '== Lifecycle source map =='
for f in \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java \
src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java
do
echo "-- $f"
git show "$head:$f" > "/tmp/$(basename "$f")"
ast-grep outline "/tmp/$(basename "$f")" --items all || true
done
echo '== Receipt validation and transitions =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java" | numbered
echo '== Ledger serialization, append, and replay =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java" | numbered
echo '== Public contract and states =='
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java" | numbered
git show "$head:src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java" | numbered
echo '== Exact-head ledger tests =='
git ls-tree -r --name-only "$head" src/test/java/com/clearfolio/viewer/lifecycle |
rg 'ArtifactDeletion.*Test\.java$' |
while IFS= read -r f; do
echo "-- $f"
git show "$head:$f" | numbered
done
echo '== Documentation, changelog, and configuration =='
git diff --unified=30 "$parent" "$head" -- \
CHANGELOG.md \
docs/security/2026-08-06-durable-artifact-deletion-receipts.md \
src/main/resources/application.yml
echo '== Parent explicit-tenant lookup contract, unchanged by this head =='
git show "$parent:src/test/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepositoryTest.java" |
rg -n -C 5 '(findByTenantAndContentHash|blank|null|findByContentHash)' || true
git diff --name-status "$parent" "$head" -- \
src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java \
src/main/java/com/clearfolio/viewer/service/DefaultDocumentConversionService.java \
src/test/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepositoryTest.java
echo '== Scope exclusions and integration references =='
git diff --name-only "$parent" "$head" |
rg '(^|/)(controller|repository|worker|scheduler|workflow|artifact)(/|$)|(^|/)(pom\.xml|build\.gradle|build\.gradle\.kts|package\.json|Dockerfile)$|^\.github/|release|CHANGELOG' || true
git grep -n -E '(ArtifactDeletionReceiptStore|ArtifactDeletionLedger|ArtifactDeletionReceipt|ArtifactDeletionState)' \
"$head" -- ':!src/main/java/com/clearfolio/viewer/lifecycle' ':!src/test/java/com/clearfolio/viewer/lifecycle' || trueLength of output: 122137
I found one actionable finding.
I also verified the following:
I did not run tests because this inspection environment does not execute repository code. I did not infer CI, security, coverage, Javadoc, protected-branch, or independent approval status from the reported fuzz result. This PR remains Draft. The incomplete-cleanup finding remains open.
|
36b192d to
8448fdd
Compare
909c38d to
36b192d
Compare
|
This mutable branch is superseded by two immutable, bounded Drafts:
The current #277 head and all of its checks/reviews are stale for those clean slices. Closing this PR unmerged prevents further automated commits from mixing issue #263 Slice B and Slice C. No approval, protection, or completion is inferred from this closure. |
Buyer-visible lifecycle gap
Authorized tenant deletion currently removes metadata before best-effort artifact-store deletion. Storage failure can therefore leave confidential bytes without restart-replayable cleanup evidence. Issue #263 owns the complete transactional tombstone, outbox, revocation, cleanup-worker, and truthful API/UI solution.
This Draft is the bounded receipt-ledger foundation only. It does not claim that artifact cleanup or deletion completion is integrated.
Exact current stack
Exact head:
8448fdd98d4a6c58f4e5407fcfcce903785abaa8.The branch was reconstructed directly on parent PR #268 exact head
d57f1aa8153aa092607a147c9587c683f009ea06after that parent advanced. Fresh comparison reports:The test-first sequence is:
7e0c8f3da1f6d5063b6172da2c40b5b5ce41eb32— defines deterministic receipt identity, replay, crash-tail, transition, failure, and coverage contracts.8448fdd98d4a6c58f4e5407fcfcce903785abaa8— adds the standalone and file-backed ledger implementation, configuration, documentation, and changelog evidence.Changed ledger files:
CHANGELOG.mddocs/security/2026-08-06-durable-artifact-deletion-receipts.mdsrc/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.javasrc/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.javasrc/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.javasrc/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.javasrc/main/resources/application.ymlsrc/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCoverageTest.javasrc/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCrashTailTest.javasrc/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerReplayValidationTest.javasrc/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.javaNo endpoint, controller, existing repository mutation, artifact-store mutation, scheduler, workflow, dependency, packaging, version, or release is changed.
Receipt and MSA contract
ArtifactDeletionReceiptStoreis the standalone and replaceable service boundary. Its reference adapter supports direct in-memory construction and Spring file-backed operation atdata/artifact-deletion-receipts.log.Each immutable
RECEIPT_V1identity binds deletion request ID, tenant, permanently reserved conversion-job ID, exact artifact SHA-256, privacy-safe audit correlation, and request time. Exact duplicates are idempotent. Any same-job identity conflict fails closed.The monotonic lifecycle is:
DELETION_REQUESTED → METADATA_TOMBSTONED → ARTIFACT_CLEANUP_PENDING → ARTIFACT_CLEANUP_COMPLETEDwith retry:
ARTIFACT_CLEANUP_PENDING → ARTIFACT_CLEANUP_FAILED → ARTIFACT_CLEANUP_PENDING.Completion is terminal. Time cannot reverse. Failure evidence is restricted to controlled
[a-z0-9_]{1,64}codes.Durability and replay boundary
RECEIPT_V1record is bounded to 16 KiB.FileChannel.force(true).Remaining product work
This PR does not resolve #268's incomplete-cleanup finding. Still required under #263:
202and status semantics;Exact-head acceptance state
For exact current head
8448fdd98d4a6c58f4e5407fcfcce903785abaa8:31096007229completed successfully across all three targets;Keep this PR Draft. Parent #270 must integrate before #268, and #268 must integrate before this slice. After reconciliation onto protected
main, rerun every exact-head and base-sensitive gate and merge only with zero actionable unresolved threads and all repository protections satisfied. Do not weaken tests, infer approval from advisory status, resolve the cleanup finding prematurely, bypass protections, or publish a release.