Skip to content

feat(frost): interactive-signing observability counters (handoff §6.3)#4103

Merged
mswilkison merged 2 commits into
feat/frost-schnorr-migration-scaffoldfrom
feat/frost-interactive-signing-metrics
Jun 21, 2026
Merged

feat(frost): interactive-signing observability counters (handoff §6.3)#4103
mswilkison merged 2 commits into
feat/frost-schnorr-migration-scaffoldfrom
feat/frost-interactive-signing-metrics

Conversation

@mswilkison

Copy link
Copy Markdown
Contributor

What

The one genuinely buildable, non-gated item from the handoff's §6 production-integration review. The interactive signing runner surfaces outcomes only via return values — no logs or metrics — so before the coordinated tECDSA→FROST flip there's no operator-visible signal for "is interactive signing working, and is anything failing closed?"

Adds process-wide cumulative counters following the existing roast_retry_metrics.go pattern:

  • frost_interactive_signing_success_total / _failure_total — whether the interactive path, once driven, produces signatures or fails on a committed attempt. Emitted at the single executor-entry chokepoint where the drive's (signature, error) outcome is interpreted (the inactive fall-through — both nil — counts as neither).
  • frost_interactive_signing_coarse_fallback_refused_total — the flip-safety signal: increments whenever no-coarse-fallback mode (KEEP_CORE_FROST_INTERACTIVE_SIGNING_ONLY) terminally refuses a would-be coarse/legacy signing, at all three feat(frost): no-coarse-fallback mode for coarse-path retirement (default off) #4101 refusal sites (legacy backend, native-backend promotion, FFI adapter). During a staged flip a misconfigured node — interactive-only on but interactive signing not running — shows up here instead of silently failing every attempt.

RegisterInteractiveSigningMetrics mirrors RegisterRoastRetryMetrics; operators wire it at startup (alongside the existing one, when the registration wiring lands). Emitted in every build, stays at zero until the gated interactive path runs — inert by default.

Why this is the only code item here

From the §6 review (verified against code, in FROST_PRODUCTION_HANDOFF.md): §6.1 signer-material is mostly already built (material flows via DKG + persistence; the resolver fail-closed is already tested), §6.2 activation wiring and §6.4 wallet lifecycle are gated (audit/recovery-leaf/MacLane), and the rest of §6.3 is ops/runbooks. Observability is the one un-gated code slice — and it's exactly what the coordinated flip needs.

Validation

Builds across all tag combos; new tests pass (incl. an end-to-end legacy-backend refusal bumping the counter); no regression in backend/executor-entry suites; cgo vet + gofmt clean.

🤖 Generated with Claude Code

The interactive signing runner surfaces outcomes only via return values - no logs or
metrics - so before the coordinated tECDSA->FROST flip there is no operator-visible
signal for "is interactive signing working, and is anything failing closed?". Adds
process-wide cumulative counters following the roast_retry_metrics.go pattern:

  - frost_interactive_signing_success_total / _failure_total: whether the interactive
    path, once driven, produces signatures or fails on a committed attempt. Emitted at
    the single executor-entry chokepoint where the drive's (signature, error) outcome
    is interpreted (the inactive fall-through - both nil - counts as neither).
  - frost_interactive_signing_coarse_fallback_refused_total: the FLIP-SAFETY signal -
    increments whenever no-coarse-fallback mode (KEEP_CORE_FROST_INTERACTIVE_SIGNING_ONLY)
    terminally refuses a would-be coarse/legacy signing, at all three #4101 refusal
    sites (legacy backend, native backend promotion, FFI adapter). During a staged flip
    a misconfigured node - interactive-only on but interactive signing not running -
    shows up here instead of silently failing every attempt.

RegisterInteractiveSigningMetrics mirrors RegisterRoastRetryMetrics; operators wire it
at startup (alongside the existing one, when the registration wiring lands). Emitted in
every build, stays at zero until the gated interactive path runs - inert by default.

This is the one genuinely buildable, non-gated item from the handoff's §6 production-
integration review: §6.1 (signer material) is mostly already built (DKG+persistence;
resolver fail-closed is tested), §6.2 activation wiring + §6.4 wallet lifecycle are
gated, and the rest of §6.3 is ops/runbooks.

Builds across all tag combos; new tests pass (incl. an end-to-end legacy-backend
refusal bumping the counter); no regression; cgo vet + gofmt clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: aeafc290-7175-4018-b09a-b212b94d0428

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/frost-interactive-signing-metrics

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.

… startup

Self-review fold (the one valid finding; Codex + Gemini both approved the PR with no
findings): the counters incremented internally but RegisterInteractiveSigningMetrics
was never called at startup - so they never reached the Prometheus scrape, leaving the
PR's "operator-visible signal" latent. (The pre-existing RegisterRoastRetryMetrics had
the same gap.)

Wire both Phase 7.3 metric families at the existing tbtc.Initialize clientInfo
registration site (right beside ObserveApplicationSource("tbtc", ...)). This is inert:
the sources report zero until the gated interactive path runs, and registering a scrape
callback does not activate any signing behavior - safe regardless of the cutover gates.
Wiring both (not only the new one) avoids leaving the sibling roast-retry counters
unexposed next to a freshly-exposed interactive family.

Builds clean (default + frost_native); vet + gofmt clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mswilkison mswilkison merged commit b439903 into feat/frost-schnorr-migration-scaffold Jun 21, 2026
15 of 16 checks passed
@mswilkison mswilkison deleted the feat/frost-interactive-signing-metrics branch June 21, 2026 19:27
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