Skip to content

feat(subscription addon): v3 assign add-on to a subscription endpoint#4392

Open
borosr wants to merge 12 commits into
mainfrom
feat/attach-subscription-addon-v3
Open

feat(subscription addon): v3 assign add-on to a subscription endpoint#4392
borosr wants to merge 12 commits into
mainfrom
feat/attach-subscription-addon-v3

Conversation

@borosr

@borosr borosr commented May 19, 2026

Copy link
Copy Markdown
Contributor

Add new v3 endpoint to assign an add-on to a subscription

What

Add new V3 endpoint for assign an add-on to a subscription POST /api/v3/openmeter/subscriptions/{subscriptionID}/addons.


Testing

curl --request POST \
  --url http://localhost:8888/api/v3/openmeter/subscriptions/{subscriptionID}/addons \
  --header 'Content-Type: application/json' \
  --data '{
	"name": "addon",
	"quantity": 1,
	"timing": "immediate",
	"addon": {
		"id": "<addonID>"
	}
}'

Summary by CodeRabbit

  • New Features
    • New API endpoint to create subscription add-ons (returns HTTP 201).
    • Create/update requests accept a configurable "timing" field for scheduling operations.
  • Behavior Change
    • Creating an add-on that already exists now returns a conflict error.
  • Validation
    • Add-on name is required; description has a maximum length and is optional.
  • Documentation
    • Listing text updated to use "add-ons" consistently.

@borosr borosr requested a review from tothandras May 19, 2026 22:17
@borosr borosr self-assigned this May 19, 2026
@borosr borosr requested a review from a team as a code owner May 19, 2026 22:17
@borosr borosr added the release-note/ignore Ignore this change when generating release notes label May 19, 2026
@coderabbitai

coderabbitai Bot commented May 19, 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 a POST API to create subscription add‑ons (TypeSpec + model changes), maps requests into the subscription workflow input, implements a create handler that invokes SubscriptionWorkflowService, and wires the workflow service into server routing and config.

Changes

Create Subscription Add-on Feature

Layer / File(s) Summary
API contract and data model
api/spec/packages/aip/src/subscriptions/operations.tsp, api/spec/packages/aip/src/subscriptions/subscriptionaddon.tsp
TypeSpec adds create-subscription-addon POST operation; SubscriptionAddon now explicitly defines name/description and a timing: SubscriptionEditTiming field (create/update visibility); nearby wording change to "add‑ons".
Request and response conversion
api/v3/handlers/subscriptions/subscriptionaddons/convert.go
Adds mapCreateSubscriptionAddonRequestToInput (casts timing, converts labels→metadata) and updates toAPISubscriptionAddon to use apiv3.AddonReference.
Create handler implementation
api/v3/handlers/subscriptions/subscriptionaddons/create.go
Adds handler factory/type aliases, decodes JSON and resolves namespace, maps request to workflow input, calls SubscriptionWorkflowService.AddAddon, and returns 201 with the API model.
Handler interface and dependencies
api/v3/handlers/subscriptions/subscriptionaddons/handler.go
Adds CreateSubscriptionAddon() to exported Handler; concrete handler stores SubscriptionWorkflowService and New accepts that dependency.
Server routing and configuration
api/v3/server/server.go, api/v3/server/routes.go
Config gains SubscriptionWorkflowService with validation; NewServer wires the service into the subscriptionAddons handler; new server route delegates to the create handler.
Openmeter server formatting (cosmetic)
openmeter/server/server.go
Reformatted v3server.Config struct literal alignment only; no behavioral changes.

Sequence Diagram

sequenceDiagram
  participant Client
  participant CreateAddonHandler
  participant SubscriptionAddonService
  participant SubscriptionWorkflowService
  Client->>CreateAddonHandler: POST /subscriptions/{id}/addons (CreateRequest)
  CreateAddonHandler->>CreateAddonHandler: Parse request and resolve namespace
  CreateAddonHandler->>SubscriptionAddonService: List existing add-ons
  alt Add-on exists
    CreateAddonHandler->>SubscriptionWorkflowService: Update existing add-on (workflow)
  else Add-on is new
    CreateAddonHandler->>SubscriptionWorkflowService: AddAddon (workflow)
  end
  SubscriptionWorkflowService-->>CreateAddonHandler: Created/updated add-on
  CreateAddonHandler->>Client: 201 Created + SubscriptionAddon JSON
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

Suggested Labels

release-note/feature

Suggested Reviewers

  • tothandras
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(subscription addon): v3 assign add-on to a subscription endpoint' clearly describes the main change—adding a V3 API endpoint to assign add-ons to subscriptions, which aligns with the comprehensive changeset.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/attach-subscription-addon-v3

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.

@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: 2

🤖 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 `@api/v3/handlers/subscriptions/subscriptionaddons/create.go`:
- Around line 64-76: The handler currently performs an implicit upsert: when an
existing addon (found via lo.Find on subsAdds.Items matching
request.AddonInput.AddonID) is present it calls
SubscriptionWorkflowService.ChangeAddonQuantity but still behaves like a Create
(returns 201). Change this to strict-create behavior: if sAdd is found, do NOT
call ChangeAddonQuantity and instead return a 409 Conflict (with a clear error
message) so clients know the addon already exists; otherwise proceed to call
SubscriptionWorkflowService.AddAddon as before. Ensure the branch that
previously called ChangeAddonQuantity (using
SubscriptionWorkflowService.ChangeAddonQuantity and variables sAdd,
request.SubscriptionID, subscriptionworkflow.ChangeAddonQuantityWorkflowInput)
is removed and replaced by the conflict response, and update any tests or
documentation to reflect the create-only contract.
- Line 87: The operation name passed to httptransport.WithOperationName is
incorrect ("create-plan-addon")—update the call in the subscription addon
handler to use the correct operation name "create-subscription-addon" so
traces/metrics align with the endpoint; locate the
httptransport.WithOperationName invocation in the create subscription addon
handler (the call shown as httptransport.WithOperationName("create-plan-addon"))
and replace the string accordingly.
🪄 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: 1559f8b3-689b-4674-adb5-8920d50634b3

📥 Commits

Reviewing files that changed from the base of the PR and between 7fc84c4 and abb1276.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (9)
  • api/spec/packages/aip/src/subscriptions/operations.tsp
  • api/spec/packages/aip/src/subscriptions/subscriptionaddon.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/subscriptions/subscriptionaddons/convert.go
  • api/v3/handlers/subscriptions/subscriptionaddons/create.go
  • api/v3/handlers/subscriptions/subscriptionaddons/handler.go
  • api/v3/server/routes.go
  • api/v3/server/server.go
  • openmeter/server/server.go

Comment thread api/v3/handlers/subscriptions/subscriptionaddons/create.go Outdated
Comment thread api/v3/handlers/subscriptions/subscriptionaddons/create.go Outdated
@borosr borosr force-pushed the feat/attach-subscription-addon-v3 branch from abb1276 to 5b8f77e Compare May 20, 2026 07:32

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

♻️ Duplicate comments (1)
api/v3/handlers/subscriptions/subscriptionaddons/create.go (1)

64-76: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Create endpoint still behaves like upsert, which conflicts with the declared contract.

Right now, when the add-on already exists, this path updates quantity (ChangeAddonQuantity) and still responds as 201 Created. That makes create-subscription-addon ambiguous for clients. Please either make this strict-create (conflict on existing add-on) or explicitly model upsert semantics and status codes in both spec and handler.

As per coding guidelines, "The declared API should be accurate, in parity with the actual implementation, and easy to understand for the user."

Also applies to: 84-84

🤖 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 `@api/v3/handlers/subscriptions/subscriptionaddons/create.go` around lines 64 -
76, The handler currently upserts by calling
SubscriptionWorkflowService.ChangeAddonQuantity when an existing addon is found;
change this to strict-create semantics by detecting existing addon (the lo.Find
check that returns sAdd) and returning an HTTP 409 Conflict (with a clear
message) instead of calling SubscriptionWorkflowService.ChangeAddonQuantity,
leaving SubscriptionWorkflowService.AddAddon to be called only in the else
branch and returning 201 Created on successful AddAddon; alternatively, if you
prefer upsert semantics, update the API spec and this handler to document/model
upsert and return the appropriate status (e.g., 200/201) consistently—pick one
approach and make the codepaths around ChangeAddonQuantity and AddAddon match
that choice.
🤖 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.

Duplicate comments:
In `@api/v3/handlers/subscriptions/subscriptionaddons/create.go`:
- Around line 64-76: The handler currently upserts by calling
SubscriptionWorkflowService.ChangeAddonQuantity when an existing addon is found;
change this to strict-create semantics by detecting existing addon (the lo.Find
check that returns sAdd) and returning an HTTP 409 Conflict (with a clear
message) instead of calling SubscriptionWorkflowService.ChangeAddonQuantity,
leaving SubscriptionWorkflowService.AddAddon to be called only in the else
branch and returning 201 Created on successful AddAddon; alternatively, if you
prefer upsert semantics, update the API spec and this handler to document/model
upsert and return the appropriate status (e.g., 200/201) consistently—pick one
approach and make the codepaths around ChangeAddonQuantity and AddAddon match
that choice.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a87d802d-712f-436c-9fb8-df1ed4447bea

📥 Commits

Reviewing files that changed from the base of the PR and between abb1276 and 5b8f77e.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (9)
  • api/spec/packages/aip/src/subscriptions/operations.tsp
  • api/spec/packages/aip/src/subscriptions/subscriptionaddon.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/subscriptions/subscriptionaddons/convert.go
  • api/v3/handlers/subscriptions/subscriptionaddons/create.go
  • api/v3/handlers/subscriptions/subscriptionaddons/handler.go
  • api/v3/server/routes.go
  • api/v3/server/server.go
  • openmeter/server/server.go
✅ Files skipped from review due to trivial changes (1)
  • openmeter/server/server.go

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a new POST /api/v3/openmeter/subscriptions/{subscriptionID}/addons endpoint that lets callers assign a published add-on to a running subscription with configurable timing (immediate or next_billing_cycle). It also enriches the existing list/get responses with timeline and rate_cards arrays (including affected_subscription_item_ids) and adds a partial unique index to prevent duplicate addon attachments at the database level.

  • New create.go handler wires through subscriptionWorkflowService.AddAddon, decodes timing/labels, and returns HTTP 201 with the full SubscriptionAddon shape including timeline and rate-card mappings.
  • toAPISubscriptionAddon is updated to accept a SubscriptionView for affected-item-ID computation, and the not-found error for future-scheduled addons is replaced with a Quantity: 0 fallback, fixing the 404-on-next_billing_cycle bug.
  • Repo constraint handling is narrowed to SQLSTATE 23505 only (unique violation), so FK violations on bad addon IDs no longer surface as false-positive 409 conflicts.
  • A new partial unique index (namespace, subscription_id, addon_id) WHERE (deleted_at IS NULL) is added with atlas:nolint MF101 suppression.

Confidence Score: 5/5

Safe to merge; the new endpoint is additive, previously-flagged issues are addressed, and the narrowed constraint-error check correctly distinguishes unique violations from FK violations.

The create endpoint, its convert helpers, the updated list/get handlers, and the repo constraint fix are all straightforward and well-tested by both unit and E2E tests. The atlas:nolint MF101 suppression on the migration was flagged in an earlier review thread and accepted by the team. No new correctness issues were found in this pass.

tools/migrate/migrations/20260623085650_add_subscription_addon_unique_index.up.sql — the nolint suppression means the index will fail at deploy time if duplicate rows exist; the risk was previously acknowledged but no deduplication step was added.

Important Files Changed

Filename Overview
api/v3/handlers/subscriptions/subscriptionaddons/create.go New handler for POST /addons; correctly decodes body, resolves namespace, delegates to workflow service, and returns 201 with the full SubscriptionAddon shape.
api/v3/handlers/subscriptions/subscriptionaddons/convert.go Adds FromAPICreateSubscriptionAddonRequest and enriches toAPISubscriptionAddon with timeline, rate-cards, and affected-item-ID mapping; nil-slice fallbacks for empty arrays are correct.
api/v3/handlers/subscriptions/subscriptionaddons/list.go GetView is now guarded by an early-return when the result set is empty, addressing the prior unconditional DB roundtrip concern.
openmeter/subscription/addon/repo/subscriptionaddon.go Constraint-error handling is now narrowed to SQLSTATE 23505; FK violations (23503) correctly fall through instead of being mapped to a false-positive 409.
tools/migrate/migrations/20260623085650_add_subscription_addon_unique_index.up.sql Adds partial unique index with atlas:nolint MF101; pre-existing data-deduplication risk was flagged in a previous thread and acknowledged by the team.
openmeter/ent/schema/subscription_addon.go Adds the unique partial index definition in the Ent schema matching the migration; OnDelete cascade edge is preserved.
e2e/subscriptionaddons_v3_test.go Good E2E coverage: immediate/next_billing_cycle timing, 409 conflict on duplicate attach, quantity-0 validation, GET and LIST responses all exercised.
api/v3/handlers/subscriptions/subscriptionaddons/convert_test.go Unit tests cover timing conversion, future-scheduled quantity-0 fallback, empty-instance error path, and label round-trip.
api/v3/handlers/subscriptions/subscriptionaddons/handler.go Handler struct extended with subscriptionService and subscriptionWorkflowService; both validated non-nil via the server config.
api/v3/server/server.go SubscriptionWorkflowService added to Config, nil-checked in Validate(), and passed through to the handler constructor.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Client
    participant Handler as create.go Handler
    participant Convert as convert.go
    participant Workflow as subscriptionWorkflowService
    participant SubSvc as subscription.Service
    participant AddonSvc as subscriptionaddon.Service
    participant Repo as subscriptionAddonRepo
    participant DB as PostgreSQL

    Client->>Handler: "POST /subscriptions/{id}/addons"
    Handler->>Convert: FromAPICreateSubscriptionAddonRequest(body)
    Convert-->>Handler: "AddAddonWorkflowInput{AddonID, Quantity, Timing}"
    Handler->>Workflow: AddAddon(ctx, subscriptionID, input)

    Workflow->>Workflow: input.Validate()
    Workflow->>SubSvc: GetView(ctx, subscriptionID)
    SubSvc-->>Workflow: SubscriptionView
    Workflow->>AddonSvc: "List(ctx, ns, {SubscriptionID})"
    AddonSvc-->>Workflow: existing addons

    alt addon already attached (in-memory check)
        Workflow-->>Handler: 409 GenericConflictError
        Handler-->>Client: HTTP 409 Conflict
    end

    Workflow->>Workflow: timing.ValidateForAction + ResolveForSpec
    Workflow->>AddonSvc: Create(ctx, ns, CreateSubscriptionAddonInput)
    AddonSvc->>Repo: Create(ctx, ns, input)
    Repo->>DB: INSERT INTO subscription_addons

    alt unique index violation SQLSTATE 23505
        DB-->>Repo: constraint error
        Repo-->>AddonSvc: GenericConflictError
        AddonSvc-->>Workflow: wrapped conflict error
        Workflow-->>Handler: 409 Conflict
        Handler-->>Client: HTTP 409 Conflict
    end

    DB-->>Repo: NamespacedID
    Repo-->>AddonSvc: NamespacedID
    AddonSvc-->>Workflow: SubscriptionAddon

    Workflow->>Workflow: syncWithAddons restore+apply diffs update subscription
    Workflow->>SubSvc: GetView(ctx, subscriptionID)
    SubSvc-->>Workflow: updated SubscriptionView

    Workflow-->>Handler: SubscriptionView + SubscriptionAddon
    Handler->>Convert: toAPISubscriptionAddon(view, addon)
    Convert->>Convert: compute timeline rate_cards affectedItemIDs
    Convert-->>Handler: apiv3.SubscriptionAddon
    Handler-->>Client: HTTP 201 Created
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Client
    participant Handler as create.go Handler
    participant Convert as convert.go
    participant Workflow as subscriptionWorkflowService
    participant SubSvc as subscription.Service
    participant AddonSvc as subscriptionaddon.Service
    participant Repo as subscriptionAddonRepo
    participant DB as PostgreSQL

    Client->>Handler: "POST /subscriptions/{id}/addons"
    Handler->>Convert: FromAPICreateSubscriptionAddonRequest(body)
    Convert-->>Handler: "AddAddonWorkflowInput{AddonID, Quantity, Timing}"
    Handler->>Workflow: AddAddon(ctx, subscriptionID, input)

    Workflow->>Workflow: input.Validate()
    Workflow->>SubSvc: GetView(ctx, subscriptionID)
    SubSvc-->>Workflow: SubscriptionView
    Workflow->>AddonSvc: "List(ctx, ns, {SubscriptionID})"
    AddonSvc-->>Workflow: existing addons

    alt addon already attached (in-memory check)
        Workflow-->>Handler: 409 GenericConflictError
        Handler-->>Client: HTTP 409 Conflict
    end

    Workflow->>Workflow: timing.ValidateForAction + ResolveForSpec
    Workflow->>AddonSvc: Create(ctx, ns, CreateSubscriptionAddonInput)
    AddonSvc->>Repo: Create(ctx, ns, input)
    Repo->>DB: INSERT INTO subscription_addons

    alt unique index violation SQLSTATE 23505
        DB-->>Repo: constraint error
        Repo-->>AddonSvc: GenericConflictError
        AddonSvc-->>Workflow: wrapped conflict error
        Workflow-->>Handler: 409 Conflict
        Handler-->>Client: HTTP 409 Conflict
    end

    DB-->>Repo: NamespacedID
    Repo-->>AddonSvc: NamespacedID
    AddonSvc-->>Workflow: SubscriptionAddon

    Workflow->>Workflow: syncWithAddons restore+apply diffs update subscription
    Workflow->>SubSvc: GetView(ctx, subscriptionID)
    SubSvc-->>Workflow: updated SubscriptionView

    Workflow-->>Handler: SubscriptionView + SubscriptionAddon
    Handler->>Convert: toAPISubscriptionAddon(view, addon)
    Convert->>Convert: compute timeline rate_cards affectedItemIDs
    Convert-->>Handler: apiv3.SubscriptionAddon
    Handler-->>Client: HTTP 201 Created
Loading

Reviews (5): Last reviewed commit: "fix: double check the constraint error i..." | Re-trigger Greptile

Comment thread api/v3/handlers/subscriptions/subscriptionaddons/list.go
Comment on lines +1 to +3
-- create index "subscriptionaddon_namespace_subscription_id_addon_id" to table: "subscription_addons"
-- atlas:nolint MF101
CREATE UNIQUE INDEX "subscriptionaddon_namespace_subscription_id_addon_id" ON "subscription_addons" ("namespace", "subscription_id", "addon_id") WHERE (deleted_at IS NULL);

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.

P2 atlas:nolint MF101 suppresses data-safety check without a cleanup step

MF101 fires because adding a unique index to an existing table fails at deploy time if there are pre-existing rows that violate the constraint. The v1 API's AddAddon workflow had an application-level duplicate guard, but that guard ran in a separate step before Create, leaving a window where concurrent requests or retries could have inserted duplicates into subscription_addons. A DELETE / UPDATE deduplication CTE before the CREATE UNIQUE INDEX statement (or a pre-migration data audit confirming no duplicates exist) would close this risk and make the nolint suppression unnecessary.

Fix in Claude Code

@borosr borosr force-pushed the feat/attach-subscription-addon-v3 branch from 5fa8a4a to 1c703e3 Compare June 15, 2026 07:54
Comment thread openmeter/subscription/addon/repo/subscriptionaddon.go
Annotations(
entsql.IndexWhere("deleted_at IS NULL"),
).
Unique(),

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.

is it unique? how's quantity handled?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@tothandras what do you think about that? Should we keep this unique or support multiple addon attachment to the same subscription?

@borosr borosr force-pushed the feat/attach-subscription-addon-v3 branch 2 times, most recently from a176b02 to 3bc5ab1 Compare June 23, 2026 13:00
@borosr borosr force-pushed the feat/attach-subscription-addon-v3 branch from cbb2126 to 457539d Compare June 23, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/ignore Ignore this change when generating release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants