Skip to content

feat(security): say why a CSP derivation produced nothing - #3482

Merged
kojiwakayama merged 2 commits into
mainfrom
feat/derived-csp-observability
Aug 8, 2026
Merged

feat(security): say why a CSP derivation produced nothing#3482
kojiwakayama merged 2 commits into
mainfrom
feat/derived-csp-observability

Conversation

@kojiwakayama

@kojiwakayama kojiwakayama commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

v0.1.1216 is live in production and derived origins still do not appear. I verified after the rollout: vf-csp-probe.production.veryfront.com serves the bare floor, while vf-csp-probe.preview.veryfront.com serves both derived origins from the same release and the same source.

#3474 was a real bug but not this one. It stopped an empty read being cached forever, and the retry it introduced is what proves the point: every request now re-reads the source and still derives nothing. The empty result is persistent, not the cold-start race I diagnosed. I said that fix would close this out; it did not, and the promotion notes on veryfront-server#304 are wrong about that.

Two further hypotheses, both falsified:

  • Release files carry no content in production — no, the API returns full content for both the release and the branch listing.
  • The file-list warmup is failing — no, there are no File list warmup failed warnings, and Refreshed source snapshot shows the adapter reading source for this project.

Which leaves me unable to diagnose it from outside, because every path out of the derivation returns an empty result with debug-level logs, and production runs above debug. A derivation that never works looks exactly like a project that references no external origins. That silence is the reason this shipped broken, survived a promotion, and then survived a fix aimed at the wrong cause.

So this makes each outcome say which one it was:

  • adapter cannot run in a tenant context
  • adapter exposes no source listing
  • the read threw (with the error)
  • the read returned nothing
  • read N files (M with content), derived K origins

The last one carries the file count deliberately: read 40 files, derived 0 origins is the signature of a broken extractor, and without the count it reads identically to a correct derivation of a project that uses no external origins.

Logged once per content version — which is precisely what the cache key already is — so it cannot grow with traffic.

This is not a fix. It is the instrument I should have added before claiming a diagnosis, and it will name the cause on the next release.

Lint, typecheck, fmt and the full unit suite green by exit code.

Summary by CodeRabbit

  • Bug Fixes

    • Improved diagnostics for CSP origin derivation issues.
    • Added clear warnings when source data is empty or unavailable.
    • Runtime responses continue gracefully without derived CSP when derivation fails.
  • Logging

    • Successful CSP derivations now consistently report relevant project, content, file, and origin details.
    • Errors include clearer context to support troubleshooting.

v0.1.1216 shipped the negative-caching fix and derived origins still do not
appear in production. The probe project serves the bare floor while its preview
serves both derived origins from the same release and the same source.

That fix was real -- an empty read was being cached forever -- but it was not
the cause, and the retry it introduced proves it: every request now re-reads
and still derives nothing, so the empty result is persistent rather than a
cold-start race. Which leaves the actual cause somewhere between the adapter
and the extractor, and no way to tell from outside, because every path out of
this code returns an empty derivation with debug-level logs. A derivation that
never works is indistinguishable from a project that references no external
origins.

So each outcome now says which one it was: the adapter cannot run in a tenant
context, it exposes no source listing, the read threw, the read returned
nothing, or it read N files and derived M origins. The success line carries the
file count because "read 40 files, derived 0 origins" is the shape of a broken
extractor and reads identically to a correct one without it.

Logged once per content version, which is what the cache key already is, so
this cannot grow with traffic.
@kojiwakayama
kojiwakayama requested a review from kwakayama as a code owner August 8, 2026 19:31
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d7f8d561-1883-40d0-af30-daceb1725f4b

📥 Commits

Reviewing files that changed from the base of the PR and between 2c7ecbc and 5cee7e9.

📒 Files selected for processing (2)
  • src/security/http/derived-csp-cache.test.ts
  • src/security/http/derived-csp-cache.ts
📝 Walkthrough

Walkthrough

CSP origin derivation now emits structured warning and info logs for source-read failures, empty sources, unavailable runtime context, and derivation errors. Successful derivations report file and origin counts. Non-fatal fallback behavior remains unchanged.

Changes

CSP derivation observability

Layer / File(s) Summary
Derived CSP cache logging
src/security/http/derived-csp-cache.ts
Source-read failures and empty reads now use warnings. Successful derivations now report file and derived-origin counts at info level.
Runtime derivation logging
src/server/runtime-handler/project-runtime-context.ts
Unavailable adapter context, missing source listing, and caught derivation errors now include warning or error details. Fallback responses remain unchanged.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: kwakayama

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding reasons for empty CSP derivations through improved logging.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/derived-csp-observability

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c7ecbca5d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/security/http/derived-csp-cache.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@src/security/http/derived-csp-cache.ts`:
- Around line 107-113: Add a bounded per-key warning guard around the
logger.warn calls in getDerivedCspOrigins so repeated failures or empty reads
for the same lookup key do not emit warnings on every request. Preserve clearing
inFlight and retrying subsequent reads, and add a test that repeatedly calls the
same key and verifies warning emission is limited.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 212b9f19-55ec-4b1d-b880-920048c65088

📥 Commits

Reviewing files that changed from the base of the PR and between ee9df12 and 2c7ecbc.

📒 Files selected for processing (2)
  • src/security/http/derived-csp-cache.ts
  • src/server/runtime-handler/project-runtime-context.ts

Comment thread src/security/http/derived-csp-cache.ts Outdated
…quest

The two failure paths deliberately do not cache, so the read is retried on
every request. The diagnostic followed it, which would emit a warning per
request per pod for as long as a failure lasted -- the log flooding the report
endpoint's own ceiling exists to prevent, and the opposite of what I claimed in
this PR's description.

The warning is now gated on a bounded per-content-version guard, so the retry
is preserved and the signal stays one line per release. The guard is exported
and tested directly rather than through log interception, which the component
logger makes impossible.
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 8, 2026
Merged via the queue into main with commit 4e2901a Aug 8, 2026
31 checks passed
@kojiwakayama
kojiwakayama deleted the feat/derived-csp-observability branch August 8, 2026 20:21
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