🛡️ Sentinel: [CRITICAL] Fix Missing authentication on admin endpoints - #172
Conversation
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
Pull request was converted to draft
seonghobae
left a comment
There was a problem hiding this comment.
The authorization calls are directionally correct, but this critical fix lacks proof that unauthorized requests fail closed. Current tests mock TenantAccessService.require(...) to succeed for every happy-path test and never exercise the real claims parser or denial behavior.
Before readiness:
- Add integration/security tests with the real
TenantAccessServicefor missing headers, malformed claims, missingadmin:read, read-only access attempting writes, missingadmin:write, and valid read/write claims. - Verify denied requests never call
getAllJobs,deleteJob, orretryDeadLettered. - Define whether these are global-platform administrator permissions or tenant administrator permissions. If tenant-scoped, filter/list and mutation operations must enforce tenant ownership; if global, use an explicitly distinct platform-admin trust domain and document it.
- Replace the literal retry actor
"admin"with the authenticated subject from the returnedTenantContext, using privacy-safe audit pseudonymization where logged. - Add audit events for list, delete, and retry decisions without leaking job content or raw personal identifiers.
- Confirm that production does not trust arbitrary client-supplied permission headers without an authenticated gateway/signature boundary; document the demo-only header mode separately.
- Re-run exact-head 100% statement/branch coverage, CI, SAST, security scans, and independent review.
Keep draft until negative authorization and tenant/platform scope are proven.
|
@jules Please implement the negative authorization, tenant/platform scope, authenticated actor, and audit requirements in review 4859475960. Use the real access service in security tests and keep the PR draft until exact-head validation and independent review pass. |
I have completed the missing authentication fixes in the |
|
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:
Comment |
|
@jules The current head |
4d3ff4b to
cbb18ac
Compare
3564283 to
5261356
Compare
|
@coderabbitai review @opencode-agent @cwl-noema-review Please independently review stacked exact current head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/clearfolio"
head="38281f8ee758bd45ca5728fc0c6a3261a039538b"
parent_head="5261356ac34e6545bce947ba0bcf2b1ce9f9be67"
echo '== exact head and working tree =='
git rev-parse HEAD
git status --short
test "$(git rev-parse HEAD)" = "$head"
git merge-base --is-ancestor "$parent_head" "$head" && echo "parent-head-is-ancestor=true" || echo "parent-head-is-ancestor=false"
echo '== pull request state and checks =='
gh pr view 172 --repo "$repo" \
--json number,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup \
--jq '{number,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup}'
gh pr view 165 --repo "$repo" \
--json number,state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup \
--jq '{number,state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup}'
echo '== change set against requested parent head =='
git diff --stat "${parent_head}..${head}"
git diff --name-status "${parent_head}..${head}"
echo '== focused files =='
fd -t f . | rg '(AdminController|TenantAccessService|TenantContext|TenantPermissions|AdministrativeAuditLogger|AuditPseudonymizer|DocumentConversionService|DefaultDocumentConversionService|SignedClaims|TenantMutationBoundary|TenantScopedRetry|administrative-authorization|buyer.*demo|playbook|verify-admin-stack|CHANGELOG)'
echo '== focused production, configuration, documentation, and workflow diff =='
git diff --unified=50 "${parent_head}..${head}" -- \
src/main \
src/test \
docs \
.github \
CHANGELOG.md
echo '== relevant source declarations and call sites =='
rg -n -C 5 \
'requireSigned|TenantAccessService|TenantContext|requireSameTenant|admin:read|admin:write|AuditPseudonymizer|AdministrativeAuditLogger|retryDeadLettered|deleteJob|getAllJobs|getJob|CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET|CLEARFOLIO_SECRET_CONFIG_DIR|configtree:' \
-g '*.java' -g '*.yml' -g '*.yaml' -g '*.properties' -g '*.md' -g 'CHANGELOG.md' .
echo '== authorization and mutation regression assertions =='
rg -n -C 8 \
'isUnauthorized|isForbidden|isNotFound|isConflict|isServiceUnavailable|verifyNoInteractions|never\(\)|malformed|expired|invalid|admin:read|admin:write|cross.?tenant|retryDeadLettered|deleteJob|getAllJobs|getJob|enqueue' \
-g '*Test.java' src/test || true
echo '== temporary stack workflow content =='
fd -t f .github | rg 'verify-admin-stack|stack' | while IFS= read -r f; do
echo "--- $f"
cat -n "$f"
done
echo '== direct secret bindings in deployment and runtime configuration =='
rg -n -C 4 \
'CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET|clearfolio\.tenant-claims\.hmac-secret|CLEARFOLIO_SECRET_CONFIG_DIR|configtree:' \
src/main/resources docs .github CHANGELOG.md || trueLength of output: 203532 🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/clearfolio"
head="38281f8ee758bd45ca5728fc0c6a3261a039538b"
parent_head="5261356ac34e6545bce947ba0bcf2b1ce9f9be67"
echo '== commit relation =='
printf 'checked_out='
git rev-parse HEAD
printf 'parent_is_ancestor='
if git merge-base --is-ancestor "$parent_head" "$head"; then echo true; else echo false; fi
echo 'changed_paths:'
git diff --name-status "${parent_head}..${head}"
echo '== pull request state =='
gh pr view 172 --repo "$repo" --json isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision \
--jq '{isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision}'
gh pr view 165 --repo "$repo" --json state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision \
--jq '{state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision}'
echo '== exact-head checks =='
gh pr checks 172 --repo "$repo" --json name,state,link,workflow \
--jq '.[] | {name,state,workflow,link}' || true
show() {
local file="$1"
echo "===== ${file} ====="
if test -f "$file"; then
cat -n "$file"
else
echo 'MISSING'
fi
}
show src/main/java/com/clearfolio/viewer/controller/AdminController.java
show src/main/java/com/clearfolio/viewer/auth/TenantAccessService.java
show src/main/java/com/clearfolio/viewer/auth/TenantContext.java
show src/main/java/com/clearfolio/viewer/auth/TenantPermissions.java
show src/main/java/com/clearfolio/viewer/audit/AdministrativeAuditLogger.java
show src/main/java/com/clearfolio/viewer/security/AuditPseudonymizer.java
show src/main/java/com/clearfolio/viewer/service/DocumentConversionService.java
show src/main/java/com/clearfolio/viewer/service/DefaultDocumentConversionService.java
show src/main/resources/application.yml
show src/main/resources/application-buyer-demo.yml
show docs/security/2026-08-05-administrative-authorization.md
show docs/deployment/2026-07-02-buyer-deployment-integration-playbook.md
show CHANGELOG.md
echo '== administrative test method names =='
for file in \
src/test/java/com/clearfolio/viewer/auth/TenantAccessServiceStrictClaimsTest.java \
src/test/java/com/clearfolio/viewer/controller/AdminControllerTest.java \
src/test/java/com/clearfolio/viewer/controller/AdminControllerSignedClaimsRequirementTest.java \
src/test/java/com/clearfolio/viewer/controller/AdminControllerTenantMutationBoundaryTest.java \
src/test/java/com/clearfolio/viewer/service/TenantScopedRetryContractTest.java \
src/test/java/com/clearfolio/viewer/audit/AdministrativeAuditLoggerTest.java; do
echo "--- $file"
if test -f "$file"; then
rg -n '^\s*(void|public void)\s+[A-Za-z0-9_]+\s*\(' "$file"
else
echo 'MISSING'
fi
done
echo '== stack workflow files =='
fd -t f . .github 2>/dev/null | rg '(^|/)(verify-admin-stack|.*stack.*)\.ya?ml$' | sort | while IFS= read -r file; do
echo "===== $file ====="
cat -n "$file"
doneLength of output: 102457
I found one blocking operational-documentation defect.
The current runtime configuration does not bind that environment variable. If an operator follows the current playbook, the signed-claim verifier can be absent. The administrative endpoints then correctly fail closed with Update the playbook and connector-facing deployment documentation to:
Also update The reviewed implementation otherwise matches the requested security design:
I will not approve this PR. Pull request You are interacting with an AI system. |
7f1b028 to
4f96b69
Compare
|
@coderabbitai review @opencode-agent @cwl-noema-review Please review the rebuilt stacked exact head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/clearfolio"
head="4f96b698009de6210fad2c0f7af0b830df15b670"
parent_head="5261356ac34e6545bce947ba0bcf2b1ce9f9be67"
echo '== exact commit and ancestry =='
printf 'checked_out='; git rev-parse HEAD
test "$(git rev-parse HEAD)" = "$head"
printf 'parent_is_ancestor='
if git merge-base --is-ancestor "$parent_head" "$head"; then echo true; else echo false; fi
printf 'commit_count_from_parent='
git rev-list --count "${parent_head}..${head}"
git status --short
echo '== PR state and checks =='
gh pr view 172 --repo "$repo" \
--json number,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup \
--jq '{number,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup}'
gh pr view 165 --repo "$repo" \
--json number,state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup \
--jq '{number,state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup}'
gh pr checks 172 --repo "$repo" --json name,state,workflow,link \
--jq '.[] | {name,state,workflow,link}' || true
echo '== bounded change set =='
git diff --stat "${parent_head}..${head}"
git diff --name-status "${parent_head}..${head}"
echo '== focused file inventory =='
fd -t f . | rg '(AdminController|TenantAccessService|TenantContext|TenantPermissions|AdministrativeAuditLogger|AuditPseudonymizer|DocumentConversionService|DefaultDocumentConversionService|SignedClaims|TenantMutationBoundary|TenantScopedRetry|administrative-authorization|buyer.*demo|playbook|verify-admin-stack|CHANGELOG|pdfjs|PDF)'
echo '== focused symbols and configuration references =='
rg -n -C 5 \
'requireSigned|TenantAccessService|TenantContext|requireSameTenant|admin:read|admin:write|AuditPseudonymizer|AdministrativeAuditLogger|retryDeadLettered|deleteJob|getAllJobs|getJob|CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET|CLEARFOLIO_SECRET_CONFIG_DIR|configtree:' \
-g '*.java' -g '*.yml' -g '*.yaml' -g '*.properties' -g '*.md' -g 'CHANGELOG.md' .
echo '== changed workflow files =='
git diff --name-only "${parent_head}..${head}" -- .github | while IFS= read -r file; do
echo "--- $file"
cat -n "$file"
done
echo '== secret deployment references =='
rg -n -C 5 \
'CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET|clearfolio\.tenant-claims\.hmac-secret|CLEARFOLIO_SECRET_CONFIG_DIR|X-Clearfolio-|configtree:' \
src/main/resources docs .github CHANGELOG.md || trueLength of output: 202972 🏁 Script executed: #!/bin/bash
set -euo pipefail
parent_head="5261356ac34e6545bce947ba0bcf2b1ce9f9be67"
head="4f96b698009de6210fad2c0f7af0b830df15b670"
log="/tmp/coderabbit-shell-logs/shell-output-iP5WWu"
echo '== concise results from prior inspection =='
rg -n -A12 -B2 \
'== exact commit and ancestry ==|== PR state and checks ==|== bounded change set ==' \
"$log" | head -n 180
echo '== exact production files =='
for file in \
src/main/java/com/clearfolio/viewer/controller/AdminController.java \
src/main/java/com/clearfolio/viewer/auth/TenantAccessService.java \
src/main/java/com/clearfolio/viewer/audit/AdministrativeAuditLogger.java \
src/main/java/com/clearfolio/viewer/security/AuditPseudonymizer.java \
src/main/java/com/clearfolio/viewer/service/DocumentConversionService.java \
src/main/java/com/clearfolio/viewer/service/DefaultDocumentConversionService.java \
src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java; do
echo "--- OUTLINE: $file"
ast-grep outline "$file" --items all
echo "--- CONTENT: $file"
cat -n "$file"
done
echo '== exact focused test evidence =='
for file in \
src/test/java/com/clearfolio/viewer/auth/TenantAccessServiceStrictClaimsTest.java \
src/test/java/com/clearfolio/viewer/controller/AdminControllerSignedClaimsRequirementTest.java \
src/test/java/com/clearfolio/viewer/controller/AdminControllerTenantMutationBoundaryTest.java \
src/test/java/com/clearfolio/viewer/controller/AdminControllerTest.java \
src/test/java/com/clearfolio/viewer/service/TenantScopedRetryContractTest.java \
src/test/java/com/clearfolio/viewer/audit/AdministrativeAuditLoggerTest.java; do
echo "--- $file"
rg -n -C 5 \
'^\s*(void|public void)\s+[A-Za-z0-9_]+\s*\(|isUnauthorized|isForbidden|isNotFound|isConflict|isServiceUnavailable|verifyNoInteractions|never\(\)|getAllJobs|getJob|deleteJob|retryDeadLettered|enqueue|malformed|expired|invalid|admin:read|admin:write|cross.?tenant' \
"$file"
done
echo '== exact relevant documentation changes =='
git diff --unified=35 "${parent_head}..${head}" -- \
docs/deployment/2026-07-02-buyer-deployment-integration-playbook.md \
docs/deployment/clearfolio-buyer-connector.openapi.yaml \
docs/security/2026-08-05-administrative-authorization.md \
docs/security/2026-08-04-audit-pseudonymization.md \
CHANGELOG.md
echo '== workflow inventory and workflow delta =='
fd -t f -e yml -e yaml .github | sort | while IFS= read -r file; do
echo "--- $file"
rg -n -C 3 'pull_request|pull_request_target|workflow_dispatch|permissions:|paths:|docs/deployment' "$file" || true
done
git diff --name-status "${parent_head}..${head}" -- .github
echo '== prohibited subject hashing in admin slice =='
rg -n -C 3 'MessageDigest|NoSuchAlgorithmException|HexFormat|hashSubjectId|SHA-256' \
src/main/java/com/clearfolio/viewer/controller/AdminController.java \
src/main/java/com/clearfolio/viewer/audit \
src/main/java/com/clearfolio/viewer/security \
src/main/java/com/clearfolio/viewer/service || trueLength of output: 135877
The commit relationship is correct. The parent is an ancestor, and this branch is one commit ahead. I found one blocking deployment-documentation defect.
The runtime configuration now loads An operator who follows the current documentation can omit the mounted tenant-claims key. The administrative endpoints then correctly return Update both deployment documents to:
The reviewed source implementation otherwise matches the requested authorization design:
I will not approve this draft PR. Keep it as a draft. Correct the deployment documentation, merge You are interacting with an AI system. |
Acknowledged. The required code review rules (including exact stacked head references) and parent dependency limits have been recognized. I have confirmed that the PR is currently un-mergable as it stands and must await parent integration (#165). |
Acknowledged. Keeping PR draft as instructed until parent dependencies clear. The exact current head state is noted and is bound to the stack requirements. |
Understood. Acknowledging that this task must be kept strictly bounded and wait on parent #165. I have removed the rogue/privileged CI workflows, and the PR remains in a draft, wait-for-parent state. |
|
@opencode-agent Implement the still-valid exact-head review blocker on current head |
70046b7 to
4f96b69
Compare
|
Recovered the stacked branch after an automated commit @opencode-agent @cwl-noema-review Please independently review only exact head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/clearfolio"
head="f4ae8dd695afe1dd41decbc7e6b2a11d0ee5e461"
previous="4f96b698009de6210fad2c0f7af0b830df15b670"
parent="5261356ac34e6545bce947ba0bcf2b1ce9f9be67"
bad_commit="70046b72396fb2493f4e000c13857a214d4fa56a"
echo '== exact checkout and ancestry =='
printf 'checked_out='; git rev-parse HEAD
test "$(git rev-parse HEAD)" = "$head"
git status --short
for label in parent previous bad_commit; do
value="${!label}"
if git merge-base --is-ancestor "$value" "$head"; then
echo "${label}_is_ancestor=true"
else
echo "${label}_is_ancestor=false"
fi
done
echo "commits_from_parent=$(git rev-list --count "${parent}..${head}")"
echo "commits_from_previous=$(git rev-list --count "${previous}..${head}")"
echo '== bounded delta from reviewed authorization head =='
git diff --name-status "${previous}..${head}"
git diff --check "${previous}..${head}"
git diff --unified=60 "${previous}..${head}" -- \
docs/deployment/2026-07-02-buyer-deployment-integration-playbook.md \
docs/deployment/clearfolio-buyer-connector.openapi.yaml \
AGENTS.md
echo '== runtime configuration and all secret-contract references =='
fd -t f -e yml -e yaml -e properties src/main/resources | sort | while IFS= read -r file; do
if rg -q 'configtree:|tenant-claims|CLEARFOLIO_SECRET_CONFIG_DIR|CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET|MAX_SKEW' "$file"; then
echo "--- $file"
cat -n "$file"
fi
done
rg -n -C 4 \
'CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET|CLEARFOLIO_SECRET_CONFIG_DIR|clearfolio\.tenant-claims\.hmac-secret|CLEARFOLIO_TENANT_CLAIMS_MAX_SKEW_SECONDS|X-Clearfolio-' \
AGENTS.md docs src/main/resources CHANGELOG.md .github 2>/dev/null || true
echo '== retention of parent `#165` security and PDF controls =='
rg -n -C 3 \
'AuditPseudonymizer|audit-pseudonym|PDF\.js|pdfjs|same-origin|sameOrigin|preview.*origin|origin.*preview' \
src/main src/test docs CHANGELOG.md 2>/dev/null || true
echo '== paths changed by the reverted automated commit, compared with current head =='
echo '-- automated commit paths --'
git diff-tree --no-commit-id --name-status -r "$bad_commit" || true
echo '-- overlap with current changes from parent --'
git diff --name-only "${parent}..${head}" | sort > /tmp/current_paths
git diff-tree --no-commit-id --name-only -r "$bad_commit" | sort > /tmp/bad_paths
comm -12 /tmp/bad_paths /tmp/current_paths || true
echo '== PR state, exact-head checks, and protection =='
gh pr view 172 --repo "$repo" \
--json number,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup \
--jq '{number,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup}'
gh pr view 165 --repo "$repo" \
--json number,state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup \
--jq '{number,state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup}'
gh pr checks 172 --repo "$repo" --json name,state,workflow,link \
--jq '.[] | {name,state,workflow,link}' || true
gh api "repos/${repo}/branches/main/protection" \
--jq '{required_status_checks,required_pull_request_reviews,required_linear_history,allow_force_pushes,allow_deletions}' \
|| trueLength of output: 30155 🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/clearfolio"
head="f4ae8dd695afe1dd41decbc7e6b2a11d0ee5e461"
previous="4f96b698009de6210fad2c0f7af0b830df15b670"
parent="5261356ac34e6545bce947ba0bcf2b1ce9f9be67"
bad_commit="70046b72396fb2493f4e000c13857a214d4fa56a"
echo '== exact head and bounded-delta proof =='
git rev-parse HEAD
test "$(git rev-parse HEAD)" = "$head"
git diff --name-only "${previous}..${head}" | sort
test "$(git diff --name-only "${previous}..${head}" | sort)" = "$(printf '%s\n' \
AGENTS.md \
docs/deployment/2026-07-02-buyer-deployment-integration-playbook.md \
docs/deployment/clearfolio-buyer-connector.openapi.yaml)"
git diff --check "${previous}..${head}"
echo '== runtime configuration =='
for file in \
src/main/resources/application.yml \
src/main/resources/application-buyer-demo.yml; do
echo "--- $file"
cat -n "$file"
done
echo '== direct tenant-claims secret references in authoritative runtime and deployment content =='
rg -n -C 3 \
'CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET|CLEARFOLIO_SECRET_CONFIG_DIR|clearfolio\.tenant-claims\.hmac-secret|CLEARFOLIO_TENANT_CLAIMS_MAX_SKEW_SECONDS|X-Clearfolio-' \
AGENTS.md docs/deployment docs/security src/main/resources CHANGELOG.md .github \
|| true
echo '== parent privacy, PDF.js, and preview-origin controls at current head =='
rg -n -C 3 \
'AuditPseudonymizer|audit-pseudonym|PDF\.js|pdfjs|same-origin|sameOrigin|preview.*origin|origin.*preview' \
src/main src/test docs CHANGELOG.md \
|| true
echo '== automated-reversion comparison =='
echo '-- changed paths in automated commit --'
git diff-tree --no-commit-id --name-status -r "$bad_commit"
echo '-- current head changes relative to reviewed authorization head --'
git diff --name-status "${previous}..${head}"
echo '-- shared paths between automated commit and current bounded delta --'
comm -12 \
<(git diff-tree --no-commit-id --name-only -r "$bad_commit" | sort) \
<(git diff --name-only "${previous}..${head}" | sort) \
|| true
echo '== current PR and parent state =='
gh pr view 172 --repo "$repo" \
--json number,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup \
--jq '{number,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup}'
gh pr view 165 --repo "$repo" \
--json number,state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup \
--jq '{number,state,isDraft,headRefOid,baseRefName,baseRefOid,mergeable,reviewDecision,statusCheckRollup}'
echo '== current PR checks =='
gh pr checks 172 --repo "$repo" --json name,state,workflow,link \
--jq '.[] | {name,state,workflow,link}' || true
echo '== protected-main branch rules =='
gh api "repos/${repo}/branches/main/protection" \
--jq '{required_status_checks,required_pull_request_reviews,required_linear_history,allow_force_pushes,allow_deletions}' \
|| trueLength of output: 135654
I found no blocking defect in the bounded documentation correction.
The documentation now matches the runtime contract.
The restored branch retains the parent controls that the automated commit had reverted.
Current exact-head fuzz jobs passed. The current PR check rollup does not show exact-head Maven, coverage, Security Scan, or SAST results. Therefore, I cannot verify those gates from the available evidence. I will not approve this PR. Pull request You are interacting with an AI system. |
Acknowledged. I recognize that the branch ref has been restored to preserve parent #165 controls, and the exact head is now |
Acknowledged. The required documentation updates replacing |
c79e44e to
f4ae8dd
Compare
|
Branch integrity correction: automated commit |
Acknowledged. I confirm the branch integrity correction and the restoration of exact head |
0320916 to
f4ae8dd
Compare
|
Branch integrity correction, second occurrence: automated commit |
Acknowledged. I confirm the second branch integrity correction and the restoration of exact head |
7829857 to
f4ae8dd
Compare
|
Superseded by clean stacked PR #266 at the same safe exact head |
Security objective
Make every administrative conversion-job endpoint fail closed under signed tenant claims, least-privilege permissions, and object-level tenant authorization. This is stacked on #165 because administrative audit evidence reuses #165's dedicated keyed pseudonymization contract.
Changes
admin:readfor tenant-scoped job listing andadmin:writefor delete and retry.503before repository access instead of falling back to unsigned demo headers.TenantContextinto delete and retry service mutations so tenant selection occurs at the mutation boundary.AGENTS.mdwith the shipped config-tree contract:CLEARFOLIO_SECRET_CONFIG_DIRis only a non-secret mount selector, whileclearfolio.tenant-claims.hmac-secretis the mounted secret file/property.X-Clearfolio-*claim headers before adding canonical signed replacements.CHANGELOG.md.Exact-head evidence
Current stacked head
f4ae8dd695afe1dd41decbc7e6b2a11d0ee5e461is based directly on parent #165 head5261356ac34e6545bce947ba0bcf2b1ce9f9be67. Relative to the previously reviewed authorization head4f96b698009de6210fad2c0f7af0b830df15b670, the current head changes only:docs/deployment/2026-07-02-buyer-deployment-integration-playbook.md;docs/deployment/clearfolio-buyer-connector.openapi.yaml; andAGENTS.md.The earlier authorization head's fuzz run
30976501953completed successfully. Exact-current-head checks were re-triggered after the documentation corrections and must complete before this evidence is considered current. The equivalent pre-rebuild implementation at38281f8ee758bd45ca5728fc0c6a3261a039538bpassedVerify administrator stackrun30973612097and fuzz run30973612098; those earlier runs are supporting provenance only.Merge gate
Keep this PR draft. After #165 merges, retarget/rebuild the same bounded change on protected
mainif necessary, then require exact-head CI, 100% production line/branch coverage, Security Scan, SAST, fuzzing, fresh automated review, independent approval, zero unresolved threads, and every repository protection before enabling merge.