feat(lifecycle): add immutable artifact-deletion receipt foundation v2 - #282
feat(lifecycle): add immutable artifact-deletion receipt foundation v2#282seonghobae wants to merge 5 commits into
Conversation
|
Warning Review limit reached
Next review available in: 14 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (12)
Comment |
|
@coderabbitai review @opencode-agent @cwl-noema-review Please independently review exact current head |
|
I will not approve the PR or claim passing checks until the required exact-head evidence and repository protections are available.
|
|
@coderabbitai review @opencode-agent @cwl-noema-review Please independently review exact current head |
|
I will verify the specified receipt-store contracts, four-commit RED/GREEN sequence, 12-file scope, inherited tenant isolation, and absence of out-of-scope changes. I will not approve the PR or claim passing evidence unless the required exact-head checks and repository protections are complete.
|
|
@coderabbitai @opencode-agent @cwl-noema-review Please perform a fresh formal review of exact head |
|
Closing unmerged as superseded. The exact receipt-foundation history and tree are now fast-forward integrated into PR #268 exact head |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
head='3396c03a458294175006efd0c9cea35d6911d55c'
parent='3ba53ac843685e483fdd3f8f060ba61825b9a798'
printf '%s\n' '== Checked-out commit and requested commits =='
git rev-parse HEAD
git cat-file -t "$head"
git cat-file -t "$parent"
printf 'merge-base: '
git merge-base "$head" "$parent"
printf '%s\n' '== Commit sequence =='
git log --reverse --format='%H %s' "$parent..$head"
printf '%s\n' '== Changed files and diff stat =='
git diff --stat "$parent" "$head"
git diff --name-status "$parent" "$head"
printf '%s\n' '== Repository status =='
git status --short
printf '%s\n' '== Java source and test structure for receipt symbols =='
rg -n -i -C 2 'ArtifactDeletionReceipt(Store|File|Memory)?|RECEIPT_V1|FileChannel\.force|DELETION_REQUESTED|ARTIFACT_CLEANUP' \
-g '*.java' .
printf '%s\n' '== Changed-file outlines =='
while IFS= read -r path; do
case "$path" in
*.java)
printf '\n--- %s ---\n' "$path"
ast-grep outline "$path" --items all --view expanded || true
;;
esac
done < <(git diff --name-only "$parent" "$head")
printf '%s\n' '== Parent tenant-lifecycle query evidence =='
rg -n -i -C 4 'buyer-demo|tenant.*lifecycle|lifecycle.*tenant|scopedTenant' -g '*.java' .Length of output: 83722 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='3396c03a458294175006efd0c9cea35d6911d55c'
parent='3ba53ac843685e483fdd3f8f060ba61825b9a798'
show() {
local path="$1"
printf '\n===== %s =====\n' "$path"
git show "${head}:${path}" | nl -ba
}
printf '%s\n' '== Exact-head implementation =='
show 'src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java'
show 'src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java'
show 'src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java'
show 'src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java'
printf '%s\n' '== Exact-head receipt test method map =='
for path in \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java' \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCoverageTest.java' \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCrashTailTest.java' \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerReplayCoverageTest.java' \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerReplayValidationTest.java'
do
printf '\n===== %s =====\n' "$path"
git show "${head}:${path}" | rg -n -C 2 '`@Test`|void [A-Za-z0-9_]+' || true
done
printf '%s\n' '== Out-of-scope change check =='
git diff --name-only "$parent" "$head" | rg -n -i \
'(^|/)(controller|endpoint|worker|scheduler|workflow|pom\.xml|build\.gradle|gradle\.properties|package\.json|Dockerfile|.*\.github/|.*\.yml)$' \
|| true
printf '%s\n' '== Parent tenant-isolation changes and matching source =='
git diff -U8 "$parent" "$head" -- \
'src/main/java/**/*.java' | rg -n -C 5 'buyer-demo|tenant|lifecycle' || true
git grep -n -i -E 'buyer-demo|scopedTenant|tenant.*lifecycle|lifecycle.*tenant' "$parent" -- 'src/main/java/*.java' 'src/main/java/**/*.java' || trueLength of output: 2338 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='3396c03a458294175006efd0c9cea35d6911d55c'
parent='3ba53ac843685e483fdd3f8f060ba61825b9a798'
show_numbered() {
local path="$1"
printf '\n===== %s =====\n' "$path"
git show "${head}:${path}" | awk '{printf "%5d %s\n", NR, $0}'
}
printf '%s\n' '== Exact-head receipt model =='
show_numbered 'src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceipt.java'
printf '%s\n' '== Exact-head ledger adapter =='
show_numbered 'src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedger.java'
printf '%s\n' '== Exact-head store contract and states =='
show_numbered 'src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionReceiptStore.java'
show_numbered 'src/main/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionState.java'
printf '%s\n' '== Exact-head test names =='
for path in \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerTest.java' \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCoverageTest.java' \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCrashTailTest.java' \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerReplayCoverageTest.java' \
'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerReplayValidationTest.java'
do
printf '\n===== %s =====\n' "$path"
git show "${head}:${path}" | rg -n -C 1 '`@Test`|void [A-Za-z0-9_]+' || true
done
printf '%s\n' '== Exact range: potentially out-of-scope files =='
git diff --name-only "$parent" "$head" | rg -n -i \
'(^|/)(controller|endpoint|worker|scheduler|workflow|pom\.xml|build\.gradle|gradle\.properties|package\.json|Dockerfile|.*\.github/|.*\.yml)$' \
|| true
printf '%s\n' '== Tenant-isolation source at the immutable parent =='
git grep -n -i -E 'buyer-demo|scopedTenant|tenant.*lifecycle|lifecycle.*tenant' "$parent" -- 'src/main/java' || trueLength of output: 49143 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='3396c03a458294175006efd0c9cea35d6911d55c'
parent='3ba53ac843685e483fdd3f8f060ba61825b9a798'
slice() {
local object="$1"
local path="$2"
local first="$3"
local last="$4"
printf '\n===== %s:%s lines %s-%s =====\n' "$object" "$path" "$first" "$last"
git show "${object}:${path}" | sed -n "${first},${last}p" | awk -v n="$first" '{printf "%5d %s\n", n++, $0}'
}
printf '%s\n' '== CRLF replay behavior and test expectation =='
slice "$head" 'src/test/java/com/clearfolio/viewer/lifecycle/ArtifactDeletionLedgerCoverageTest.java' 195 225
printf '%s\n' '== ADR and changelog delimiter and replay contract =='
git show "${head}:docs/security/2026-08-06-durable-artifact-deletion-receipts.md" \
| rg -n -i -C 4 'LF|CRLF|delimiter|UTF-8|tail|16 KiB|16KiB|replay'
git show "${head}:CHANGELOG.md" | tail -n 40
printf '%s\n' '== Exact configuration change =='
git diff -U12 "$parent" "$head" -- 'src/main/resources/application.yml'
printf '%s\n' '== Parent tenant lifecycle query implementation =='
git grep -n -E 'findLifecycleEventsByTenantId|scopedTenant' "$parent" -- 'src/main/java' 'src/test/java' || true
git show "${parent}:src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java" \
| sed -n '230,285p' | awk '{printf "%5d %s\n", NR + 229, $0}'
printf '%s\n' '== Exact-head difference from requested commit is excluded from review =='
git log --oneline "${head}..HEAD"Length of output: 16156
P1 — Reject CRLF records during replay. The receipt contract requires a fixed ASCII LF ( I also verified these items by static inspection of the exact Git object:
I did not approve this PR. The stated fuzz result does not replace the absent CI, Security Scan, SAST, complete Maven/JaCoCo/Javadoc evidence, or independent counted approval.
|
Objective
Part of #263, Slice B. Add only the durable
RECEIPT_V1artifact-deletion state-store foundation on the exact tenant-isolated administrator snapshot. HTTP mutation, cleanup execution, scheduling, signed-link revocation, and product-status semantics remain later slices.Exact clean stack
Exact current head is
3396c03a458294175006efd0c9cea35d6911d55con immutable parent snapshot3ba53ac843685e483fdd3f8f060ba61825b9a798through base branchsnapshot/admin-endpoint-auth-3ba53ac.The parent is the merge base. The slice changes exactly 12 foundation-scoped files and preserves the parent's fail-closed lifecycle-event tenant query: null and blank scoped tenant identifiers cannot infer
buyer-demo. It changes no endpoint, controller, cleanup worker, scheduler, workflow, dependency, packaging, version, or release path.Test-first provenance
96a09662eed2449baece2b76e3bdd3d5c6800300defines deterministic receipt identity, append, replay, crash-tail, transition, and failure contracts.8c803dafd14c1b6e7cac80b39e5c5a9915fc1cbdadds the versioned store, configuration, ADR, changelog, and implementation.31200cf17c18104568f7cd4b22ef87b1c83a20a1restores deterministic coverage for full failure/retry/completion replay, terminal completion, malformed versions, blank required tenants, inconsistent failure evidence, and immutable-identity mutation.3396c03a458294175006efd0c9cea35d6911d55cremoves a redundant initial-attempt replay branch while retaining constructor-level invariant enforcement and complete fail-closed replay validation.Receipt and durability contract
Each immutable identity 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; same-job identity conflicts fail 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. Transition time cannot reverse. Attempt count and attempt time must coexist consistently and remain preserved through retry and completion. Failure evidence is restricted to controlled
[a-z0-9_]{1,64}codes.Strict UTF-8
RECEIPT_V1records are bounded to 16 KiB. Append uses a fixed LF commit delimiter and returns only afterFileChannel.force(true). Any non-empty unterminated final tail fails closed and is preserved. Replay rejects malformed Base64URL, blank or missing identity, invalid timestamps, states, counts, immutable conflicts, non-monotonic time, illegal successors, unsafe failure details, and oversized records. Completed receipts remain retained for idempotency but are excluded from pending work. Standalone in-memory and restart-replay file adapters implement oneArtifactDeletionReceiptStoreMSA contract.Exact-head acceptance state
For exact current head
3396c03a458294175006efd0c9cea35d6911d55c:31102838777completed successfully acrossTenantClaimsFuzzTest,DocumentValidationFuzzTest, andArtifactTokenParserFuzzTestafter each job verified the exact checked-out SHA under Java 21;Queued, pending, cancelled, skipped-required, absent-required, stale-head, predecessor-head, advisory-only, local-only, or synthetic-only evidence is not passing.
PR #280 was closed unmerged as superseded; none of its checks or reviews are transferred. Keep this PR Draft. Parent order remains #270 → #268 → this foundation → cleanup worker #283. This foundation alone does not resolve incomplete artifact cleanup or prove physical deletion completion. Do not weaken tests, infer approval from status-only evidence, bypass protections, or publish a release.