Skip to content

fix: wire CreateDefaultBillingProfile through on v1 marketplace app install - #4783

Open
vsengar-79 wants to merge 5 commits into
openmeterio:mainfrom
vsengar-79:sandbox-fix
Open

fix: wire CreateDefaultBillingProfile through on v1 marketplace app install#4783
vsengar-79 wants to merge 5 commits into
openmeterio:mainfrom
vsengar-79:sandbox-fix

Conversation

@vsengar-79

@vsengar-79 vsengar-79 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

POST /api/v1/marketplace/listings/{type}/install (and the API-key variant) accepted a createBillingProfile flag but silently ignored it — the flag was decoded into a dead field on the HTTP request wrapper struct instead of InstallAppV3Input.CreateDefaultBillingProfile, and CreateDefaultBillingProfileFn was never set at all, so no billing profile was ever provisioned regardless of the flag's value.

Changes:

Extracted the billing-profile provisioning logic (createBillingProfile/makeStripeDefaultBillingApp) out of api/v3/handlers/apps/install_app.go into a new shared package, openmeter/app/billingprofile, so both the v1 and v3 install handlers use identical provisioning behavior instead of duplicating it.
Fixed openmeter/app/httpdriver/marketplace.go (MarketplaceAppInstall and MarketplaceAppAPIKeyInstall) to set CreateDefaultBillingProfile on InstallAppV3Input and wire CreateDefaultBillingProfileFn via the new shared package, matching the v3 handler's pattern.
Removed the now-redundant CreateBillingProfile field from the v1 request wrapper structs.
No API contract changes — this only fixes existing, already-documented request/response behavior that wasn't functioning.

Summary by CodeRabbit

  • New Features
    • App installation now provisions a default billing profile based on the selected app type.
    • Stripe installations automatically configure billing, tax, invoicing, and payment references.
    • Sandbox installations receive a supported default billing profile with applicable capabilities.
    • Marketplace installation requests can control whether a default billing profile is created, defaulting to enabled.

Greptile Summary

This PR activates billing-profile provisioning for v1 marketplace installs and shares the existing provisioning implementation across API versions.

  • Moves Stripe, Sandbox, and Custom Invoicing provisioning dispatch into openmeter/app/billingprofile.
  • Passes createBillingProfile into InstallAppV3Input for both v1 installation methods.
  • Attaches the shared transactional provisioning callback in the v1 and v3 handlers.

Confidence Score: 3/5

The Custom Invoicing path should be fixed before merging because an enabled or defaulted createBillingProfile request still succeeds without creating a billing profile.

The newly activated v1 callback reaches a supported Custom Invoicing branch that returns success without performing the requested provisioning, leaving the endpoint's documented flag silently ineffective for that app type.

Files Needing Attention: openmeter/app/billingprofile/provision.go, openmeter/app/httpdriver/marketplace.go

Important Files Changed

Filename Overview
api/v3/handlers/apps/install_app.go Replaces handler-local provisioning methods with the equivalent shared billingprofile callback.
openmeter/app/billingprofile/provision.go Extracts shared provisioning behavior, but reports successful provisioning for Custom Invoicing without creating a profile.
openmeter/app/httpdriver/marketplace.go Correctly forwards the v1 request flag and installs the shared callback, exposing the incomplete Custom Invoicing branch.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[v1 marketplace install] --> B[InstallAppV3Input]
  B --> C[AppService.InstallApp transaction]
  C --> D{Create billing profile?}
  D -->|No| E[Return installed app]
  D -->|Yes| F[billingprofile.CreateDefault]
  F -->|Stripe| G[Create Stripe profile]
  F -->|Sandbox| H[Provision default profile]
  F -->|Custom Invoicing| I[Return success without profile]
Loading

Fix All in Claude Code 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
openmeter/app/billingprofile/provision.go:36-38
**Custom invoicing skips provisioning**

When a Custom Invoicing app is installed with `createBillingProfile` enabled or omitted, this branch returns success without creating a billing profile, causing the installation to complete while the documented flag remains ineffective and the response reports no default capabilities.

Reviews (1): Last reviewed commit: "Add default billing profile provisioning..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used:

Signed-off-by: vsengar-79 <146079793+vsengar-79@users.noreply.github.com>
Refactor billing profile creation to be transactional and remove the createBillingProfile function.

Signed-off-by: vsengar-79 <146079793+vsengar-79@users.noreply.github.com>
Signed-off-by: vsengar-79 <146079793+vsengar-79@users.noreply.github.com>
Signed-off-by: vsengar-79 <146079793+vsengar-79@users.noreply.github.com>
Implement default billing profile creation for installed apps, including Stripe and Sandbox types. Add error handling for unknown app types and incomplete implementations.

Signed-off-by: vsengar-79 <146079793+vsengar-79@users.noreply.github.com>
@vsengar-79
vsengar-79 requested a review from a team as a code owner July 26, 2026 11:52
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Default billing profile provisioning is centralized in billingprofile.CreateDefault. API and marketplace installation flows now inject this function transactionally, while marketplace request types replace the old boolean field with default-provisioning fields.

Changes

Billing profile provisioning

Layer / File(s) Summary
Type-specific provisioning
openmeter/app/billingprofile/provision.go
Adds shared provisioning for Stripe and Sandbox apps, preserves the CustomInvoicing placeholder, and errors on unknown app types.
API installation delegation
api/v3/handlers/apps/install_app.go
Delegates default billing profile creation to billingprofile.CreateDefault and removes handler-local provisioning helpers.
Marketplace installation delegation
openmeter/app/httpdriver/marketplace.go
Replaces CreateBillingProfile with default-provisioning fields and injects shared provisioning for both marketplace install paths.

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

Sequence Diagram(s)

sequenceDiagram
  participant InstallHandler
  participant billingprofile.CreateDefault
  participant billing.Service
  participant StripeAppService

  InstallHandler->>billingprofile.CreateDefault: provision installed app
  billingprofile.CreateDefault->>billing.Service: provision or inspect default profile
  billingprofile.CreateDefault->>StripeAppService: retrieve supplier contract for Stripe
  billingprofile.CreateDefault->>billing.Service: create billing profile
Loading

Possibly related PRs

Suggested labels: release-note/bug-fix

Suggested reviewers: turip

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: wiring default billing profile creation through the v1 marketplace install flow.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Comment on lines +36 to +38
// TODO: Implement custom invoicing billing profile creation
return nil, nil
default:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Custom invoicing skips provisioning

When a Custom Invoicing app is installed with createBillingProfile enabled or omitted, this branch returns success without creating a billing profile, causing the installation to complete while the documented flag remains ineffective and the response reports no default capabilities.

Knowledge Base Used: App Framework (Marketplace Integrations)

Prompt To Fix With AI
This is a comment left during a code review.
Path: openmeter/app/billingprofile/provision.go
Line: 36-38

Comment:
**Custom invoicing skips provisioning**

When a Custom Invoicing app is installed with `createBillingProfile` enabled or omitted, this branch returns success without creating a billing profile, causing the installation to complete while the documented flag remains ineffective and the response reports no default capabilities.

**Knowledge Base Used:** [App Framework (Marketplace Integrations)](https://app.greptile.com/openmeter/-/custom-context/knowledge-base/openmeterio/openmeter/-/docs/app.md)

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

Fix in Claude Code Fix in Codex

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
openmeter/app/httpdriver/marketplace.go (1)

132-136: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: the same three-line closure appears three times, and the comment oversells it a bit.

The closure is pure partial application — it doesn't itself open a transaction; the install service does, and it just runs inside that boundary. Something like "provisioning runs inside the install transaction" reads more accurately, and a small shared binder in the billingprofile package would collapse the triplication. Totally fine to leave as-is if you'd rather keep the wiring explicit at each call site.

  • openmeter/app/httpdriver/marketplace.go#L132-L136: reword the comment and optionally swap in the shared binder.
  • openmeter/app/httpdriver/marketplace.go#L204-L208: apply the same change.
  • api/v3/handlers/apps/install_app.go#L115-L117: apply the same change.
♻️ Sketch of the shared binder
// openmeter/app/billingprofile/provision.go
// DefaultFn binds the services needed by CreateDefault so handlers can hand the
// result straight to app.InstallAppV3Input.CreateDefaultBillingProfileFn.
func DefaultFn(billingService billing.Service, stripeAppService appstripe.Service) func(context.Context, app.App) ([]app.CapabilityType, error) {
	return func(ctx context.Context, installedApp app.App) ([]app.CapabilityType, error) {
		return CreateDefault(ctx, billingService, stripeAppService, installedApp)
	}
}
-			// make the billing profile provisioning transactional
-			request.CreateDefaultBillingProfileFn = func(ctx context.Context, installedApp app.App) ([]app.CapabilityType, error) {
-				return billingprofile.CreateDefault(ctx, h.billingService, h.stripeAppService, installedApp)
-			}
+			// Runs inside the install transaction opened by the app service.
+			request.CreateDefaultBillingProfileFn = billingprofile.DefaultFn(h.billingService, h.stripeAppService)
🤖 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 `@openmeter/app/httpdriver/marketplace.go` around lines 132 - 136, The repeated
billing-profile closure should be centralized as an optional shared binder, and
its comments should accurately state that provisioning runs inside the install
transaction. Add the binder in the billingprofile package, then replace the
closures at openmeter/app/httpdriver/marketplace.go lines 132-136 and 204-208
and api/v3/handlers/apps/install_app.go lines 115-117 with it; update each
associated comment accordingly.
🤖 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 `@openmeter/app/httpdriver/marketplace.go`:
- Around line 132-136: The repeated billing-profile closure should be
centralized as an optional shared binder, and its comments should accurately
state that provisioning runs inside the install transaction. Add the binder in
the billingprofile package, then replace the closures at
openmeter/app/httpdriver/marketplace.go lines 132-136 and 204-208 and
api/v3/handlers/apps/install_app.go lines 115-117 with it; update each
associated comment accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8b495aca-6013-42c6-a764-5585fa6c11c4

📥 Commits

Reviewing files that changed from the base of the PR and between 6457e4b and d115497.

📒 Files selected for processing (3)
  • api/v3/handlers/apps/install_app.go
  • openmeter/app/billingprofile/provision.go
  • openmeter/app/httpdriver/marketplace.go

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