Skip to content

feat(helper): each seat reports the fee era its device accepts (#847) - #945

Merged
danielgorgonha merged 11 commits into
stagingfrom
feat/seat-fee-report
Nov 13, 2026
Merged

danielgorgonha merged 11 commits into
stagingfrom
feat/seat-fee-report

Conversation

@danielgorgonha

Copy link
Copy Markdown
Member

What & why

Second step of the fee release (#847): each device tells the vault's server, when it registers, from which block height its build accepts the lower network fee (ZIP 2009), and the server keeps that per seat. Nothing changes in what a payment pays yet: the next step reads these reports to decide, per vault, whether every seat accepts the lower fee.

Why one piece: the field only works end to end. The height comes from the device's own fee table (konclave-seal), the browser sends it (the wasm export and ui/src/device-registration.ts), and the server stores and reads it (/api/vault/devicekey, orchestrator/src/helper.rs). Split, each half would ship code with no producer or no consumer, and the version tests below need both sides in one change.

  • konclave-seal: Table::fee_from() answers the height from the fee table; no literal elsewhere (a source scan catches one in the UI too).
  • The browser sends fee_from on the device registration; an old package or a failing export simply omits it.
  • The server stores it on the seat's own record, under the write lock; only a request that names its seat writes; a registration without the field clears that seat's report (the safe side: the seat counts as the current fee). The report is a hint, not a proof: it is not part of any signed message.
  • seat_fee_reports reads seats 1..=total and answers "do not decide" for a vault with no seat count.
  • Version tests: version_matrix_a_v020_coordinator_ignores_fee_from_and_it_is_in_no_signed_payload, version_matrix_b_v021_coordinator_takes_a_registration_without_fee_from_as_no_report, version_matrix_c_a_v020_coordinator_reads_the_registry_a_v021_wrote.
  • The browser package is rebuilt from source (reproducible with wasm-pack 0.13.1).

Verify-before-finishing checklist

  • cargo fmt --check + cargo clippy -- -D warnings pass (konclave-seal, konclave-wasm, orchestrator, helper-server)
  • cargo test passes (seal, wasm, orchestrator, helper-server); ui/: vitest, tsc, lint, build; Playwright 114
  • No secret, key share, seed, or passphrase in code, logs, URLs, or query strings
  • Every fund-moving path keeps preview + explicit confirmation (no fee change in this step)
  • Reviewed: code, tester, security
  • CHANGELOG: root, ui/ and helper-server/
  • Docs/comments in English; commits are type(scope): description
  • AI disclosure: written with Claude Code, reviewed by the author, who answers for every line. Commits carry Co-Authored-By: Claude <noreply@anthropic.com>. No session link.

🤖 Generated with Claude Code

danielgorgonha and others added 11 commits November 12, 2026 23:22
… fee

One function over the era table (Table::fee_from), tested against the literal 3,590,000; no other place states it.

Co-Authored-By: Claude <noreply@anthropic.com>
POST /api/vault/devicekey takes an optional fee_from (height or absent, strict). It is kept on the seat's record, a registration without it clears it, and the pinned branch writes it under the same lock without touching the seat or the keys. seat_fee_reports reads it per seat 1..=total. Version-matrix tests for v0.20 <-> v0.21 included.

Co-Authored-By: Claude <noreply@anthropic.com>
Read from the wasm export; an older wasm without it sends no field.

Co-Authored-By: Claude <noreply@anthropic.com>
…ees it accepts

Nothing changes in what a payment pays yet.

Co-Authored-By: Claude <noreply@anthropic.com>
The shape test allows each category once per section.

Co-Authored-By: Claude <noreply@anthropic.com>
…ckage

feeFrom() reads Table::fee_from; the package is rebuilt with wasm-pack 0.13.1 --target web and copied with --remove-destination. fee-estimate.test.ts pins the literal 3,590,000 through the real wasm.

Co-Authored-By: Claude <noreply@anthropic.com>
…that seat

A registration without a seat no longer writes or clears any report; the writer and the reader share one seat selector; seat_fee_reports answers None for a vault with no seat count. Version matrix (b) now asserts the stored report first, (c) covers a v0.20 reading the registry a v0.21 wrote, and (a) reads the signed field lists.

Co-Authored-By: Claude <noreply@anthropic.com>
…ort omits the field

The scan in fee-estimate.test.ts gains the 3,590,000 pattern with planted and non-matching cases; device-registration-fee covers feeFrom throwing.

Co-Authored-By: Claude <noreply@anthropic.com>
…uthenticated

No behaviour change.

Co-Authored-By: Claude <noreply@anthropic.com>
…and the scan pins seat_message's signature

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
konclave-demo Ready Ready Preview Nov 13, 2026 3:18am UTC

Request Review

@danielgorgonha danielgorgonha self-assigned this Nov 13, 2026
@danielgorgonha danielgorgonha added the enhancement New feature or request label Nov 13, 2026
@danielgorgonha
danielgorgonha merged commit 08a4524 into staging Nov 13, 2026
10 checks passed

This branch was successfully deployed

1 active deployment
Preview — e124a83a Deployed Nov 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant