Skip to content

fix(security): enforce production HMAC signing key readiness - #313

Open
seonghobae wants to merge 2 commits into
mainfrom
fix/production-tenant-claims-key-strength
Open

fix(security): enforce production HMAC signing key readiness#313
seonghobae wants to merge 2 commits into
mainfrom
fix/production-tenant-claims-key-strength

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Objective

Fail closed when production uses missing, ephemeral, undersized, purpose-reused, or misleadingly normalized HMAC signing material for tenant claims and artifact links.

Fresh exact state — 2026-08-10

  • exact source head: 610f081cc56cfcaa372d674a56f4b21c91123c8f;
  • exact protected main: 55d7ae8647208e301f282350f076eeddaba61d11 after protected merge of fix(security): harden audit pseudonymization and refresh Netty evidence #270;
  • clean reconciliation: two commits, two changed files, no inherited parent/source noise;
  • open, Draft at this metadata update, mergeable;
  • exact-head CI 31387412055: success;
  • exact-head Security Scan 31387411478: success;
  • exact-head SAST Semgrep 31387411422: success;
  • exact-head fuzz 31387412079: success;
  • no qualifying independent approval is inferred from automated checks, comments, statuses, or model output.

The former divergent branch and every predecessor run are historical. #270's mvn verify, zero-missed owned production coverage, strict public-Javadoc and privacy/security substrate are now protected-main behavior.

Test-first security evidence

This bounded slice establishes regressions for:

  • effective tenant-claims HMAC key must be nonblank and at least 16 UTF-8 bytes after the exact NUL-removal/strip() normalization used by TenantAccessService;
  • production rejects a configured tenant secret whose literal bytes would be silently changed by runtime normalization;
  • production requires explicit stable artifact-token signing material rather than the process-random development fallback;
  • artifact-token HMAC material must be at least 16 UTF-8 bytes;
  • effective tenant and artifact signing keys must be byte-distinct by purpose;
  • an explicitly null tenant secret follows the same controlled missing-secret failure rather than escaping the effective-key path.

Clean-base coverage RED → GREEN

Initial clean head 2e1dc916a0b4f5392439da147abf190a18cf3e3c executed 505 Maven tests with zero failures, errors, or skips, but exact CI 31387048868 failed the uncompromised JaCoCo gate: ProductionAuthReadinessConfig.java retained one missed line and one missed branch in the explicit-null normalization path.

Current head 610f081cc56cfcaa372d674a56f4b21c91123c8f adds the focused null-secret regression without changing production behavior or weakening coverage. Exact-head CI, Security Scan, SAST, and fuzz are all GREEN.

Claim boundary

The 16-byte floor is a minimum-strength guard, not proof of entropy, independent generation, KMS custody, rotation, or complete key-management compliance. NIST SP 800-224 remains draft guidance; final key-management authority and operational controls remain distinct. Issue #319 owns migration from direct environment/config secret authority to a provider-neutral credential registry and must not be conflated with this readiness slice. Issue #314 separately owns OIDC/JWT federation.

Scope

Only these files change:

  1. src/main/java/com/clearfolio/viewer/config/ProductionAuthReadinessConfig.java
  2. src/test/java/com/clearfolio/viewer/config/ProductionAuthReadinessConfigTest.java

The slice does not change tenant-claim payload/signature semantics, artifact-token payloads, HMAC algorithm, endpoint authorization, or secret transport.

Merge gate

Move to Ready for ordinary independent review. Merge only if this unchanged exact head continues to satisfy every live required check, zero valid unresolved findings, the counted write-authorized independent approval required by repository policy, and expected-head-safe protection. Do not treat this key-readiness slice as completion of issue #319's credential-source migration.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@seonghobae, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c45e89f9-a028-4073-b4a6-19a7bb57d521

📥 Commits

Reviewing files that changed from the base of the PR and between 55d7ae8 and 610f081.

📒 Files selected for processing (2)
  • src/main/java/com/clearfolio/viewer/config/ProductionAuthReadinessConfig.java
  • src/test/java/com/clearfolio/viewer/config/ProductionAuthReadinessConfigTest.java

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Please review exact current source head bcf9989eaebac435802425708cdc2a48f243d295 against live protected main f3cc09a9838f0f88c81a2ceae22138fab80a2edb. This is a bounded production-readiness change for clearfolio.tenant-claims.hmac-secret: 15 UTF-8 bytes must fail closed; exactly 16 bytes and the existing 17-byte fixture must start successfully. Verify byte-count semantics, fail-closed production-profile behavior, preservation of the missing-secret contract, test boundary coverage, public Javadocs, and that the standards wording does not claim entropy or compliant key generation from length alone. Exact-head CI 31345183533, Security Scan 31345183536, SAST Semgrep 31345183547, and fuzz 31345183539 are successful. Treat bot status as advisory and report only current-head actionable findings.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='bcf9989eaebac435802425708cdc2a48f243d295'
base='f3cc09a9838f0f88c81a2ceae22138fab80a2edb'

printf '%s\n' '== Exact commits =='
git show -s --format='base %H%n%P%n%an <%ae>%n%s' "$base"
git show -s --format='head %H%n%P%n%an <%ae>%n%s' "$head"

printf '%s\n' '== Changed files and diff =='
git diff --name-status "$base" "$head"
git diff --find-renames --find-copies --check "$base" "$head"
git diff --find-renames --find-copies --unified=80 "$base" "$head"

printf '%s\n' '== Candidate source and test files =='
fd -t f -i 'ProductionAuthReadinessConfig' . || true

printf '%s\n' '== Candidate file AST outlines =='
fd -t f -i 'ProductionAuthReadinessConfig' . -x ast-grep outline {} --items all --view expanded || true

printf '%s\n' '== Tenant-claims configuration, guards, and test references =='
rg -n -i -C 8 \
  '(clearfolio\.tenant-claims\.hmac-secret|tenant.?claims|hmac.?secret|ProductionAuthReadinessConfig)' \
  --glob '!**/target/**' --glob '!**/.git/**' .

printf '%s\n' '== Production profile configuration files =='
fd -t f -i 'application*' . -x sh -c '
  case "$1" in
    *.yml|*.yaml|*.properties)
      if rg -q -i "(spring\.config\.activate\.on-profile|spring\.profiles|production|tenant-claims|hmac-secret)" "$1"; then
        echo "--- $1"
        cat -n "$1"
      fi
      ;;
  esac
' sh {} || true

Length of output: 143632


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/clearfolio'
pr='313'
head='bcf9989eaebac435802425708cdc2a48f243d295'
base='f3cc09a9838f0f88c81a2ceae22138fab80a2edb'

printf '%s\n' '== Commit ancestry and changed paths =='
git merge-base --is-ancestor "$base" "$head" && echo 'base is an ancestor of head'
git diff --name-only "$base" "$head"
git diff --check "$base" "$head"

printf '%s\n' '== Fixture UTF-8 byte counts =='
python3 - <<'PY'
for value in ("short-hmac-key!", "0123456789abcdef", "production-secret"):
    print(f"{value!r}: chars={len(value)}, utf8_bytes={len(value.encode('utf-8'))}")
PY

printf '%s\n' '== Exact PR metadata, reviews, and commits =='
gh pr view "$pr" --repo "$repo" --json \
  number,state,isDraft,mergeable,headRefOid,baseRefOid,reviewDecision,reviews,statusCheckRollup,commits \
  --jq '{
    number, state, isDraft, mergeable, headRefOid, baseRefOid, reviewDecision,
    reviews: [.reviews[] | {author: .author.login, state, commit: .commit.oid}],
    checks: [.statusCheckRollup[] | {name, status, conclusion}],
    commits: [.commits[] | {oid: .oid, messageHeadline: .messageHeadline}]
  }'

printf '%s\n' '== Pull-request review threads at the requested head =='
gh api graphql \
  -F owner='ContextualWisdomLab' \
  -F name='clearfolio' \
  -F number="$pr" \
  -f query='
query($owner: String!, $name: String!, $number: Int!) {
  repository(owner: $owner, name: $name) {
    pullRequest(number: $number) {
      reviewThreads(first: 100) {
        nodes {
          isResolved
          comments(first: 20) {
            nodes {
              author { login }
              commit { oid }
              body
              path
              line
            }
          }
        }
      }
    }
  }
}' \
  --jq '.data.repository.pullRequest.reviewThreads.nodes
    | map(select(.isResolved == false)
      | {comments: [.comments.nodes[] | select(.commit.oid == "bcf9989eaebac435802425708cdc2a48f243d295")
          | {author: .author.login, path, line, body}]})'

printf '%s\n' '== Build and JavaDoc configuration =='
fd -t f -g 'pom.xml' -g 'build.gradle' -g 'build.gradle.kts' . -x sh -c '
  echo "--- $1"
  rg -n -i -C 4 "(maven-javadoc|javadoc|doclint|maven-checkstyle|spotless|maven-enforcer)" "$1" || true
' sh {}

Length of output: 6086


@seonghobae I found one actionable test-coverage gap.

  • P2 — Add a non-ASCII UTF-8 boundary fixture in src/test/java/com/clearfolio/viewer/config/ProductionAuthReadinessConfigTest.java, Line 27. The 15-, 16-, and 17-byte fixtures are all ASCII. Their character count equals their UTF-8 byte count. A future regression from getBytes(StandardCharsets.UTF_8).length to String.length() would still pass all current tests. Add a value with 16 UTF-8 bytes but fewer than 16 Java characters, such as eight two-byte characters. Assert that production startup succeeds. This test proves the stated byte-count contract.

I verified the exact requested head and base. The implementation uses UTF-8 bytes in ProductionAuthReadinessConfig.java, Line 37. The production-only profile guard remains in place. The missing or blank secret error contract remains unchanged. The public Javadoc states that length does not establish entropy or approved key generation. No other current-head actionable finding was identified.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae seonghobae changed the title fix(security): enforce production tenant-claims HMAC key length fix(security): enforce production HMAC signing key readiness Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Please review exact current source head 4724bf33637bec6385551280d59b0e14bcb296ab against live protected main f3cc09a9838f0f88c81a2ceae22138fab80a2edb. Verify the bounded production-readiness contract for both tenant-claims and artifact-token HMAC signing material: missing/blank rejection, UTF-8 byte-length floor, explicit stable artifact-token key in production instead of the process-random development fallback, exact 16-byte acceptance boundaries, unchanged token/claim payload and HMAC algorithm semantics, and no overlap with the active #270/#268 security/lifecycle work. Exact-head CI 31346286160 is successful with Maven job 93328727596 executing 439 tests with zero failures/errors/skips; Security Scan 31346286168, SAST Semgrep 31346286175, and fuzz 31346286131 are successful. Treat predecessor evidence as historical. Report only current actionable findings; automated review remains advisory and is not counted as qualifying independent approval.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='4724bf33637bec6385551280d59b0e14bcb296ab'
base='f3cc09a9838f0f88c81a2ceae22138fab80a2edb'
repo='ContextualWisdomLab/clearfolio'

printf '%s\n' '== Exact commits and ancestry =='
git show -s --format='base: %H%nparents: %P%nsubject: %s' "$base"
git show -s --format='head: %H%nparents: %P%nsubject: %s' "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'base is an ancestor of head'

printf '%s\n' '== Changed paths and diff =='
git diff --name-status "$base" "$head"
git diff --check "$base" "$head"
git diff --find-renames --unified=100 "$base" "$head"

printf '%s\n' '== Candidate source and test files =='
fd -t f -i 'ProductionAuthReadinessConfig' . -E target
fd -t f -i 'ArtifactLinkService' . -E target

printf '%s\n' '== Java outlines =='
fd -t f -i 'ProductionAuthReadinessConfig' . -E target -x ast-grep outline {} --items all --view expanded
fd -t f -i 'ArtifactLinkService' . -E target -x ast-grep outline {} --items all --view expanded

printf '%s\n' '== Relevant configuration and signing references =='
rg -n -i -C 8 \
  '(clearfolio\.tenant-claims\.hmac-secret|clearfolio\.artifact-token\.secret|ProductionAuthReadinessConfig|ArtifactLinkService|HmacSHA|random.*key|SecureRandom)' \
  --glob '!**/target/**' --glob '!**/.git/**' .

printf '%s\n' '== Exact focused files at requested head =='
for path in $(git diff --name-only "$base" "$head"); do
  case "$path" in
    *.java)
      echo "--- $path"
      git show "$head:$path" | cat -n
      ;;
  esac
done

printf '%s\n' '== Exact PR and related PR changed paths =='
for pr in 313 270 268; do
  echo "--- PR #$pr"
  gh pr view "$pr" --repo "$repo" --json number,state,isDraft,headRefOid,baseRefOid,files,statusCheckRollup \
    --jq '{number,state,isDraft,headRefOid,baseRefOid,files:[.files[].path],checks:[.statusCheckRollup[]|{name,status,conclusion}]}' || true
done

Length of output: 233156


@seonghobae I found one actionable test-coverage gap.

  • P2 — Add non-ASCII UTF-8 acceptance tests for both secrets in src/test/java/com/clearfolio/viewer/config/ProductionAuthReadinessConfigTest.java, Line 52 and Line 61. All boundary fixtures are ASCII. Therefore, their Java character count equals their UTF-8 byte count. The tests do not prove the documented UTF-8 byte-length contract. Add production startup tests with a secret that has exactly 16 UTF-8 bytes but fewer than 16 Java characters, such as eight two-byte characters. Test it once as clearfolio.tenant-claims.hmac-secret and once as clearfolio.artifact-token.secret. A future replacement of either getBytes(StandardCharsets.UTF_8).length check with String.length() would otherwise pass the current tests.

I verified the requested source head and protected base. The production-only guard rejects missing or blank values and rejects secrets under 16 UTF-8 bytes. It blocks the production use of the process-local artifact-token fallback. The diff does not change the claim payload, artifact-token payload, or HmacSHA256 algorithm. The public Javadocs correctly state that key length alone does not prove entropy or approved key generation. The changed paths do not overlap with the active #270 or #268 changed paths. Automated checks remain advisory and do not constitute independent approval.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Please review exact current source head c1455ad0f69ba0ff1d3bb890e83e0dba5b9ad9d2 against live protected main f3cc09a9838f0f88c81a2ceae22138fab80a2edb. Verify the bounded production HMAC readiness contract: missing/blank rejection, 16-UTF-8-byte minimum for both tenant-claims and artifact-token signing material, explicit stable artifact-token key in production instead of the process-random development fallback, exact boundary acceptance, and rejection of byte-identical key reuse across tenant-claim and artifact-delivery purposes without claiming that inequality proves entropy/KMS provenance. Exact-head CI 31346737404 is successful with Maven job 93329944372 executing 440 tests with zero failures/errors/skips; Security Scan 31346737410, SAST Semgrep 31346737433, and fuzz 31346737419 are successful. Treat all predecessor heads and earlier review requests as stale. Report only current actionable findings; automated review remains advisory and is not qualifying independent approval.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/clearfolio'
pr='313'
head='c1455ad0f69ba0ff1d3bb890e83e0dba5b9ad9d2'
base='f3cc09a9838f0f88c81a2ceae22138fab80a2edb'

printf '%s\n' '== Exact commits and ancestry =='
git show -s --format='base %H%nparents %P%nsubject %s' "$base"
git show -s --format='head %H%nparents %P%nsubject %s' "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'base-is-ancestor=yes'

printf '%s\n' '== Changed paths and whitespace check =='
git diff --name-status "$base" "$head"
git diff --check "$base" "$head"

printf '%s\n' '== Changed Java outlines =='
git diff --name-only "$base" "$head" -- '*.java' | while IFS= read -r path; do
  printf '\n--- %s\n' "$path"
  ast-grep outline "$path" --items all --view expanded
done

printf '%s\n' '== Exact changed Java source =='
git diff --name-only "$base" "$head" -- '*.java' | while IFS= read -r path; do
  printf '\n--- %s\n' "$path"
  git show "$head:$path" | cat -n
done

printf '%s\n' '== Relevant implementation and call sites =='
rg -n -C 8 \
  '(ProductionAuthReadinessConfig|ArtifactLinkService|clearfolio\.tenant-claims\.hmac-secret|clearfolio\.artifact-token\.secret|HmacSHA|SecureRandom|MessageDigest\.isEqual|getBytes\(StandardCharsets\.UTF_8\))' \
  --glob '!**/target/**' --glob '!**/.git/**' .

printf '%s\n' '== Relevant file outlines =='
fd -t f -E target -E .git \
  'ProductionAuthReadinessConfig\.java|ProductionAuthReadinessConfigTest\.java|ArtifactLinkService\.java' . \
  -x ast-grep outline {} --items all --view expanded

printf '%s\n' '== PR state, checks, and changed-path overlap =='
gh pr view "$pr" --repo "$repo" \
  --json state,isDraft,mergeable,headRefOid,baseRefOid,reviewDecision,statusCheckRollup \
  --jq '{state,isDraft,mergeable,headRefOid,baseRefOid,reviewDecision,checks:[.statusCheckRollup[]|{name,status,conclusion}]}'

for related_pr in 270 268; do
  printf '\n--- PR #%s paths\n' "$related_pr"
  gh pr view "$related_pr" --repo "$repo" --json files \
    --jq '.files[].path' || true
done

printf '%s\n' '== Unresolved review threads on exact requested head =='
gh api graphql \
  -F owner='ContextualWisdomLab' -F name='clearfolio' -F number="$pr" \
  -f query='
query($owner: String!, $name: String!, $number: Int!) {
  repository(owner: $owner, name: $name) {
    pullRequest(number: $number) {
      reviewThreads(first: 100) {
        nodes {
          isResolved
          comments(first: 20) {
            nodes { author { login } commit { oid } body path line }
          }
        }
      }
    }
  }
}' \
  --jq --arg head "$head" '
    .data.repository.pullRequest.reviewThreads.nodes
    | map(select(.isResolved == false)
      | .comments.nodes[]
      | select(.commit.oid == $head)
      | {author: .author.login, path, line, body})'

Length of output: 203491


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/clearfolio'
pr='313'
head='c1455ad0f69ba0ff1d3bb890e83e0dba5b9ad9d2'
base='f3cc09a9838f0f88c81a2ceae22138fab80a2edb'

printf '%s\n' '== Exact changed paths =='
git diff --name-status "$base" "$head"
git diff --check "$base" "$head"

printf '%s\n' '== Focused test source at exact head =='
git show "$head:src/test/java/com/clearfolio/viewer/config/ProductionAuthReadinessConfigTest.java" | cat -n

printf '%s\n' '== Exact-head unresolved review threads =='
gh api graphql \
  -F owner='ContextualWisdomLab' \
  -F name='clearfolio' \
  -F number="$pr" \
  -f query='
query($owner: String!, $name: String!, $number: Int!) {
  repository(owner: $owner, name: $name) {
    pullRequest(number: $number) {
      reviewThreads(first: 100) {
        nodes {
          isResolved
          comments(first: 20) {
            nodes {
              author { login }
              commit { oid }
              body
              path
              line
            }
          }
        }
      }
    }
  }
}' \
  | jq --arg head "$head" '
      [.data.repository.pullRequest.reviewThreads.nodes[]
       | select(.isResolved == false)
       | .comments.nodes[]
       | select(.commit.oid == $head)
       | {author: .author.login, path, line, body}]'

printf '%s\n' '== UTF-8 fixture counts =='
python3 - <<'PY'
values = {
    "tenant_short": "short-hmac-key!",
    "tenant_minimum": "0123456789abcdef",
    "artifact_short": "short-art-key!",
    "artifact_minimum": "0123456789abcdef",
    "non_ascii_example": "éééééééé",
}
for name, value in values.items():
    print(f"{name}: code_points={len(value)}, utf8_bytes={len(value.encode('utf-8'))}")
PY

Length of output: 7246


@seonghobae I found two current actionable test-coverage gaps.

  • P2 — Add non-ASCII UTF-8 boundary coverage for both secrets. ProductionAuthReadinessConfigTest.java, Line 64 and Line 73 use only ASCII fixtures. Therefore, the Java character count equals the UTF-8 byte count. The tests would not detect a regression from getBytes(StandardCharsets.UTF_8).length to String.length(). Add a production-startup test that uses distinct 16-byte non-ASCII values for both secrets. For example, each value can contain eight two-byte characters.

  • P2 — Add whitespace-only secret rejection tests. ProductionAuthReadinessConfigTest.java, Line 14 and Line 32 test missing values but not blank values. The implementation correctly uses StringUtils.hasText, but the tests do not protect this requirement. Add production-startup failure tests for whitespace-only clearfolio.tenant-claims.hmac-secret and clearfolio.artifact-token.secret. Use at least 16 whitespace characters so a future null-only presence check cannot be masked by the length gate.

I verified the exact requested head and base. The diff changes only ProductionAuthReadinessConfig.java and its focused test. The implementation rejects missing and blank values, uses UTF-8 byte lengths for both minimum checks, requires a configured artifact-token secret in production, and rejects byte-identical key material with MessageDigest.isEqual.

The artifact-token development fallback remains outside the production profile guard. The claim payload, artifact-token payload, and HmacSHA256 algorithm are unchanged. The public Javadocs state that key length and distinct values do not prove entropy, independent generation, custody, rotation, or KMS provenance. The changed paths do not overlap with #270 or #268. The exact-head unresolved-thread query returned no threads. Automated checks remain advisory and are not independent approval.

You are interacting with an AI system.

Copy link
Copy Markdown
Collaborator Author

@opencode-agent @cwl-noema-review

Please review exact current source head d026524bf9d97bebdb420a09616c98a87601b30a against current protected main 83ec6f7fe2b04bdcd28bf98ec350e41e55730a18. Focus on whether production readiness validates the effective tenant HMAC bytes actually used by TenantAccessService, stable artifact-token signing across restart/replicas, purpose separation, fail-closed ambiguity handling, and whether the 16-byte minimum is described without overstating entropy/KMS/compliance. NIST SP 800-224 remains an Initial Public Draft in the current NIST publication catalog; treat draft guidance separately from final FIPS/SP 800-57 authority. Report only current-head source-backed findings. Advisory model review is not qualifying independent approval.

@seonghobae
seonghobae force-pushed the fix/production-tenant-claims-key-strength branch from d026524 to 2e1dc91 Compare August 10, 2026 12:13
@seonghobae
seonghobae marked this pull request as ready for review August 10, 2026 12:20
@seonghobae
seonghobae enabled auto-merge (squash) August 10, 2026 12:21

Copy link
Copy Markdown
Collaborator Author

@opencode-agent @cwl-noema-review Please independently review exact current head 610f081cc56cfcaa372d674a56f4b21c91123c8f against protected main 55d7ae8647208e301f282350f076eeddaba61d11. Exact-head CI 31387412055, Security Scan 31387411478, SAST 31387411422, and fuzz 31387412079 are successful. Verify production rejects missing/null, undersized, normalized/ambiguous, unstable artifact-token, and purpose-reused HMAC material while preserving the explicit boundary that key readiness is not issue #319 credential-registry migration. Review the clean-base coverage RED→GREEN and ensure the test did not weaken production or the 100% gate. Advisory review only; do not mutate, count as human approval, merge, or weaken gates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant