GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||
GeezerVison is showing github.com — fix(billing): withhold the payer credit and storage pools from callers who cannot manage billing by waleedlatif1 · Pull Request #6567 · simstudioai/sim Conversation
Collaborator
Stacked on #6565 → #6560. Review only this PR's own commits; merge after its parents.
On an org-hosted workspace Baseline notev2 billing does not exist on
Why concealment rather than a role gateBilling authority is not a workspace role: it is Workspace API keys are excludedAn actor-less Keys keep AlsoThe org-wide storage query now runs only after disclosure is authorized; previously it executed for every caller and the result was discarded.
Reverting the guard turns 6 tests red across both the human and workspace-key paths. type-check · biome · 553 tests ·
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
|
There was an error while loading. Please reload this page.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
PR SummaryHigh Risk Overview Adds server-side Makes Reviewed by Cursor Bugbot for commit 79a3486. Configure here. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Greptile SummaryThis PR prevents callers without billing-management authority from receiving payer-level pooled credit and storage data while preserving workspace billing standing.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/billing/application/get-billing-status.ts | Gates payer-pool projection by acting-principal billing authority and defers storage-pool resolution until disclosure is authorized. |
| apps/sim/lib/billing/core/workspace-billing-authority.ts | Implements the existing billing-management policy using canonical workspace payer and organization membership data. |
| apps/sim/lib/api/contracts/v2/billing.ts | Makes payer credit and storage fields nullable and documents their authorization semantics. |
| apps/docs/openapi-v2-billing.json | Regenerates the public billing-status schema to represent withheld payer pools as null. |
| apps/sim/lib/billing/application/billing-use-cases.test.ts | Covers authorized and unauthorized human callers, actor-less workspace keys, standing visibility, and deferred storage queries. |
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[GET billing status] --> B{Principal type}
B -->|Workspace API key| C[Resolve workspace billing status]
C --> D[Return plan, period, and standing]
D --> E[credits = null<br/>storage = null]
B -->|Personal API key| F{Requested workspace?}
F -->|No| G[Resolve caller's account scope]
G --> H[Return account credits and storage]
F -->|Yes| I[Resolve workspace and payer]
I --> J{Can manage payer billing?}
J -->|No| D
J -->|Yes| K[Resolve payer storage pool]
K --> L[Return pooled credits and storage]
Reviews (2): Last reviewed commit: "chore(billing): tidy payer-pool concealm..." | Re-trigger Greptile
Sorry, something went wrong.
There was an error while loading. Please reload this page.
`GET /api/v2/billing/status` resolved the workspace's payer and projected that payer's pooled allowances — credits used, credit limit, credits remaining, and the payer entity's storage usage and quota — to any caller holding only `read` on the workspace, including a personal API key. The payer pool is shared across every workspace that payer funds, and the platform already treats it as privileged: the workspace credit-availability surface computes `canViewPayerPool` from `canManageWorkspaceBilling` and substitutes member-scoped or null figures for everyone else. The new versioned endpoint had no equivalent gate. `credits` and `storage` are now projected only to a caller who may manage the resolved payer's billing: the billed account holder of a personally hosted workspace, an admin of the hosting organization, or a workspace API key, which only a workspace admin can provision. The endpoint stays at `read` so a plain member keeps the plan, period, and standing the workspace UI already shows them, and an exceeded pooled limit still reports as `limit_exceeded` without disclosing the numbers behind it. Both fields are nullable on the wire and in the regenerated OpenAPI spec. The decision lives in the application use case, resolved from canonical workspace state, not in the route: billing authority is payer identity and organization role, which the workspace permission ladder cannot express — a plain workspace `admin` is deliberately not enough.
The first pass gated `credits` and `storage` on billing authority for personal API keys but let a `workspace_api_key` principal through unconditionally, which left the excluded role a way back in. Any workspace `admin` may mint a workspace API key, and a workspace `admin` is deliberately not a billing manager, so an admin who reads `null` as themselves could mint a key and read the full pool with it. On an organization-hosted workspace that pool is the organization's, spanning workspaces the admin has no standing in. Billing authority is payer identity or an organization admin role — a property of a person. A workspace API key is deliberately actor-less, so it can never satisfy it and now reads both fields as `null`. Attributing the key to its creator was rejected: it would launder the same workspace-admin role, it breaks when the creator's authority is revoked while the key lives on, and substituting a key's owner for the acting principal is what the application operation boundary forbids. The reasoning sits in TSDoc at the decision point. The key keeps the plan, period, and standing it needs to monitor a workspace, including `limit_exceeded` and `billing_blocked`. No in-repo caller reads `credits` or `storage` from this endpoint. The payer storage pool is now read only once disclosure is authorized, so a caller who may not see it no longer triggers the query at all.
9667823 to
79a3486
Compare
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@cursor review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 79a3486. Configure here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
1667d3c
into
improvement/v2-route-standardization
There was an error while loading. Please reload this page.
79a3486a
Deployed
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.