feat(entitlement): allow grants on subscription-managed entitlements#4206
feat(entitlement): allow grants on subscription-managed entitlements#4206ankitk0305 wants to merge 3 commits into
Conversation
Bitnami stopped publishing versioned images to Docker Hub in Nov 2024. Override image.registry for kafka, postgresql, and redis sub-charts to pull from registry.bitnami.com where the versioned tags remain available. Fixes openmeterio#4172 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Supersedes the previous registry.bitnami.com override approach, which CodeRabbit correctly identified as non-functional (registry.bitnami.com is not publicly accessible). Root cause: old Bitnami chart versions (kafka@30.1.8, postgresql@16.1.2, redis@20.2.1) pin image tags that have been removed from Docker Hub. Newer Bitnami chart versions pin up-to-date tags that are still public. Bumps: kafka: 30.1.8 → 32.4.4 (Kafka 4.0.0) postgresql: 16.1.2 → 17.1.0 (PostgreSQL 17.6.0) redis: 20.2.1 → 23.1.1 (Redis 8.2.1) Chart.lock digest placeholder — run `helm dependency update deploy/charts/openmeter` to regenerate the lock file with correct digests. Fixes openmeterio#4172 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes openmeterio#3293 Grants are ad-hoc credit top-ups (e.g. one-time overage allowances) that do not alter the entitlement structure owned by a subscription. The previous blanket PreUpdate guard blocked them with a 403, forcing users to work around the restriction via raw entitlements instead. Changes: - subscription/context.go: add NewGrantOperationContext / IsGrantOperation so callers can mark a context as a grant operation - entitlement/hooks/subscription/hook.go: PreUpdate now allows the operation when IsGrantOperation(ctx) is true, in addition to the existing IsSubscriptionOperation bypass - entitlement/metered/entitlement_grant.go: CreateGrant wraps ctx with NewGrantOperationContext before calling PreUpdate Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughHelm chart dependencies updated to newer versions (Kafka 32.4.4, PostgreSQL 17.1.0, Redis 23.1.1). Concurrently, context utilities added and subscription hook modified to allow grant operations on subscription-managed entitlements by bypassing prior restrictions. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
openmeter/entitlement/hooks/subscription/hook.go (1)
44-58: Works as intended — one small asymmetry worth thinking about.
PreUpdatenow lets grants through on subscription-managed entitlements, butPreDeletedoesn't have (and shouldn't need) a grant bypass. That's fine today because grants go throughPreUpdate, but the bypass as written is unconditional — it returnsnilfor grant operations even on entitlements that aren't subscription-managed, which is harmless but makes the guard a no-op for the entire grant path. If you ever add non-subscription validations here later, remember that grant ops will skip them too.A slightly more surgical version would keep the guard's scope unchanged:
♻️ Optional: only bypass when the restriction would actually fire
- // Grants are ad-hoc credit top-ups and do not alter the entitlement structure, - // so they are permitted even when the entitlement is subscription-managed. - if subscription.IsGrantOperation(ctx) { - return nil - } - - if subscription.AnnotationParser.HasSubscription(ent.Annotations) { + if subscription.AnnotationParser.HasSubscription(ent.Annotations) { + // Grants are ad-hoc credit top-ups and don't alter the entitlement + // structure managed by the subscription, so allow them through. + if subscription.IsGrantOperation(ctx) { + return nil + } return models.NewGenericForbiddenError(fmt.Errorf("entitlement is managed by subscription")) }Totally a judgment call — current form is readable too.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@openmeter/entitlement/hooks/subscription/hook.go` around lines 44 - 58, PreUpdate unconditionally lets grant operations through even for entitlements that aren't subscription-managed; narrow the bypass by only returning nil for grants when the entitlement is subscription-managed. Update the logic in the hook.PreUpdate function (and reference subscription.IsGrantOperation and subscription.AnnotationParser.HasSubscription and models.NewGenericForbiddenError) so the grant early-return is conditional on HasSubscription(ent.Annotations) (e.g. check HasSubscription first or combine conditions) and keep the existing forbidden error for subscription-managed entitlements otherwise.openmeter/subscription/context.go (1)
29-37: LGTM — clean, symmetric with the subscription-operation helpers. 🙌Nice touch making
IsGrantOperationthe slightly tidierok && uform; consider givingIsSubscriptionOperationthe same one-liner treatment in a follow-up for consistency. Totally optional.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@openmeter/subscription/context.go` around lines 29 - 37, The reviewer suggests making IsSubscriptionOperation consistent with IsGrantOperation by adopting the concise one-liner style; update the IsSubscriptionOperation function to use the same pattern (use ctx.Value(subscriptionoperation).(bool) and return ok && v) so both helpers (NewSubscriptionOperationContext/IsSubscriptionOperation and NewGrantOperationContext/IsGrantOperation) have symmetric, tidy implementations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@deploy/charts/openmeter/Chart.yaml`:
- Around line 22-32: Update the Helm chart values and documentation to account
for Kafka chart breaking changes: in your values.yaml replace any
kafka.extraConfig keys with kafka.overrideConfiguration (YAML block format),
switch references from the removed $CLIENT_CONF environment variable to using
/shared/client.properties, and review kafka controller quorum-related settings
for any needed adjustments; also verify that postgresql and redis usage aligns
with version bumps (Postgres 16→17 may require data migration workflows) and
scan each chart CHANGELOG for any other values.yaml key renames or image-pull
registry changes before merging.
---
Nitpick comments:
In `@openmeter/entitlement/hooks/subscription/hook.go`:
- Around line 44-58: PreUpdate unconditionally lets grant operations through
even for entitlements that aren't subscription-managed; narrow the bypass by
only returning nil for grants when the entitlement is subscription-managed.
Update the logic in the hook.PreUpdate function (and reference
subscription.IsGrantOperation and subscription.AnnotationParser.HasSubscription
and models.NewGenericForbiddenError) so the grant early-return is conditional on
HasSubscription(ent.Annotations) (e.g. check HasSubscription first or combine
conditions) and keep the existing forbidden error for subscription-managed
entitlements otherwise.
In `@openmeter/subscription/context.go`:
- Around line 29-37: The reviewer suggests making IsSubscriptionOperation
consistent with IsGrantOperation by adopting the concise one-liner style; update
the IsSubscriptionOperation function to use the same pattern (use
ctx.Value(subscriptionoperation).(bool) and return ok && v) so both helpers
(NewSubscriptionOperationContext/IsSubscriptionOperation and
NewGrantOperationContext/IsGrantOperation) have symmetric, tidy implementations.
🪄 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: d1d598f5-60dc-4175-9cfe-d542748a8594
⛔ Files ignored due to path filters (1)
deploy/charts/openmeter/Chart.lockis excluded by!**/*.lock,!**/*.lock
📒 Files selected for processing (4)
deploy/charts/openmeter/Chart.yamlopenmeter/entitlement/hooks/subscription/hook.goopenmeter/entitlement/metered/entitlement_grant.goopenmeter/subscription/context.go
| version: "32.4.4" | ||
| repository: "oci://registry-1.docker.io/bitnamicharts" | ||
| condition: kafka.enabled | ||
| - name: postgresql | ||
| version: "16.1.2" | ||
| version: "17.1.0" | ||
| repository: "oci://registry-1.docker.io/bitnamicharts" | ||
| condition: postgresql.enabled | ||
| - name: redis | ||
| version: "20.2.1" | ||
| version: "23.1.1" | ||
| repository: "oci://registry-1.docker.io/bitnamicharts" | ||
| condition: redis.enabled |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
bitnami helm chart kafka 32.0.0 breaking changes upgrade notes
💡 Result:
The Bitnami Kafka Helm chart version 32.0.0, released on 2025-03-25, introduces several breaking changes primarily due to the upgrade to Apache Kafka 4.0.0, which fully transitions to KRaft mode (no ZooKeeper dependency). Official upgrade notes are documented in the chart's repository at https://github.com/bitnami/charts/tree/main/bitnami/kafka#to-3200 (referenced in issues). Key breaking changes and upgrade considerations: 1. extraConfig parameter removed: Replaced by overrideConfiguration. Migrate any extraConfig settings (e.g., ACLs like allow.everyone.if.no.acl.found=true) to overrideConfiguration in YAML format: overrideConfiguration: allow.everyone.if.no.acl.found: true authorizer.class.name: org.apache.kafka.metadata.authorizer.StandardAuthorizer super.users: "User:admin;User:controller_user;User:inter_broker_user" Source: GitHub issue #33873. 2. Provisioning command changes: $CLIENT_CONF environment variable removed; use /shared/client.properties instead in extraProvisioningCommands. 3. KRaft secret handling issues: Early 32.0.x versions (e.g., 32.0.1-32.0.2) had upgrade bugs where templates expected controller-{i}-id keys in kafka-kraft secret that weren't present, causing "PASSWORDS ERROR". Fixed in later patches (e.g., PR #32621). Upgrade to at least 32.0.3+ or latest (32.4.3 as of 2025-08-26). 4. Controller quorum configuration: Upgrades from 31.x may fail due to switch from controller.quorum.voters (static, kraft.version=0) to controller.quorum.bootstrap.servers (dynamic, kraft.version=1). Kafka 4.0 does not support automatic migration between static/dynamic quorums. Use new kraftVersion parameter (added in 32.3.0) to set static quorum if needed. Avoid setting kraft.version: 1 manually in overrideConfiguration during upgrade. 5. General upgrade steps: - Review your values.yaml for deprecated params. - Backup cluster data and secrets. - Test upgrade in staging: helm upgrade --install kafka oci://registry-1.docker.io/bitnamicharts/kafka --version 32.4.3 -f values.yaml. - Monitor pods/secrets post-upgrade. - Latest chart uses Kafka image docker.io/bitnami/kafka:4.0.0-debian-12-r10. Current latest version is 32.4.3 (2025-08-26). Always check CHANGELOG.md and README.md in the repo for full details. Primary sources: CHANGELOG.md, issues #33873, #32620, #34015, #32516.
Citations:
- 1: https://github.com/bitnami/charts/blob/HEAD/bitnami/kafka/CHANGELOG.md
- 2: [bitnami/kafka] Undocumented breaking changes from 31.* to 32.* bitnami/charts#33873
- 3: Kafka Chart Cannot Be Upgraded bitnami/charts#32620
- 4: [bitnam/kafka] Helm upgrade failed bitnami/charts#32635
- 5: [bitnami/kafka] Bitnami Kafka upgrade from chart 31.4.0 to 32.2.8 fails due to controller.quorum config mismatch bitnami/charts#34015
- 6: [bitnami/kafka] feat: Kafka 4.0.0 bitnami/charts#32516
- 7: https://github.com/bitnami/charts/blob/main/bitnami/kafka/README.md
🌐 Web query:
bitnami helm chart postgresql 17.0.0 breaking changes upgrade notes
💡 Result:
No specific breaking changes or dedicated upgrade notes found for Bitnami PostgreSQL Helm chart version 17.0.0 in the official CHANGELOG.md or Chart.yaml. The current latest chart version is 17.1.0 (appVersion PostgreSQL 17.6.0), with prior versions including 17.0.1 and 17.0.2 noted in CHANGELOG.md. Changes around these versions are minor: configurable data source credentials for exporter, primary.service.enabled parameter, README updates, annotations removal, and metrics collection as postgres user. No explicit breaking changes listed. For upgrades involving PostgreSQL major version changes (e.g., to PG 17), the data directory incompatibility requires manual intervention: backup data, potentially delete StatefulSet with orphan pods, upgrade Helm release reusing existing PVC, and use pg_upgrade or pg_dump/pg_restore if needed. See official README upgrading sections for prior major versions (e.g., to 16.x, 15.x) which follow similar patterns, and GitHub issues #14926, #4468 for procedures. Always backup before upgrading.
Citations:
- 1: https://github.com/bitnami/charts/blob/main/bitnami/postgresql/CHANGELOG.md
- 2: https://github.com/bitnami/charts/blob/main/bitnami/postgresql/Chart.yaml
- 3: https://github.com/bitnami/charts/blob/466dbcda/bitnami/postgresql/Chart.yaml
- 4: https://github.com/bitnami/charts/tree/main/bitnami/postgresql
- 5: [bitnami/postgresql] Better documentation needed on major version upgrades bitnami/charts#14926
- 6: https://medium.com/@andrea.berlingieri42/upgrading-a-postgresql-bitnami-helm-release-11-to-15-2ca447b4580d
- 7: [bitnami/postgresql-ha] upgrade to helm chart version 11.9.8 triggers PostgreSQL major version bump 15=>16 bitnami/charts#19596
- 8: [bitnami/postgresql] Upgrade from 9.8.12 to 10.1.0 failed bitnami/charts#4468
🌐 Web query:
bitnami helm chart redis 23.0.0 breaking changes upgrade notes
💡 Result:
No breaking changes or specific upgrade notes are documented for Bitnami Redis Helm chart version 23.0.0. The official CHANGELOG.md lists patch releases starting from 23.0.1 (2025-09-05) with bugfixes and minor updates like README changes, sentinel fixes, and dependency updates. Earlier commits around August 2025 include multiple dependency updates and fixes for sentinel with single replica, but no explicit "breaking changes" or major upgrade warnings for 23.0.0. General upgrade advice from the chart README: reuse existing secrets or update auth.password/auth.existingSecret. Current latest version is 23.1.1 (appVersion Redis 8.2.1). Review full CHANGELOG at https://github.com/bitnami/charts/blob/main/bitnami/redis/CHANGELOG.md and test upgrades in staging.
Citations:
- 1: https://github.com/bitnami/charts/blob/HEAD/bitnami/redis/CHANGELOG.md
- 2: https://github.com/bitnami/charts/blob/main/bitnami/redis/CHANGELOG.md
- 3: https://github.com/bitnami/charts/commits/main/bitnami/redis
- 4: https://github.com/bitnami/charts/blob/main/bitnami/redis/Chart.yaml
- 5: https://github.com/bitnami/charts/tree/main/bitnami/redis
🏁 Script executed:
# Let me gather the current chart version you're upgrading to for Kafka to confirm patch level
grep -A2 "name: kafka" deploy/charts/openmeter/Chart.yamlRepository: openmeterio/openmeter
Length of output: 161
Kafka chart has documented breaking changes—worth reviewing your values.yaml before merge.
Good news: you're hitting Kafka 32.4.4, which sidesteps the critical KRaft secret bugs in early 32.0.x. But there ARE config migrations needed:
extraConfig→overrideConfiguration(YAML format now, not flat strings)$CLIENT_CONFenv var removed; switch to/shared/client.properties- Controller quorum config may need updates depending on your current setup
PostgreSQL 16→17 and Redis 20→23 don't have chart-level breaking changes, though note that Postgres major version upgrades do require the usual database data directory migration (backup + pg_upgrade or pg_dump/restore path).
Worth a quick scan of each chart's CHANGELOG to spot any values.yaml key renames or security defaults that might affect your setup. Also fair game to spot-check that image pulls still resolve in any air-gapped registries you're using.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@deploy/charts/openmeter/Chart.yaml` around lines 22 - 32, Update the Helm
chart values and documentation to account for Kafka chart breaking changes: in
your values.yaml replace any kafka.extraConfig keys with
kafka.overrideConfiguration (YAML block format), switch references from the
removed $CLIENT_CONF environment variable to using /shared/client.properties,
and review kafka controller quorum-related settings for any needed adjustments;
also verify that postgresql and redis usage aligns with version bumps (Postgres
16→17 may require data migration workflows) and scan each chart CHANGELOG for
any other values.yaml key renames or image-pull registry changes before merging.
|
Hi @ankitk0305 The subscription system works by "closing" and "recreating" entitlements according to subscription / addon changes. This is partly due to the limitations of the current entitlement-grant system. Manual granting is disabled on subscription managed entitlements because the two systems cannot currently reconcile and the results would be confusing to the end user: let's say, you add a manual grant of +100. On the next subscription edit (or any general "change type event"), that 100 grant would be lost with the closed entitlement. |
|
On a related note, if you check recent activity in the repo, the first version of the new credit system is close to its first release, that will be a better solution for most usecases. |
Problem
Fixes #3293
Users cannot apply grants (one-time credit top-ups) to entitlements that are managed by a subscription. The
PreUpdatehook in the subscription guard returns a403 Forbiddenfor any external modification of a subscription-managed entitlement, including grant creation.This forces users into a poor workaround: abandoning subscriptions entirely and managing entitlements + grants manually with raw entitlements.
Use case
A customer has a subscription plan that grants 100 API calls/month. They exceed their limit and the operator wants to add a one-time overage grant of 50 extra calls — without changing the subscription plan or creating a recurring add-on. This is a natural billing pattern that should be supported.
Root Cause
In
openmeter/entitlement/hooks/subscription/hook.go,PreUpdateblocks all external mutations on subscription-managed entitlements:CreateGrantinentitlement/metered/entitlement_grant.gocalls this hook before creating the grant, so every grant attempt on a subscription-managed entitlement is rejected.Solution
Grants are ad-hoc credit top-ups — they do not alter the entitlement structure (type, feature key, config) that the subscription owns. The guard should distinguish between structural mutations (still blocked) and grant creation (now allowed).
The fix follows the existing
IsSubscriptionOperationcontext pattern:subscription/context.go— addNewGrantOperationContext/IsGrantOperationto mark a context as a grant operationentitlement/hooks/subscription/hook.go—PreUpdatepasses through whenIsGrantOperation(ctx)is trueentitlement/metered/entitlement_grant.go—CreateGrantwrapsctxwithNewGrantOperationContextbefore callingPreUpdateChanges
Invariants preserved:
IsSubscriptionOperationbypass for the subscription subsystem itself is unchangedTest Plan
POST /api/v2/customers/{id}/entitlements/{featureKey}/grants— should return200instead of403GET .../grants403)make testSummary by CodeRabbit
Chores
New Features