Skip to content

feat: don't allow listing or getting unit config equipped plans on v1 - OM-409#4679

Merged
rolosp merged 4 commits into
mainfrom
feat/om-409-exclude-unit-config-from-v1
Jul 14, 2026
Merged

feat: don't allow listing or getting unit config equipped plans on v1 - OM-409#4679
rolosp merged 4 commits into
mainfrom
feat/om-409-exclude-unit-config-from-v1

Conversation

@rolosp

@rolosp rolosp commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What

Excludes unit_config-bearing plans and subscriptions from the v1 API read surface: the v1 plan list omits them, and v1 plan GET / subscription GET return a typed error instead of a silently-stripped object. Touches openmeter/productcatalog/* (ratecard, plan, errors, plan adapter/httpdriver, subscription http) and openmeter/subscription/* (subscriptionspec), plus a new e2e test. No schema change, no migration — this is a read-only serialization-boundary change.

Why

The v1 API's rate-card types have no unit_config field, so on read the v1 mapper (productcatalog/http/mapping.go FromRateCard) silently drops it. A v3-authored plan billing e.g. $X per 1000 units comes back over v1 looking like a plain $X per unit plan — active misrepresentation, not just missing data, and unsafe wherever v1 read consumers exist (an enablement gate for the UnitConfig epic). Read and subscribe are separable: a subscription can still be started from a unit_config plan server-side (OM-399), it just can't be faithfully serialized to v1 shapes. So the fix restricts only the read surfaces and steers authoring/consumption of unit_config to v3.

How

  • Added a content-derived predicate — RateCards.HasUnitConfig() (productcatalog/ratecard.go), plan.Plan.HasUnitConfig() (plan/plan.go), and SubscriptionSpec.HasUnitConfig() + phase-level (subscription/subscriptionspec.go, mirroring the existing HasEntitlements/HasBillables) — so exclusion is decided from object content, with no stored flag.
  • Added a shared typed error ErrUnitConfigNotRepresentable (code unit_config_not_representable_in_v1, productcatalog/errors.go), carrying a WithHTTPStatusCodeAttribute(400) so both v1 error encoders resolve it to a 400 at the serialization boundary (the subscription encoder derives status from that attribute).
  • v1 plan LIST — excludes unit_config plans at the query layer via a new opt-in ListPlansInput.ExcludeUnitConfig, applied as an Ent Not(HasPhasesWith(HasRatecardsWith(UnitConfigNotNil, DeletedAtIsNil))) predicate before Paginate's COUNT, so TotalCount and the page slice stay exact. Opt-in because the adapter is shared with v3 (api/v3/handlers/plans/list.go), which can represent unit_config and must keep showing these plans; only the v1 handler sets the flag.
  • v1 plan GET — rejects a unit_config plan with the typed 400 in GetPlan, before mapping.
  • v1 subscription GET — rejects via view.Spec.HasUnitConfig() in the GET handler (not in the shared MapSubscriptionViewToAPI mapper, which is also used by change/migrate and must stay permissive). v1 subscription LIST needs no change — its summary shape carries no rate cards.
  • Subscribe-by-plan-key stays permissive — a v1 subscription started from a unit_config plan by key still succeeds and rates correctly; only the read surfaces are restricted.
  • Tests: predicate unit tests (RateCards, plan.Plan, SubscriptionSpec); a DB adapter test asserting the LIST exclusion + exact TotalCount; and an e2e (e2e/v1readsurface_unitconfig_test.go) driving the full path over HTTP — plan GET → 400, plain plan GET → 200, LIST exclusion + exact TotalCount, v1 subscribe-by-key → 201, subscription GET → 400. The OM-399 subscribe-from-unit_config-plan test is retained as a regression guard.
  • Docs/TypeSpec for the v1 endpoints are intentionally deferred (feature is behind unitConfig.enabled, dev rollout first); the LIST carries no hidden-count signal by explicit decision.

No production code outside the v1 read path is changed, and no schema or migration is introduced.

Summary by CodeRabbit

  • New Features

    • Added representability safeguards for plans, plan add-ons, add-ons, and subscription workflows that include unit-based billing configurations.
    • v1 list endpoints now exclude unsupported items, and v1 detail/lifecycle/assignment operations reject them with a consistent validation error.
  • Bug Fixes

    • Fixed filtered TotalCount/listing behavior to reflect excluded unit-config items accurately.
  • Tests

    • Added/extended unit, adapter, and end-to-end tests to cover v1 read, list, lifecycle, subscription creation, and add-on flows for unsupported configurations.

Greptile Summary

This PR keeps unit-config resources off the v1 API read and mutation surfaces. The main changes are:

  • Adds content-based unit-config detection for rate cards, plans, add-ons, and subscription specs.
  • Filters unit-config plans and add-ons out of v1 list queries.
  • Returns a typed v1 error when unit-config resources cannot be represented safely.
  • Propagates mutation guards through plan and add-on publish, archive, update, and next-version paths.
  • Adds tests for list filtering, mutation rejection, and v1 read behavior.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
openmeter/productcatalog/plan/service/plan.go Forwards the unit-config rejection flag into predecessor archival and checks plan mutations before state changes.
openmeter/productcatalog/addon/service/addon.go Forwards the unit-config rejection flag into predecessor archival and checks add-on mutations before state changes.
openmeter/productcatalog/plan/httpdriver/plan.go Sets v1 plan read and mutation paths to reject or exclude unit-config-backed plans.
openmeter/productcatalog/addon/httpdriver/addon.go Sets v1 add-on read and mutation paths to reject or exclude unit-config-backed add-ons.

Reviews (7): Last reviewed commit: "fix: review comment fixes" | Re-trigger Greptile

Context used (3)

  • Context used - CLAUDE.md (source)
  • Context used - AGENTS.md (source)
  • Context used - api/spec/AGENTS.md (source)

@rolosp
rolosp requested a review from a team as a code owner July 9, 2026 18:33
@rolosp rolosp changed the title feat: don't allow listing or getting unit config equipped plans on v1… feat: don't allow listing or getting unit config equipped plans on v1 - OM-409 Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds typed unit_config detection across catalog and subscription models, excludes configured plans and add-ons from v1 lists, rejects unsupported v1 reads and mutations, and adds unit, adapter, service, and end-to-end coverage.

Changes

Unit config detection and validation

Layer / File(s) Summary
Unit config error and detection helpers
openmeter/productcatalog/..., openmeter/subscription/subscriptionspec.go, related tests
Adds the typed validation error and HasUnitConfig() helpers for rate cards, plans, add-ons, and subscription specifications.

Plan filtering and mutation guards

Layer / File(s) Summary
Plan filtering and lifecycle rejection
openmeter/productcatalog/plan/...
Adds exclusion and rejection inputs, filters configured plans before pagination and counting, and rejects unsupported lifecycle operations.
v1 plan handler wiring
openmeter/productcatalog/plan/httpdriver/plan.go
Enables configured-plan exclusion for v1 lists and rejection for reads and mutations.

Add-on filtering and mutation guards

Layer / File(s) Summary
Add-on filtering and lifecycle rejection
openmeter/productcatalog/addon/...
Adds configured add-on filtering and lifecycle rejection, including adapter coverage for filtered totals.
v1 add-on handler wiring
openmeter/productcatalog/addon/httpdriver/addon.go
Excludes configured add-ons from v1 lists and rejects configured reads and mutations.

Subscription and plan add-on safeguards

Layer / File(s) Summary
Subscription and subscription add-on guards
openmeter/productcatalog/subscription/..., openmeter/subscription/addon/http/...
Propagates rejection flags through subscription changes and migrations, and blocks configured subscription and subscription add-on operations.
Plan add-on assignment guards
openmeter/productcatalog/planaddon/...
Rejects configured plans or add-ons during assignment creation, updates, listing, and retrieval.

End-to-end coverage

Layer / File(s) Summary
v1 read-surface and mutation coverage
e2e/v1readsurface_unitconfig_test.go
Verifies v1 plan reads, lists, mutations, configured-plan subscription creation, subscription reads, and subscription add-on listing behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant V3Catalog
  participant V1PlanAPI
  participant V1SubscriptionAPI
  participant V1AddonAPI
  V3Catalog->>V1PlanAPI: create configured and plain plans
  V1PlanAPI-->>V3Catalog: reject configured reads and mutations
  V3Catalog->>V1SubscriptionAPI: create subscription by configured plan key
  V1SubscriptionAPI-->>V3Catalog: reject subscription read
  V3Catalog->>V1AddonAPI: list subscription add-ons
  V1AddonAPI-->>V3Catalog: reject configured subscription surface
Loading

Possibly related PRs

Suggested labels: release-note/bug-fix, area/product-catalog, area/subscriptions

Suggested reviewers: chrisgacsal, tothandras

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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 matches the main v1 read-surface change: excluding or rejecting unit-config plans on list/get paths.
✨ 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 feat/om-409-exclude-unit-config-from-v1

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.

@rolosp rolosp added the release-note/misc Miscellaneous changes label Jul 9, 2026
@GAlexIHU

Copy link
Copy Markdown
Contributor

should we extend this boundary to every v1 response that serializes rate cards? add-on GET/LIST, mutations, etc... can return an object with unit_config silently stripped... is that intentionally out of scope, or should we guarantee that v1 never serializes these objects?

@rolosp
rolosp force-pushed the feat/om-409-exclude-unit-config-from-v1 branch from 2323906 to a26e0d2 Compare July 10, 2026 14:46

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

Actionable comments posted: 1

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

Inline comments:
In `@openmeter/productcatalog/addon/adapter/adapter_test.go`:
- Around line 453-454: In TestListAddonsExcludeUnitConfig, replace
context.Background() with t.Context() so the test context follows the test
lifecycle.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 64c97b9f-bb11-42a2-84ba-ab78f8c2e064

📥 Commits

Reviewing files that changed from the base of the PR and between 2323906 and a26e0d2.

📒 Files selected for processing (19)
  • e2e/v1readsurface_unitconfig_test.go
  • openmeter/productcatalog/addon/adapter/adapter_test.go
  • openmeter/productcatalog/addon/adapter/addon.go
  • openmeter/productcatalog/addon/httpdriver/addon.go
  • openmeter/productcatalog/addon/service.go
  • openmeter/productcatalog/errors.go
  • openmeter/productcatalog/http/mapping.go
  • openmeter/productcatalog/http/mapping_test.go
  • openmeter/productcatalog/plan/adapter/adapter_test.go
  • openmeter/productcatalog/plan/adapter/plan.go
  • openmeter/productcatalog/plan/httpdriver/plan.go
  • openmeter/productcatalog/plan/plan.go
  • openmeter/productcatalog/plan/plan_test.go
  • openmeter/productcatalog/plan/service.go
  • openmeter/productcatalog/ratecard.go
  • openmeter/productcatalog/ratecard_test.go
  • openmeter/productcatalog/subscription/http/get.go
  • openmeter/subscription/subscriptionspec.go
  • openmeter/subscription/subscriptionspec_test.go
✅ Files skipped from review due to trivial changes (3)
  • openmeter/productcatalog/addon/service.go
  • openmeter/productcatalog/errors.go
  • openmeter/subscription/subscriptionspec_test.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • openmeter/productcatalog/subscription/http/get.go
  • openmeter/productcatalog/plan/plan.go
  • openmeter/subscription/subscriptionspec.go
  • openmeter/productcatalog/plan/adapter/plan.go
  • openmeter/productcatalog/ratecard.go
  • openmeter/productcatalog/plan/plan_test.go
  • openmeter/productcatalog/plan/httpdriver/plan.go
  • openmeter/productcatalog/plan/service.go
  • e2e/v1readsurface_unitconfig_test.go
  • openmeter/productcatalog/plan/adapter/adapter_test.go
  • openmeter/productcatalog/ratecard_test.go

Comment on lines +453 to +454
func TestListAddonsExcludeUnitConfig(t *testing.T) {
ctx := context.Background()

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the test file around the cited lines and nearby context.
FILE="openmeter/productcatalog/addon/adapter/adapter_test.go"
wc -l "$FILE"
sed -n '430,480p' "$FILE"

# Check for t.Context() usage in the same file and surrounding tests.
rg -n 't\.Context\(\)|context\.Background\(\)|context\.TODO\(\)' "$FILE" openmeter/productcatalog/addon/adapter -g '*_test.go'

Repository: openmeterio/openmeter

Length of output: 2117


Use t.Context() here
It matches the test lifecycle better than context.Background().

🤖 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/productcatalog/addon/adapter/adapter_test.go` around lines 453 -
454, In TestListAddonsExcludeUnitConfig, replace context.Background() with
t.Context() so the test context follows the test lifecycle.

Source: Coding guidelines

@rolosp
rolosp force-pushed the feat/om-409-exclude-unit-config-from-v1 branch 2 times, most recently from 8b22826 to 5e0a664 Compare July 13, 2026 19:07
Comment thread openmeter/productcatalog/plan/service/plan.go
Comment thread openmeter/productcatalog/addon/service/addon.go

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

Actionable comments posted: 4

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

Inline comments:
In `@openmeter/productcatalog/addon/service.go`:
- Around line 411-413: Update the nested ArchiveAddon request in the v1 publish
flow to pass RejectUnitConfig from the incoming params, ensuring version
transitions reject an active addon with unit_config when requested. Add a
regression test covering a representable new version replacing an active
configured version.

In `@openmeter/productcatalog/addon/service/addon.go`:
- Around line 345-348: Extend the validation around RejectUnitConfig in the
add-on update flow to inspect incoming params.RateCards for unit_config, not
only add.AsProductCatalogAddon().HasUnitConfig(). Reject the update with
productcatalog.ErrUnitConfigNotRepresentable when either the existing add-on or
the resolved incoming/merged rate-card candidate contains unit_config, before
calling UpdateAddon.

In `@openmeter/productcatalog/plan/service.go`:
- Around line 154-156: Update CreatePlanInput.Validate to honor the embedded
RejectUnitConfig flag by adding the same unit_config conversion rejection used
during mutation validation to its existing error aggregation. If create
operations are intentionally unsupported, remove the flag from CreatePlanInput
instead.

In `@openmeter/subscription/addon/http/create.go`:
- Around line 62-70: Extend the addon creation validation around
currentView.Spec.HasUnitConfig() to also load the addon identified by
req.AddonInput.AddonID and reject it when its rate card has UnitConfig. Perform
this addon-side check before the addon merge or creation path, returning
productcatalog.ErrUnitConfigNotRepresentable, while preserving the existing
subscription check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 092ff0bc-a204-4b58-ad2e-81804b38bc85

📥 Commits

Reviewing files that changed from the base of the PR and between 8b22826 and 5e0a664.

📒 Files selected for processing (36)
  • e2e/v1readsurface_unitconfig_test.go
  • openmeter/productcatalog/addon.go
  • openmeter/productcatalog/addon/adapter/adapter_test.go
  • openmeter/productcatalog/addon/adapter/addon.go
  • openmeter/productcatalog/addon/httpdriver/addon.go
  • openmeter/productcatalog/addon/service.go
  • openmeter/productcatalog/addon/service/addon.go
  • openmeter/productcatalog/errors.go
  • openmeter/productcatalog/http/mapping.go
  • openmeter/productcatalog/plan.go
  • openmeter/productcatalog/plan/adapter/adapter_test.go
  • openmeter/productcatalog/plan/adapter/plan.go
  • openmeter/productcatalog/plan/httpdriver/plan.go
  • openmeter/productcatalog/plan/plan.go
  • openmeter/productcatalog/plan/plan_test.go
  • openmeter/productcatalog/plan/service.go
  • openmeter/productcatalog/plan/service/plan.go
  • openmeter/productcatalog/plan/service_test.go
  • openmeter/productcatalog/plan_test.go
  • openmeter/productcatalog/planaddon/httpdriver/planaddon.go
  • openmeter/productcatalog/planaddon/service.go
  • openmeter/productcatalog/planaddon/service/planaddon.go
  • openmeter/productcatalog/ratecard.go
  • openmeter/productcatalog/ratecard_test.go
  • openmeter/productcatalog/subscription/http/change.go
  • openmeter/productcatalog/subscription/http/get.go
  • openmeter/productcatalog/subscription/http/migrate.go
  • openmeter/productcatalog/subscription/service.go
  • openmeter/productcatalog/subscription/service/change.go
  • openmeter/productcatalog/subscription/service/migrate.go
  • openmeter/subscription/addon/http/create.go
  • openmeter/subscription/addon/http/get.go
  • openmeter/subscription/addon/http/list.go
  • openmeter/subscription/addon/http/update.go
  • openmeter/subscription/subscriptionspec.go
  • openmeter/subscription/subscriptionspec_test.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • openmeter/productcatalog/plan/plan_test.go
  • openmeter/productcatalog/plan/plan.go
  • openmeter/subscription/subscriptionspec_test.go
  • openmeter/productcatalog/plan/adapter/plan.go
  • openmeter/productcatalog/errors.go
  • openmeter/productcatalog/plan/adapter/adapter_test.go
  • openmeter/productcatalog/subscription/http/get.go
  • openmeter/productcatalog/ratecard.go
  • openmeter/subscription/subscriptionspec.go
  • openmeter/productcatalog/addon/adapter/adapter_test.go
  • openmeter/productcatalog/addon/adapter/addon.go

Comment on lines 411 to 413

// EffectiveFrom defines the time from the Addon is going to be unpublished.
EffectiveTo time.Time `json:"effectiveTo,omitempty"`

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Propagate RejectUnitConfig when archiving the previous version.

The v1 publish handler sets this flag, but the nested ArchiveAddon call at Lines 458-464 omits it. If the new version is representable but the currently active version has unit_config, v1 publish still archives that configured resource instead of rejecting the mutation.

Pass RejectUnitConfig: params.RejectUnitConfig to the nested request and add a regression test for this version-transition case.

🤖 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/productcatalog/addon/service.go` around lines 411 - 413, Update the
nested ArchiveAddon request in the v1 publish flow to pass RejectUnitConfig from
the incoming params, ensuring version transitions reject an active addon with
unit_config when requested. Add a regression test covering a representable new
version replacing an active configured version.

Comment on lines +345 to +348
if params.RejectUnitConfig && add.AsProductCatalogAddon().HasUnitConfig() {
return nil, productcatalog.ErrUnitConfigNotRepresentable
}

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject unit_config in the incoming update payload too.

This check only inspects the existing add-on. A v1 caller can update a clean add-on with params.RateCards containing unit_config; those cards are resolved and then passed to UpdateAddon, allowing v1 to create a resource it cannot represent. Check the incoming rate cards as well, or validate the merged candidate before persisting.

🤖 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/productcatalog/addon/service/addon.go` around lines 345 - 348,
Extend the validation around RejectUnitConfig in the add-on update flow to
inspect incoming params.RateCards for unit_config, not only
add.AsProductCatalogAddon().HasUnitConfig(). Reject the update with
productcatalog.ErrUnitConfigNotRepresentable when either the existing add-on or
the resolved incoming/merged rate-card candidate contains unit_config, before
calling UpdateAddon.

Comment thread openmeter/productcatalog/plan/service.go Outdated
Comment thread openmeter/subscription/addon/http/create.go Outdated
@rolosp
rolosp force-pushed the feat/om-409-exclude-unit-config-from-v1 branch from 5e0a664 to 38c4a3c Compare July 14, 2026 10:43

@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/productcatalog/plan/plan.go (1)

50-55: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: Prefer standard-library slices.ContainsFunc.

This logic works perfectly! However, since the coding guidelines prefer standard-library slices and slices.ContainsFunc is already used for the equivalent check in RateCards.HasUnitConfig(), you might want to use it here for consistency. Feel free to ignore if you prefer lo.SomeBy.

As per coding guidelines: Prefer standard-library slices and maps, or github.com/samber/lo where clearer.

💡 Proposed refactor
-func (p Plan) HasUnitConfig() bool {
-	return lo.SomeBy(p.Phases, func(ph Phase) bool {
-		return ph.RateCards.HasUnitConfig()
-	})
-}
+import "slices" // Make sure to include this in the imports block
+
+func (p Plan) HasUnitConfig() bool {
+	return slices.ContainsFunc(p.Phases, func(ph Phase) bool {
+		return ph.RateCards.HasUnitConfig()
+	})
+}
🤖 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/productcatalog/plan/plan.go` around lines 50 - 55, Optionally
update Plan.HasUnitConfig to use standard-library slices.ContainsFunc instead of
lo.SomeBy, matching the existing RateCards.HasUnitConfig implementation and
project guidelines while preserving the current boolean behavior.

Source: Coding guidelines

🤖 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/productcatalog/plan/plan.go`:
- Around line 50-55: Optionally update Plan.HasUnitConfig to use
standard-library slices.ContainsFunc instead of lo.SomeBy, matching the existing
RateCards.HasUnitConfig implementation and project guidelines while preserving
the current boolean behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7a488c71-582f-4867-af37-7bdfe5582e15

📥 Commits

Reviewing files that changed from the base of the PR and between 5e0a664 and 38c4a3c.

📒 Files selected for processing (36)
  • e2e/v1readsurface_unitconfig_test.go
  • openmeter/productcatalog/addon.go
  • openmeter/productcatalog/addon/adapter/adapter_test.go
  • openmeter/productcatalog/addon/adapter/addon.go
  • openmeter/productcatalog/addon/httpdriver/addon.go
  • openmeter/productcatalog/addon/service.go
  • openmeter/productcatalog/addon/service/addon.go
  • openmeter/productcatalog/errors.go
  • openmeter/productcatalog/http/mapping.go
  • openmeter/productcatalog/plan.go
  • openmeter/productcatalog/plan/adapter/adapter_test.go
  • openmeter/productcatalog/plan/adapter/plan.go
  • openmeter/productcatalog/plan/httpdriver/plan.go
  • openmeter/productcatalog/plan/plan.go
  • openmeter/productcatalog/plan/plan_test.go
  • openmeter/productcatalog/plan/service.go
  • openmeter/productcatalog/plan/service/plan.go
  • openmeter/productcatalog/plan/service_test.go
  • openmeter/productcatalog/plan_test.go
  • openmeter/productcatalog/planaddon/httpdriver/planaddon.go
  • openmeter/productcatalog/planaddon/service.go
  • openmeter/productcatalog/planaddon/service/planaddon.go
  • openmeter/productcatalog/ratecard.go
  • openmeter/productcatalog/ratecard_test.go
  • openmeter/productcatalog/subscription/http/change.go
  • openmeter/productcatalog/subscription/http/get.go
  • openmeter/productcatalog/subscription/http/migrate.go
  • openmeter/productcatalog/subscription/service.go
  • openmeter/productcatalog/subscription/service/change.go
  • openmeter/productcatalog/subscription/service/migrate.go
  • openmeter/subscription/addon/http/create.go
  • openmeter/subscription/addon/http/get.go
  • openmeter/subscription/addon/http/list.go
  • openmeter/subscription/addon/http/update.go
  • openmeter/subscription/subscriptionspec.go
  • openmeter/subscription/subscriptionspec_test.go
🚧 Files skipped from review as they are similar to previous changes (30)
  • openmeter/productcatalog/addon/adapter/addon.go
  • openmeter/productcatalog/subscription/service/migrate.go
  • openmeter/subscription/addon/http/list.go
  • openmeter/productcatalog/subscription/http/change.go
  • openmeter/productcatalog/plan/service_test.go
  • openmeter/productcatalog/subscription/service.go
  • openmeter/productcatalog/plan/plan_test.go
  • openmeter/productcatalog/subscription/http/get.go
  • openmeter/productcatalog/plan_test.go
  • openmeter/subscription/addon/http/get.go
  • openmeter/productcatalog/plan/adapter/adapter_test.go
  • openmeter/productcatalog/addon.go
  • openmeter/productcatalog/errors.go
  • openmeter/subscription/addon/http/create.go
  • openmeter/productcatalog/subscription/http/migrate.go
  • openmeter/subscription/addon/http/update.go
  • openmeter/productcatalog/addon/service/addon.go
  • openmeter/productcatalog/plan.go
  • openmeter/productcatalog/planaddon/service.go
  • openmeter/productcatalog/plan/service/plan.go
  • openmeter/productcatalog/planaddon/service/planaddon.go
  • openmeter/productcatalog/planaddon/httpdriver/planaddon.go
  • openmeter/productcatalog/ratecard.go
  • openmeter/productcatalog/plan/httpdriver/plan.go
  • openmeter/subscription/subscriptionspec.go
  • openmeter/productcatalog/addon/adapter/adapter_test.go
  • e2e/v1readsurface_unitconfig_test.go
  • openmeter/productcatalog/plan/adapter/plan.go
  • openmeter/subscription/subscriptionspec_test.go
  • openmeter/productcatalog/addon/httpdriver/addon.go

@rolosp
rolosp force-pushed the feat/om-409-exclude-unit-config-from-v1 branch from 38c4a3c to 25aeada Compare July 14, 2026 11:39
@rolosp
rolosp force-pushed the feat/om-409-exclude-unit-config-from-v1 branch from 25aeada to 7e28ebf Compare July 14, 2026 13:36
@rolosp
rolosp enabled auto-merge (squash) July 14, 2026 13:41
@rolosp
rolosp merged commit 488d1f1 into main Jul 14, 2026
27 checks passed
@rolosp
rolosp deleted the feat/om-409-exclude-unit-config-from-v1 branch July 14, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/misc Miscellaneous changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants