-
Notifications
You must be signed in to change notification settings - Fork 24
feat(billing): Chargebee invoicing + PayPal wallet as agent tools (#788, #789, #527) #856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
senamakel
merged 48 commits into
tinyhumansai:main
from
CodeGhost21:feat/788-chargebee-tools
Aug 17, 2026
Merged
Changes from all commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
116afd9
feat(chargebee): billing REST integration and its operations (#788)
CodeGhost21 1fa34d4
feat(chargebee): wire the billing tools into the agent toolbelt (#788)
CodeGhost21 8334e36
feat(chargebee): inbound webhook that tells the operator about paymen…
CodeGhost21 349464d
feat(chargebee): billing config endpoints for the Settings UI (#788, …
CodeGhost21 ab9dbea
feat(console): Settings → Billing page for the Chargebee connection (…
CodeGhost21 e1b01fa
feat(paypal): wallet and transaction REST layer (#789)
CodeGhost21 ebe8fb6
feat(paypal): agent tools, config endpoints and Settings UI (#789)
CodeGhost21 2c7c403
fix(billing): re-resolve credentials per turn and declare the tools (…
CodeGhost21 451fbb3
fix(chargebee): raise the invoice when a site refuses payment terms (…
CodeGhost21 d198d8a
chore: resolve Cargo.lock after merging upstream/main
CodeGhost21 9de03ab
fix(paypal): explain an unavailable transaction window instead of rel…
CodeGhost21 a55c113
fix(billing): gate the harness bridges on their own features (#788, #…
CodeGhost21 769a684
fix(billing): review findings — credential leaks, lax parsing, PII in…
CodeGhost21 694fb36
fix(billing): name the company and agent in the fail-closed warnings
CodeGhost21 c11fdf3
ci(staging): build the tenant image with chargebee and paypal (#788, …
CodeGhost21 1aa7d12
fix(billing): add the gated deps fields to the composio turn test
CodeGhost21 5f395dc
fix(billing): withhold unparseable response bodies, and always send a…
CodeGhost21 0902202
fix(billing): redact the client key, tighten the PayPal error match, …
CodeGhost21 79deeb9
test(billing): pin both fingerprints, and run the PayPal toolbelt tes…
CodeGhost21 e661c7b
fix(billing): finish the no-raw-bodies rule, and drop stale state on …
CodeGhost21 bf02465
fix(billing): authenticate the webhook before its body is read, and c…
CodeGhost21 3b2f29a
fix(billing): wire the gated billing fields at main's new HarnessDeps…
CodeGhost21 c86f9d8
fix(billing): remount BillingView per company so credentials cannot c…
CodeGhost21 6379e34
fix(billing): derive idempotency keys from a stable hash, and make th…
CodeGhost21 f46d045
fix(console): import CompanyFeed from its real module in the billing …
CodeGhost21 0d2efa9
fix(paypal): reject malformed transaction responses (#789)
oxoxDev 5c5dc04
fix(deps): restore the tinymemory version main already locked
oxoxDev 5d61f3f
Merge branch 'main' into feat/788-chargebee-tools
oxoxDev 4f1405f
fix(paypal): never trust a token past its own expiry, and stop derivi…
oxoxDev 7874c54
merge: main into feat/788-chargebee-tools
oxoxDev d93df1a
fix(harness): set the billing deps on main's workflow-build fixture
oxoxDev 9a74267
fix(paypal): refuse a request path that could move the host (#856)
oxoxDev 0ab81fd
fix(paypal): refuse a missing amount rather than reporting it as 0.00…
oxoxDev 90097d4
fix(billing): apply credential writes as a batch that rolls back on f…
oxoxDev 3b9186b
test(chargebee): assert a verified webhook actually raises the compan…
oxoxDev d7cd799
Merge remote-tracking branch 'upstream/main' into feat/788-chargebee-…
CodeGhost21 b3032e1
fix(billing-view): load Chargebee and PayPal independently (#856)
oxoxDev 988c9af
test(billing-view): cover the load-failure and status branches (#856)
oxoxDev f7dbbd6
test(harness): cover per-company billing credential resolution (#856)
oxoxDev 4650393
Merge remote-tracking branch 'codeghost/feat/788-chargebee-tools' int…
oxoxDev e4c0cb4
fix(billing): add the new CompanyRecord field to the test fixture (#856)
oxoxDev 939e64a
fix(workflows): repair the gated-lane fixtures main left behind (#856)
oxoxDev 9b2f8a4
fix(harness): gate the billing test fixture on its features (#856)
CodeGhost21 45bb956
Merge remote-tracking branch 'refs/remotes/upstream/main' into pr/856
senamakel 494d720
fix(api): handle null values in chargebee API response
senamakel 4bb091f
fix(api): handle null values in chargebee API response
senamakel 86af3ac
fix(api): handle null values in chargebee API response
senamakel 08bdd79
fix(test): remove unnecessary braces in async block
senamakel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| // The Chargebee billing configuration API (issue #788, UI tracked in #527). | ||
| // | ||
| // Credentials are write-only: the API key and the webhook credential are sent | ||
| // on save and stored in the host's secret store; neither is ever returned. The | ||
| // read shape carries booleans and the (non-secret) site identifier only, so | ||
| // there is no field on this type that could leak a key into a rendered page. | ||
| // | ||
| // Standalone functions over the shared client, mirroring `api/mcp.ts` and | ||
| // `api/skills.ts`, so `OpenCompanyClient` needs no new methods. | ||
|
|
||
| import type { OpenCompanyClient } from "./client"; | ||
|
|
||
| /** | ||
| * The non-secret view of a company's Chargebee configuration. | ||
| * | ||
| * Four separate flags rather than one `connected`, because they fail | ||
| * differently and a single boolean sends an operator to the wrong place for | ||
| * three of them — see `BillingView` for how each is worded. | ||
| */ | ||
| export interface BillingStatus { | ||
| /** Whether an API key is stored. Never the key. */ | ||
| apiKeyConfigured: boolean; | ||
| /** The Chargebee site slug, e.g. `acme-test`. Not secret. */ | ||
| site: string | null; | ||
| /** Whether a webhook credential is stored. */ | ||
| webhookConfigured: boolean; | ||
| /** The URL to paste into Chargebee, or null on a host with no public URL. */ | ||
| webhookUrl: string | null; | ||
| /** Whether the company's manifest explicitly grants `chargebee`. */ | ||
| granted: boolean; | ||
| /** Whether the `chargebee` feature is compiled into the running host. */ | ||
| inBuild: boolean; | ||
| } | ||
|
|
||
| /** The write-only save body. Omitted fields keep their stored value. */ | ||
| export interface BillingConfig { | ||
| /** Write-only. Omit to leave the stored key unchanged. */ | ||
| apiKey?: string; | ||
| /** The site identifier; accepts a bare slug, a host, or a full URL. */ | ||
| site?: string; | ||
| /** Write-only `username:password` pair. Omit to leave it unchanged. */ | ||
| webhookSecret?: string; | ||
| } | ||
|
|
||
| /** Reads the company's Chargebee configuration status. */ | ||
| export async function getBilling( | ||
| client: OpenCompanyClient, | ||
| company: string | null, | ||
| ): Promise<BillingStatus> { | ||
| return client.get<BillingStatus>(`${client.scopeFor(company)}/billing/chargebee`); | ||
| } | ||
|
|
||
| /** | ||
| * Saves whatever is supplied, and returns the resulting status. | ||
| * | ||
| * A patch, not a replace: the host applies only the fields present and | ||
| * non-empty, so correcting the site never means re-typing the API key — which | ||
| * an operator cannot do anyway, since it is never shown back to them. | ||
| */ | ||
| export async function saveBilling( | ||
| client: OpenCompanyClient, | ||
| company: string | null, | ||
| config: BillingConfig, | ||
| ): Promise<BillingStatus> { | ||
| return client.put<BillingStatus>(`${client.scopeFor(company)}/billing/chargebee`, config); | ||
| } | ||
|
|
||
| /** Clears every stored Chargebee credential. */ | ||
| export async function clearBilling( | ||
| client: OpenCompanyClient, | ||
| company: string | null, | ||
| ): Promise<BillingStatus> { | ||
| return client.del<BillingStatus>(`${client.scopeFor(company)}/billing/chargebee/key`); | ||
|
CodeGhost21 marked this conversation as resolved.
|
||
| } | ||
|
oxoxDev marked this conversation as resolved.
|
||
|
|
||
| /** The non-secret view of a company's PayPal connection (issue #789). */ | ||
| export interface PaypalStatus { | ||
| /** Whether a client id is stored. Never the id. */ | ||
| clientIdConfigured: boolean; | ||
| /** Whether a client secret is stored. */ | ||
| clientSecretConfigured: boolean; | ||
| /** `sandbox` or `live` — which PayPal world the credentials belong to. */ | ||
| environment: string; | ||
| /** Whether the company's manifest explicitly grants `paypal`. */ | ||
| granted: boolean; | ||
| /** Whether the `paypal` feature is compiled into the running host. */ | ||
| inBuild: boolean; | ||
| } | ||
|
|
||
| /** The write-only PayPal save body. Omitted fields keep their stored value. */ | ||
| export interface PaypalConfig { | ||
| clientId?: string; | ||
| clientSecret?: string; | ||
| /** `sandbox` or `live`; anything else is stored as `sandbox`. */ | ||
| environment?: string; | ||
| } | ||
|
|
||
| /** Reads the company's PayPal configuration status. */ | ||
| export async function getPaypal( | ||
| client: OpenCompanyClient, | ||
| company: string | null, | ||
| ): Promise<PaypalStatus> { | ||
| return client.get<PaypalStatus>(`${client.scopeFor(company)}/billing/paypal`); | ||
| } | ||
|
|
||
| /** Saves whatever is supplied, and returns the resulting status. */ | ||
| export async function savePaypal( | ||
| client: OpenCompanyClient, | ||
| company: string | null, | ||
| config: PaypalConfig, | ||
| ): Promise<PaypalStatus> { | ||
| return client.put<PaypalStatus>(`${client.scopeFor(company)}/billing/paypal`, config); | ||
| } | ||
|
|
||
| /** Clears the stored PayPal credentials and resets the environment. */ | ||
| export async function clearPaypal( | ||
| client: OpenCompanyClient, | ||
| company: string | null, | ||
| ): Promise<PaypalStatus> { | ||
| return client.del<PaypalStatus>(`${client.scopeFor(company)}/billing/paypal/key`); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.