Skip to content

Source of funds: report visuals, export bundle, shared tx detail panel#170

Open
tobomobo wants to merge 10 commits into
mainfrom
claude/thirsty-bardeen-a153e7
Open

Source of funds: report visuals, export bundle, shared tx detail panel#170
tobomobo wants to merge 10 commits into
mainfrom
claude/thirsty-bardeen-a153e7

Conversation

@tobomobo
Copy link
Copy Markdown
Contributor

Summary

  • On-device diagram renderer (kassiber/core/source_funds_diagram.py): one reportlab.graphics builder renders to vector PDF and a frozen SVG so the PDF and the desktop preview can't drift. Weighted Sankey flow with value/% edge labels, donut rollups (source mix + data sources), a cover at-a-glance strip, and a Bitcoin-native legend. Adds per-edge percent_of_target; source-mix percentages stay target-relative (no >100% artifact). SVG emission is gated (include_diagrams) so the hot compute_coverage path stays fast.
  • Export bundle: reports export-source-funds-bundle (+ ui.source_funds.export_bundle daemon kind) ships the report PDF plus the original evidence files attached to disclosed sources, with a SHA-256 manifest.json, reveal-mode scoped (no files for labels_only/minimal). New attachments.resolve_attachment_files helper. The report references originals; it never transcribes them.
  • Shared transaction detail panel: extracted TransactionDetailController from [codex] Extract transactions dashboard components #169's dashboard modules so the real, editable TransactionDetailSheet is reused in Source of Funds (Details/Classify/Pricing/Tax/Linked/Ledger). Replaced the target dropdown with a transaction-table picker. Wired the panel into the workflow — picker "details" (eye) action, and review-step gate findings + flow-path nodes open it. Because mutations invalidate all daemon queries, fixing pricing/exclusion/evidence there refreshes SoF gates + coverage automatically.

Test plan

  • ./scripts/quality-gate.sh green (py compile + smoke + review regressions + CLI help; frontend typecheck + eslint + vitest + build)
  • uv run python scripts/generate-source-funds-demo-report.py → vector PDF (0 raster XObjects), Sankey + donuts + cover strip render
  • reports export-source-funds-bundle --case <id> --file out.zip → zip has source-of-funds-report.pdf + evidence/ + manifest.json with matching SHA-256
  • Source of Funds: pick a target via the table; eye button / review flow-node / gate finding opens the real detail sheet; editing pricing refreshes the gates

Notes

  • Deliberately did not re-point the Transactions screen's own table at the shared controller (its row-level inline-classify/quick-save share draft state with the sheet — a larger follow-up).
  • Still open from the plan: German localization of report_context; Thread-2 items (traced-% hero, live reveal preview / per-node overrides).

🤖 Generated with Claude Code

- On-device diagram renderer (vector PDF + frozen SVG): weighted Sankey
  flow with value/% edge labels, donut rollups, cover at-a-glance strip,
  Bitcoin-native legend
- Per-edge percent_of_target; target-relative source-mix percentages
- Export bundle: report PDF + original evidence files + SHA-256 manifest,
  reveal-mode scoped (reports export-source-funds-bundle + daemon kind)
- attachments.resolve_attachment_files helper for evidence bundling
- GUI: shared TransactionDetailController reused by Source of Funds;
  transaction-table target picker; the real detail panel wired into the
  workflow (picker eye action, review gates + flow nodes); planned-amount
  mock echo so the field reflects in preview

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
drawing = Drawing(width, height)

body_top = height - pad - header_h
body_bottom = pad + legend_h
tobomobo and others added 9 commits May 25, 2026 10:22
Add a CLI test pinning the export-source-funds-bundle zip layout, manifest,
per-file SHA-256, and reveal-mode withholding. Document the bundle command +
ui.source_funds.export_bundle and the detail-panel/table-picker integration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Promote inbound-coverage buckets to a prominent hero (big fully-traced %,
segmented bar, legend) at the top of the workstation. Attested is shown as a
separate slice, never folded into fully-traced. Detailed panel stays collapsible.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extend the snapshot-frozen report_options beyond diagram_detail with
amount_precision (btc/sats), mask_recipient, and omit_sections (verbose PDF
sections). Wired through the normalizer, the PDF builder, CLI flags, and the
desktop Export-step controls, with a CLI test pinning the behavior.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Thread snapshot-frozen reveal_overrides (tx-id -> show/hide) through
_public_tx_id so a node can override the global reveal mode: hide always
redacts; show reveals even when the mode would drop it. Exposed via
reports source-funds --reveal-override and a per-transaction toggle in the
desktop Disclosure card that updates the preview live. CLI test pins both.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove the redundant "Selected:" chip (the transaction table already
highlights the selection) and restyle the planned-purpose note as an info
callout so it no longer reads as a selectable card.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…oller

Replace the Transactions screen's inline TransactionDetailSheet wiring (4
queries, attachment/unpair mutations, draft/save state, ~127-line sheet block)
with the shared TransactionDetailController used by Source of Funds. The table
keeps only its row-level needs (display-only getDraft, row-menu explorer).
Single detail-sheet implementation across both screens.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…tency

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces all native <select>/<input type=checkbox> across the Source of
Funds screen (target filters, advanced review editor, recipient picker,
report-visuals controls, omit-section toggles) with shadcn Select and
Checkbox primitives for full design-system consistency and proper
dark/light theming. Uses a non-empty sentinel for the "(no recipient)"
option and a placeholder for the empty transaction selection, as Radix
Select disallows empty-string item values.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The source-mix and data-source donut rings now sit in a two-column grid
on wider screens (stacking on narrow), cutting the report-visuals
section's vertical footprint roughly in half while the wide Sankey stays
full-width. Frozen-SVG fidelity is unchanged — each ring still renders
its own aspect, just in a narrower column.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@tobomobo tobomobo marked this pull request as ready for review May 25, 2026 18:44
Copy link
Copy Markdown

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

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: 9bfda4214a

ℹ️ 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".

key={node.id}
type="button"
className={nodeClassName}
onClick={() => onOpenTransaction?.(node.id)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Pass canonical transaction id when opening flow-node details

Clicking a transaction node in the flow preview currently passes node.id to onOpenTransaction, but those ids come from the report as tx:<uuid> graph ids, not raw transaction ids. openTxDetailById only matches raw ids / transaction_id / txRef, so this path no-ops and the detail sheet never opens from flow nodes, even though this interaction is advertised in the new workflow. Use the node's canonical transaction id (or strip the tx: prefix) before invoking the handler.

Useful? React with 👍 / 👎.

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