Skip to content

fix(api): complete managed onboarding without operator eERC registration - #165

Open
hitakshiA wants to merge 1 commit into
mainfrom
fix/console-managed-onboarding-no-operator-registration
Open

fix(api): complete managed onboarding without operator eERC registration#165
hitakshiA wants to merge 1 commit into
mainfrom
fix/console-managed-onboarding-no-operator-registration

Conversation

@hitakshiA

@hitakshiA hitakshiA commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Problem

Console onboarding on BenzoNet L1 hung forever at awaiting_registration. The UI wizard gates treasury provisioning behind KYB completion, so the whole flow deadlocked.

Root cause

Managed onboarding polled isUserRegistered(operator), but nothing ever registers the operator EOA:

  • the operator is a self-custody SIWE identity — the backend has no key to register it,
  • the console has no client-side prover, and
  • treasury provisioning registers a separate managed treasury EOA, not the operator.

In managed custody the operator is an admin that never holds an encrypted balance (the managed treasury does, and it is eERC-registered separately), so waiting on operator registration is both impossible and unnecessary.

Fix

New ONBOARDING_REQUIRE_OPERATOR_REGISTRATION flag (default false = managed). When false, onboarding completes once KYC + allowlist + gas land, and any row already parked in awaiting_registration is completed rather than polled. Set true only for a self-custody deployment where operators register themselves.

Verification

  • New test: managed onboarding completes after gas drip with zero registration polls.
  • Existing poll-path tests pin the flag true (unchanged behavior).
  • api onboarding + orgs (24/24) suites pass; build + lint clean.
  • Driven headless on live console.benzo.space (BenzoNet L1): SIWE → org → KYB complete → treasury provisioned (registered:true) → dashboard.

Summary by CodeRabbit

  • New Features

    • Added a configuration option to control whether operator registration is required during onboarding.
    • Onboarding can now complete automatically after the gas drip step when operator registration is disabled.
  • Bug Fixes

    • Improved onboarding completion handling for configurations that do not require operator registration.
  • Tests

    • Added coverage confirming onboarding completes without registration polling when the option is disabled.

Greptile Summary

This PR changes onboarding so managed custody no longer waits for operator eERC registration. The main changes are:

  • Adds an ONBOARDING_REQUIRE_OPERATOR_REGISTRATION config flag.
  • Completes managed onboarding after KYC, allowlist, and gas drip.
  • Completes existing awaiting_registration rows when operator registration is disabled.
  • Updates tests to cover managed completion and preserve polling-path behavior.

Confidence Score: 5/5

This looks safe to merge after confirming the new default is acceptable for all deployed environments.

  • The managed-custody path matches the intended flow.
  • Existing registration polling is preserved when the flag is enabled.
  • Self-custody deployments need the new env var set during rollout.

services/api/src/config.ts

Important Files Changed

Filename Overview
services/api/src/config.ts Adds the operator-registration requirement flag with a managed-custody default.
services/api/src/onboarding/service.ts Short-circuits managed onboarding completion from gas_dripped and awaiting_registration.
services/api/test/api.test.ts Adds managed-onboarding coverage and pins existing API tests to the registration-required path.
services/api/test/orgs.test.ts Pins the org test base config to the registration-required path.

Fix All in Claude Code Fix All in Cursor Fix All in Codex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
services/api/src/config.ts:191
**Self-Custody Default Skips Registration**

When an existing self-custody deployment upgrades without setting the new env var, the default `false` value sends `gas_dripped` and `awaiting_registration` rows directly to `complete`. Those operators can be treated as onboarded before their eERC registration is verified, so later encrypted-balance flows can fail after the UI has left onboarding.

Reviews (1): Last reviewed commit: "fix(api): complete managed onboarding wi..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Console onboarding hung forever at awaiting_registration on BenzoNet L1: it
polled isUserRegistered(operator) but nothing ever registers the operator
EOA. In managed custody the operator is an admin identity that never holds an
encrypted balance (the managed treasury does, and it is eERC-registered
separately during treasury provisioning), the backend has no operator key,
and the console has no client-side prover, so the poll could never resolve.

Gate the operator-registration poll behind a new
ONBOARDING_REQUIRE_OPERATOR_REGISTRATION flag (default false = managed). When
false, onboarding completes once KYC + allowlist + gas land, and any row
already parked in awaiting_registration is completed rather than polled. Set
true only for a self-custody deployment where operators register themselves.

Verified: fresh-org onboarding on console.benzo.space now advances past KYB;
new managed-path test asserts complete-after-gas with zero registration
polls; existing poll-path tests pin the flag true.
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The API adds a configuration flag controlling whether operator registration is required. When disabled, managed onboarding completes after gas dripping without polling for registration. Tests cover both enabled defaults and the disabled completion path.

Changes

Onboarding registration flow

Layer / File(s) Summary
Registration configuration and test defaults
services/api/src/config.ts, services/api/test/api.test.ts, services/api/test/orgs.test.ts
Adds and transforms ONBOARDING_REQUIRE_OPERATOR_REGISTRATION; shared API and organization test configurations enable registration requirements by default.
Conditional onboarding completion
services/api/src/onboarding/service.ts, services/api/test/api.test.ts
Adds completion handling for disabled registration requirements and verifies onboarding completes without polling after one gas drip.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant advanceOnboarding
  participant OnboardingDB
  participant RegistrationPoller
  Client->>advanceOnboarding: Start onboarding
  advanceOnboarding->>OnboardingDB: Read onboarding state
  alt registration requirement disabled
    advanceOnboarding->>OnboardingDB: Mark registration complete
    OnboardingDB-->>Client: Status complete
  else registration requirement enabled
    advanceOnboarding->>RegistrationPoller: Poll operator registration
    RegistrationPoller-->>OnboardingDB: Registration result
  end
Loading

Possibly related PRs

  • Miny-Labs/benzo#74: Implements the onboarding registration polling state machine modified by this change.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: managed onboarding now completes without operator registration.
✨ 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 fix/console-managed-onboarding-no-operator-registration

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

@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.

🧹 Nitpick comments (2)
services/api/src/onboarding/service.ts (1)

519-530: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse markOnboardingRegistered in pollRegistration to remove the duplicate update.

pollRegistration's registered branch (further down, lines 541-547) sets the exact same fields (error: null, registrationCompletedAt, registrationLastCheckedAt, status: "complete") via a separate inline updateOnboarding call. Now that this helper exists, pollRegistration should call it instead of duplicating the logic, so both completion paths stay in sync going forward.

♻️ Proposed fix
 	const now = new Date();
 	const registered = await options.chain.isUserRegistered(row.address);
 
 	if (registered) {
-		await updateOnboarding(db, row.userId, {
-			error: null,
-			registrationCompletedAt: now,
-			registrationLastCheckedAt: now,
-			status: "complete",
-		});
+		await markOnboardingRegistered(db, row.userId);
 		return;
 	}
🤖 Prompt for 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.

In `@services/api/src/onboarding/service.ts` around lines 519 - 530, Update the
registered branch of pollRegistration to call markOnboardingRegistered(db,
userId) instead of its duplicate inline updateOnboarding call, preserving the
existing completion behavior and removing the repeated field assignments.
services/api/src/config.ts (1)

182-192: 🧹 Nitpick | 🔵 Trivial

Confirm self-custody deployments explicitly set this flag.

The new default (false) means any deployment that doesn't explicitly set ONBOARDING_REQUIRE_OPERATOR_REGISTRATION=true will silently skip operator-registration polling — including any existing self-custody deployment whose env config wasn't updated for this change. Worth confirming deployment configs/runbooks for self-custody environments are updated to set this explicitly, since the security gate (operator eERC registration) would otherwise be bypassed without any warning at startup.

🤖 Prompt for 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.

In `@services/api/src/config.ts` around lines 182 - 192, Update self-custody
deployment configurations and operational runbooks to explicitly set
ONBOARDING_REQUIRE_OPERATOR_REGISTRATION=true, and add startup validation or a
warning for self-custody deployments when this flag is false. Preserve the false
default for managed-custody deployments while ensuring self-custody cannot
silently bypass operator-registration polling.
🤖 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.

Nitpick comments:
In `@services/api/src/config.ts`:
- Around line 182-192: Update self-custody deployment configurations and
operational runbooks to explicitly set
ONBOARDING_REQUIRE_OPERATOR_REGISTRATION=true, and add startup validation or a
warning for self-custody deployments when this flag is false. Preserve the false
default for managed-custody deployments while ensuring self-custody cannot
silently bypass operator-registration polling.

In `@services/api/src/onboarding/service.ts`:
- Around line 519-530: Update the registered branch of pollRegistration to call
markOnboardingRegistered(db, userId) instead of its duplicate inline
updateOnboarding call, preserving the existing completion behavior and removing
the repeated field assignments.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b61781df-55ea-4d39-a189-a35d2505ea8f

📥 Commits

Reviewing files that changed from the base of the PR and between 87c8cec and 4a37001.

📒 Files selected for processing (4)
  • services/api/src/config.ts
  • services/api/src/onboarding/service.ts
  • services/api/test/api.test.ts
  • services/api/test/orgs.test.ts

// register their own eERC identity.
ONBOARDING_REQUIRE_OPERATOR_REGISTRATION: z
.enum(["true", "false"])
.default("false")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Self-Custody Default Skips Registration

When an existing self-custody deployment upgrades without setting the new env var, the default false value sends gas_dripped and awaiting_registration rows directly to complete. Those operators can be treated as onboarded before their eERC registration is verified, so later encrypted-balance flows can fail after the UI has left onboarding.

Prompt To Fix With AI
This is a comment left during a code review.
Path: services/api/src/config.ts
Line: 191

Comment:
**Self-Custody Default Skips Registration**

When an existing self-custody deployment upgrades without setting the new env var, the default `false` value sends `gas_dripped` and `awaiting_registration` rows directly to `complete`. Those operators can be treated as onboarded before their eERC registration is verified, so later encrypted-balance flows can fail after the UI has left onboarding.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Cursor Fix in Codex

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