Skip to content

fix: require service auth for Ledger/Contextual tools and harden error handling#39

Merged
chitcommit merged 4 commits intomainfrom
fix/ledger-auth-and-test-coverage
Feb 26, 2026
Merged

fix: require service auth for Ledger/Contextual tools and harden error handling#39
chitcommit merged 4 commits intomainfrom
fix/ledger-auth-and-test-coverage

Conversation

@chitcommit
Copy link
Copy Markdown
Contributor

@chitcommit chitcommit commented Feb 26, 2026

Summary

  • Add requireServiceAuth to all 16 ChittyLedger and 2 ChittyContextual tool handlers, preventing unauthenticated requests to downstream services
  • Extract parseJsonBody helper to deduplicate 13 identical try/catch JSON parsing blocks
  • Add checkFetchError guards to 5 fact governance POST handlers that previously had no response.ok check
  • Harden requireServiceAuth to catch thrown exceptions from getServiceToken (1Password timeouts, etc.)
  • Fix evidence JSON parse in chitty_fact_mint: block minting on invalid JSON instead of silently anchoring null hash
  • Fix PDF export path: use parseJsonBody instead of unguarded factResp.json()
  • Correct CHITTY.md frontmatter type from summary to architecture
  • 177/177 tests pass (up from 160)

Test plan

  • All 177 tests pass (npm test)
  • 12 auth failure isolation tests verify no fetch when token missing (9 original + 3 new)
  • getServiceToken throw test confirms structured error instead of generic catch
  • Non-JSON response test confirms isError: true on HTML from ledger
  • Seal POST 500 test confirms PROOF_Q.send never called on upstream failure
  • Seal without PROOF_Q test confirms proof_queue_warning in response
  • Evidence invalid JSON test confirms fact minting blocked

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced error handling for service authentication failures and API response parsing
    • Standardized error messages across tool operations for clearer failure reporting
  • Documentation

    • Updated documentation structure and metadata classification
  • Tests

    • Expanded test coverage for authentication scenarios, token failures, and error responses
    • Added validation for proper error handling in API communication

chitcommit and others added 3 commits February 25, 2026 23:29
…error handling

Add requireServiceAuth gating to all 14 Ledger and 2 Contextual tool
handlers so no unauthenticated requests reach downstream services.
Add checkFetchError to 5 fact governance POST handlers that previously
only caught non-JSON errors, silently passing 4xx/5xx JSON error bodies
as success. Fix the last remaining isError-missing catch block in
chitty_fact_export JSON branch. Add 9 new tests covering auth failure
isolation, header propagation, and error response format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… coverage

- Extract parseJsonBody helper, eliminating 13 duplicated try/catch blocks (-133 lines)
- Migrate 4 inline !response.ok handlers to shared checkFetchError
- Add try-catch in requireServiceAuth for getServiceToken exceptions
- Fix evidence JSON parse in fact_mint: block minting on invalid JSON instead of silent null hash
- Fix PDF export path: use parseJsonBody instead of unguarded factResp.json()
- Simplify redundant else-if(!env.PROOF_Q) to else
- Consolidate 9 auth failure tests into it.each (+3 new: validate, dispute, export)
- Add tests: getServiceToken throw, non-JSON response, seal+PROOF_Q interaction, evidence JSON parse

177/177 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 26, 2026 08:18
@cloudflare-workers-and-pages
Copy link
Copy Markdown
Contributor

cloudflare-workers-and-pages Bot commented Feb 26, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
chittyconnect 82fc75b Feb 26 2026, 11:41 AM

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

Warning

Rate limit exceeded

@chitcommit has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 25 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 438363a and 82fc75b.

📒 Files selected for processing (2)
  • src/mcp/tool-dispatcher.js
  • tests/mcp/tool-dispatcher.test.js
📝 Walkthrough

Walkthrough

Updates MCP tool dispatcher to standardize JSON parsing error handling via new parseJsonBody function, enhances service authentication with explicit error catching and logging, and adds comprehensive test coverage for authentication failures, JSON parse errors, and ledger response handling.

Changes

Cohort / File(s) Summary
Documentation Metadata
CHITTY.md
Updated front-matter URI from chittycanon://docs/ops/summary/chittyconnect to chittycanon://docs/ops/architecture/chittyconnect and type from summary to architecture.
Error Handling & Service Authentication
src/mcp/tool-dispatcher.js
Added parseJsonBody() helper to standardize JSON parsing with MCP-formatted error responses; enhanced requireServiceAuth() to catch and log token retrieval errors; unified error handling across ledger, dashboard, evidence, and facts tool branches; improved failure paths for pre-flight checks with consistent MCP error formatting; propagated service-authenticated headers (ledgerAuth) to appropriate endpoints.
Test Coverage
tests/mcp/tool-dispatcher.test.js
Added per-test service token mocking and Authorization header assertion for multiple tool dispatch scenarios; introduced isolated tests for auth failures (null token, thrown errors); added tests for non-JSON responses and parse failures; extended coverage for PROOF_Q edge cases and ledger API failures with updated error message validation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ToolDispatcher as Tool Dispatcher
    participant ServiceAuth as Service Auth
    participant APIServer as API Server
    
    Client->>ToolDispatcher: dispatchToolCall(toolName, args)
    ToolDispatcher->>ServiceAuth: requireServiceAuth()
    
    alt Auth Token Available
        ServiceAuth-->>ToolDispatcher: serviceToken
    else Auth Error
        ServiceAuth->>ServiceAuth: catch & log error
        ServiceAuth-->>ToolDispatcher: MCP error response
        ToolDispatcher-->>Client: authentication failure
    end
    
    alt Token Retrieved Successfully
        ToolDispatcher->>APIServer: fetch(endpoint, {headers: Authorization: Bearer svc-token})
        APIServer-->>ToolDispatcher: HTTP response
        
        alt Response OK
            ToolDispatcher->>ToolDispatcher: parseJsonBody(response)
            alt JSON Parse Success
                ToolDispatcher-->>Client: structured data
            else JSON Parse Failure
                ToolDispatcher-->>Client: MCP error (parse failed)
            end
        else Response Error
            ToolDispatcher-->>Client: MCP error (HTTP error)
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • chittyos/chittyconnect#36 – Modifies ledger-related tool handling with service Authorization headers and error parsing patterns aligned with this PR's standardization approach.
  • chittyos/chittyconnect#33 – Introduces the shared tool dispatcher and routing infrastructure that serves as the foundation for this PR's error handling and authentication enhancements.

Suggested labels

security-approved, access-reviewed, docs-approved

Poem

🐰 Errors now flow through channels clear,
With tokens checked and JSON near,
No silent fails shall pass us by,
Each fault's a message, crystal dry!
Auth secure, responses bright—
The dispatcher works just right!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is missing several required sections from the template: Security & Access checklist, Docs checklist, and Validation checklist are not addressed. Complete the description template by adding the Security & Access, Docs, and Validation sections with appropriate checkboxes and confirmations.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding service authentication requirements and improving error handling for Ledger/Contextual tools.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/ledger-auth-and-test-coverage

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/mcp/tool-dispatcher.js (1)

1-10: ⚠️ Potential issue | 🟡 Minor

Address Prettier formatting issues flagged by CI.

The pipeline detected formatting inconsistencies. Run npx prettier --write src/mcp/tool-dispatcher.js to fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/mcp/tool-dispatcher.js` around lines 1 - 10, The file mcp/tool-dispatcher
has Prettier formatting inconsistencies; run the formatter or apply Prettier
rules to normalize whitespace and line breaks (e.g., run npx prettier --write on
the module containing the Shared MCP Tool Dispatcher and the import of
getServiceToken) so the file matches the project's Prettier config and CI will
pass.
🧹 Nitpick comments (1)
src/mcp/tool-dispatcher.js (1)

885-893: Consider extending parseJsonBody to Finance tools for consistency.

Finance handlers (lines 893, 903, 916, 929, 943, 962, 975, 988, 1003) still use direct .json() calls without the parseJsonBody error handling added to Ledger/Contextual tools. Non-JSON responses would throw unhandled exceptions here.

This is outside the stated PR scope but worth addressing for consistency in a follow-up.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/mcp/tool-dispatcher.js` around lines 885 - 893, In the Finance branches
(e.g., the handler when name === "chitty_finance_entities") replace direct
response.json() calls with the existing parseJsonBody helper to avoid uncaught
exceptions on non-JSON responses: after checkFetchError(...) call, call
parseJsonBody(response, "ChittyFinance") and handle its return the same way
Ledger/Contextual handlers do (check for an error return and return it if
present, otherwise assign the parsed result to result). Use the same helper
names present in this file (requireServiceAuth, checkFetchError, parseJsonBody)
so all Finance tool handlers follow the same error-safe JSON parsing pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/mcp/tool-dispatcher.js`:
- Around line 1-10: The file mcp/tool-dispatcher has Prettier formatting
inconsistencies; run the formatter or apply Prettier rules to normalize
whitespace and line breaks (e.g., run npx prettier --write on the module
containing the Shared MCP Tool Dispatcher and the import of getServiceToken) so
the file matches the project's Prettier config and CI will pass.

---

Nitpick comments:
In `@src/mcp/tool-dispatcher.js`:
- Around line 885-893: In the Finance branches (e.g., the handler when name ===
"chitty_finance_entities") replace direct response.json() calls with the
existing parseJsonBody helper to avoid uncaught exceptions on non-JSON
responses: after checkFetchError(...) call, call parseJsonBody(response,
"ChittyFinance") and handle its return the same way Ledger/Contextual handlers
do (check for an error return and return it if present, otherwise assign the
parsed result to result). Use the same helper names present in this file
(requireServiceAuth, checkFetchError, parseJsonBody) so all Finance tool
handlers follow the same error-safe JSON parsing pattern.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b554072 and 438363a.

📒 Files selected for processing (3)
  • CHITTY.md
  • src/mcp/tool-dispatcher.js
  • tests/mcp/tool-dispatcher.test.js

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens MCP tool handlers that proxy to downstream Chitty services by enforcing service-token auth and standardizing error/JSON handling, plus a small docs frontmatter correction.

Changes:

  • Require service-auth (requireServiceAuth) for ChittyLedger and ChittyContextual tool handlers and add tests ensuring no downstream fetch occurs when token retrieval fails.
  • Deduplicate response parsing via parseJsonBody and add consistent checkFetchError guarding for non-OK upstream responses.
  • Update CHITTY.md frontmatter classification (summaryarchitecture) and URI path.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/mcp/tool-dispatcher.js Adds requireServiceAuth enforcement and centralized fetch error + JSON parsing helpers across Ledger/Contextual tools.
tests/mcp/tool-dispatcher.test.js Updates expectations for auth headers/errors and adds isolation tests for missing/throwing service-token scenarios.
CHITTY.md Corrects canon frontmatter uri path segment and type.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +77 to +82
return {
error: {
content: [
{
type: "text",
text: `Authentication failed: Unable to retrieve service token for ${displayName} (${err.message})`,
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

In requireServiceAuth, the catch block interpolates err.message. If getServiceToken rejects with a non-Error (or null/undefined), accessing .message can itself throw and bypass the intended structured auth error. Consider normalizing the message (e.g., err instanceof Error ? err.message : String(err)) before building the response text.

Suggested change
return {
error: {
content: [
{
type: "text",
text: `Authentication failed: Unable to retrieve service token for ${displayName} (${err.message})`,
const safeMessage = err instanceof Error ? err.message : String(err);
return {
error: {
content: [
{
type: "text",
text: `Authentication failed: Unable to retrieve service token for ${displayName} (${safeMessage})`,

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +45
const text = await response.text();
try {
return { parsed: JSON.parse(text), error: null };
} catch {
return {
parsed: null,
error: {
content: [
{
type: "text",
text: `${label} returned non-JSON (${response.status}): ${text.slice(0, 200)}`,
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

parseJsonBody does const text = await response.text(); outside the try/catch. If response.text() rejects (stream/body read error), it will throw up to the outer dispatcher catch and return the generic Error executing ... instead of the intended structured MCP parse error. Wrap the response.text() read in the try/catch (or handle its rejection) so non-readable bodies still produce a consistent MCP error response.

Suggested change
const text = await response.text();
try {
return { parsed: JSON.parse(text), error: null };
} catch {
return {
parsed: null,
error: {
content: [
{
type: "text",
text: `${label} returned non-JSON (${response.status}): ${text.slice(0, 200)}`,
let text;
try {
text = await response.text();
return { parsed: JSON.parse(text), error: null };
} catch {
const preview =
typeof text === "string" && text.length > 0
? text.slice(0, 200)
: "Unable to read or parse response body";
return {
parsed: null,
error: {
content: [
{
type: "text",
text: `${label} returned non-JSON (${response.status}): ${preview}`,

Copilot uses AI. Check for mistakes.
Comment on lines 515 to 521
// Fetch fact with proof data
const factResp = await fetch(
`https://ledger.chitty.cc/api/facts/${encodeURIComponent(args.fact_id)}/export`,
{ headers: ledgerAuth },
);
if (!factResp.ok) {
return {
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

In the PDF export path, the non-OK handling for factResp treats any failure as “fact not found” (even for 5xx/timeouts). This can be misleading and makes diagnosing upstream issues harder. Consider reusing checkFetchError(factResp, "ChittyLedger") (or otherwise surfacing status/body) so non-404 errors are reported accurately.

Copilot uses AI. Check for mistakes.
Comment on lines +245 to 255
const evidenceCheck = await fetch(
`https://ledger.chitty.cc/api/evidence/${encodeURIComponent(args.evidence_id)}`,
{ headers: ledgerAuth },
);
if (!evidenceCheck.ok) {
return {
content: [
{
type: "text",
text: `ChittyLedger error (${response.status}): ${await response.text().catch(() => "")}`.slice(
0,
300,
),
text: `Fact minting blocked: evidence_id "${args.evidence_id}" not found in ChittyLedger (${evidenceCheck.status}). Evidence must be ingested through the pipeline before facts can be minted from it.`,
},
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

chitty_fact_mint pre-flight treats any !evidenceCheck.ok as “evidence_id not found” and instructs ingestion. For non-404 responses (e.g., 500/503), this will misreport upstream failures as missing evidence. Consider branching on evidenceCheck.status === 404 for the “not found” message, and otherwise returning a checkFetchError(evidenceCheck, "ChittyLedger")-style error.

Copilot uses AI. Check for mistakes.
@claude
Copy link
Copy Markdown

claude Bot commented Feb 26, 2026

Code Review

Overall this is a solid security hardening pass. The auth coverage gap on 16 ChittyLedger and 2 ChittyContextual tools was a real risk and these changes close it cleanly. 177/177 tests is a good signal.


What's well done

parseJsonBody extraction** — Replaces ~13 identical try/catch blocks with a single helper. The { parsed, error } return shape forces callers to check for errors explicitly before using the data.

requireServiceAuth hardening — Wrapping getServiceToken in a try-catch is the right move. Network timeouts or 1Password failures previously would have crashed the dispatcher with an unhandled rejection. The structured MCP error response is correct.

chitty_fact_mint evidence validation fix — The old await evidenceCheck.json().catch(() => null) pattern was a silent failure footgun: corrupted evidence data would produce a null hash that got anchored anyway. The new early return is the correct behavior.

Fact seal simplification — Removing the redundant response.ok && conditions after checkFetchError returns early is correct. The logic is easier to follow now.


Issues and suggestions

1. chitty_fact_seal — verify checkFetchError guard is still present

The diff removes response.ok conditions from the seal handler. Please confirm checkFetchError is still called and its result checked before the env.PROOF_Q branch. If the early-return guard was accidentally dropped, a 500 from the ledger service would silently enqueue a proof job for a failed write. Expected shape:

const fetchErr = await checkFetchError(response, "ChittyLedger seal");
if (fetchErr) return fetchErr;
// then PROOF_Q logic

2. Pre-flight evidence checks only validate HTTP status

In the batch ledger validate path, pre-flight evidence checks return { evId, ok: resp.ok, status: resp.status } without reading the body. A 200 response with corrupted JSON will pass the pre-flight check and fail later with a less informative error. Consider using parseJsonBody there too, or noting it as a known limitation.

3. Error message truncation at 200 chars may drop critical debug context

200 characters is tight for text.slice(0, 200). HTML error pages from Cloudflare proxy layers (502s, etc.) often put the relevant detail past that mark. Consider bumping to 500, or including the full body in a structured field while showing a truncated human-readable message.

4. Test gap: getServiceToken throw path for ChittyContextual tools

The PR mentions 12 auth failure isolation tests (9 original + 3 new). The new tests cover chitty_fact_seal PROOF_Q behavior and evidence invalid JSON, but it is not clear if the hardened requireServiceAuth exception path is tested for chitty_contextual_timeline and chitty_contextual_topics. A smoke test for at least one contextual tool would close the loop.

5. Minor: CHITTY.md URI type — confirm canon registry accepts architecture

The fix from type: summary to type: architecture looks correct. Worth confirming the canonical registry at chittycanon://core/services/canon accepts architecture as a valid type before re-registration.


Summary

Area Status
Auth coverage Closed — all 16+2 tools now gated
Exception safety Improved — requireServiceAuth no longer throws
Code duplication Reduced — parseJsonBody consolidates 13 blocks
Critical bug fix chitty_fact_mint no longer silently anchors null hashes
Tests 177/177 pass; coverage improved
Outstanding Verify checkFetchError call in seal handler; pre-flight JSON coverage; truncation limit

Approve pending confirmation of item #1 (seal handler guard). The rest are non-blocking suggestions.

🤖 Generated with Claude Code

…ion tests

- Extract checkAndParseJson combining checkFetchError + parseJsonBody (-21 lines)
- Consistent error label naming (ChittyLedger vs Ledger)
- Add 4 missing tools to auth isolation it.each (facts, contradictions, verify, statistics)
- Add PROOF_Q.send throw test (catch branch)
- Rename ledgerCases to serviceAuthCases for clarity
- Fix it.each description interpolation

182/182 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude Bot commented Feb 26, 2026

Code Review

This is a solid, well-scoped PR. The core security fix is important — 18 tool handlers were making unauthenticated requests to downstream services, and the approach to fixing this is clean and consistent. The refactoring work is a genuine improvement, not cleanup for its own sake.


Security

Good catch on the auth bypass. All 16 ChittyLedger and 2 ChittyContextual handlers now properly gate on service token availability before making any fetch. The it.each() auth isolation tests covering all 16+2 tools give strong confidence the fix is exhaustive. The hardening of requireServiceAuth to catch getServiceToken exceptions is practical and correct — a 1Password timeout shouldn't produce an uncaught exception that could mask the auth failure.

One thing worth a comment inline: in chitty_fact_seal, the ChittyTrust pre-flight check (RBAC) still uses authHeader (user auth), while the ChittyLedger seal call uses ledgerAuth (service token). This split is intentional and correct, but a brief comment would help future maintainers avoid accidentally 'normalizing' it.


Bug Fixes

chitty_fact_mint invalid JSON block is a real data integrity fix. The old .catch(() => null) pattern silently anchored a null hash, which is exactly the kind of quiet corruption that's hard to detect later. Blocking the mint on invalid evidence JSON is the right call.

PROOF_Q logic simplification (if (env.PROOF_Q) replacing if (response.ok && env.PROOF_Q)) is correct — by the time execution reaches that branch, checkAndParseJson has already returned early on any non-OK response. The logic is equivalent and cleaner.


Code Quality

Minor inconsistency in chitty_fact_mint: The evidence pre-flight check uses evidenceCheck.json() directly with a try/catch, which works, but is inconsistent with the parseJsonBody helper introduced in this same PR. Using parseJsonBody(evidenceCheck, 'ChittyLedger') there would make the pattern uniform and remove one bespoke try/catch.

Label inconsistency in chitty_fact_export PDF path:

const { parsed: factData, error: factParseErr } = await parseJsonBody(factResp, 'Ledger');

This uses 'Ledger' while every other call uses 'ChittyLedger'. The error message surfaced to Claude will say 'Ledger returned non-JSON...' instead of 'ChittyLedger returned non-JSON...'. Minor but easy to fix.


Breaking Change (intentional, worth noting)

Several tools changed their error response format:

  • Before: Returned a 'success' response with an error field in the JSON body: { "error": "Ledger returned (422): ..." }
  • After: Returns a proper MCP error result with isError: true

This is correct for MCP compliance. Any callers outside this codebase that were checking result.error on these tools will need updating. Worth a note in the changelog.


Test Coverage

177/177 is good. The new tests are well-structured:

  • The it.each() auth isolation table efficiently proves the fix is exhaustive across all 18 tools
  • The getServiceToken throw test covers the new catch path in requireServiceAuth
  • The non-JSON response test and the chitty_fact_seal 500 → PROOF_Q-not-called path are exactly the edge cases that matter

One note: the evidence invalid JSON test mocks .json() to throw, which correctly exercises the current code. If the code is later refactored to use parseJsonBody (as suggested above), the mock would need to switch to .text() returning non-JSON.


Summary

The security fix is real and the approach is correct. Two small items worth addressing before merge:

  1. Use parseJsonBody in chitty_fact_mint instead of the bare .json() try/catch, for consistency
  2. Fix the 'Ledger' label in the PDF export parseJsonBody call to 'ChittyLedger'

Neither is a blocker. The rest is well done.

Generated with Claude Code

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.

2 participants