Skip to content

feat: add deriveHostedDbPlan function to manage subscription levels#1768

Merged
Artuomka merged 1 commit into
mainfrom
backend_stripe_proxy_usage_reports
May 13, 2026
Merged

feat: add deriveHostedDbPlan function to manage subscription levels#1768
Artuomka merged 1 commit into
mainfrom
backend_stripe_proxy_usage_reports

Conversation

@Artuomka
Copy link
Copy Markdown
Collaborator

@Artuomka Artuomka commented May 13, 2026

Summary by CodeRabbit

  • Tests
    • Enhanced mock API to return plan information in connection responses, enabling improved testing of subscription-related scenarios
    • Refactored mock API structure for better maintainability

Review Change Stack

Copilot AI review requested due to automatic review settings May 13, 2026 14:34
@Artuomka Artuomka enabled auto-merge May 13, 2026 14:34
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

📝 Walkthrough

Walkthrough

The mock proxy API server now derives a hostedDbPlan value from currentSubscriptionLevel and includes it in the GET /api/proxy/connections response. The derivation handles frozen states and plan aliases, and subscription-level updates remain runtime-configurable via test endpoints. Existing endpoints and authentication behavior are unchanged.

Changes

Mock API Plan Derivation

Layer / File(s) Summary
Plan derivation and connection setup
test/proxy-mock-api/server.js
ID derivation functions and new deriveHostedDbPlan() function map currentSubscriptionLevel to hostedDbPlan, handling frozen, TEST_TINY_PLAN, and free-plan aliases; TEST_CONNECTION template and configurable currentSubscriptionLevel state initialize.
Connections endpoint with plan computation
test/proxy-mock-api/server.js
GET /api/proxy/connections endpoint computes hostedDbPlan from currentSubscriptionLevel and includes it in the response JSON and success-path log message.
Test endpoints and remaining handlers
test/proxy-mock-api/server.js
Routes for /healthz, subscription-level updates (PUT /api/test/subscription-level), usage-report management (POST/GET/DELETE /api/test/usage-reports), usage endpoint (POST /api/proxy/usage), 404 fallback, and server startup remain unchanged semantically.

🎯 3 (Moderate) | ⏱️ ~20 minutes

A rabbit hops through plans so fine,
Frozen states and tiers align,
Hosted DB plans now derive with grace,
From subscriptions in their rightful place, 🐰✨

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding a deriveHostedDbPlan function to manage subscription levels in the mock API server, as confirmed by the summary showing hostedDbPlan derivation from currentSubscriptionLevel.
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.
Security Check ✅ Passed Safe string comparisons, no injection vulnerabilities, proper JSON encoding, authentication maintained, no new attack vectors or security regressions.

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

✨ 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 backend_stripe_proxy_usage_reports

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 `@test/proxy-mock-api/server.js`:
- Around line 14-22: Convert the function declaration deriveCompanyId into a
const arrow function (const deriveCompanyId = (username) => { ... }) and do the
same for the other helper function declarations flagged in this file (the two
other helpers noted in the review); preserve the existing logic, return values
and any references/exports, and ensure you don't rely on hoisting (move
declarations earlier if they are used before definition).
- Around line 74-83: The unguarded JSON.parse in the PUT handler for
'/api/test/subscription-level' can throw on malformed input; wrap the body
parsing/JSON.parse in a try/catch inside the req.on('end') callback, and on
catch respond with res.writeHead(400, { 'Content-Type': 'application/json' })
and res.end(JSON.stringify({ ok: false, error: 'Invalid JSON' })) so the server
doesn't crash; on success continue to set currentSubscriptionLevel and return
the existing 200 response.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bfd1474a-9581-4153-9ec9-f8a17c3dc51b

📥 Commits

Reviewing files that changed from the base of the PR and between d02438c and 5842558.

📒 Files selected for processing (1)
  • test/proxy-mock-api/server.js

Comment on lines 14 to 22
function deriveCompanyId(username) {
// Single-username case (e.g. plain "proxy_user") keeps the legacy id so existing
// tests/clients that don't randomize still hit a stable companyId.
if (username === PROXY_USERNAME_PREFIX) {
return 'test-company-001';
}
const hash = crypto.createHash('sha1').update(username).digest('hex').slice(0, 12);
return `test-company-${hash}`;
// Single-username case (e.g. plain "proxy_user") keeps the legacy id so existing
// tests/clients that don't randomize still hit a stable companyId.
if (username === PROXY_USERNAME_PREFIX) {
return 'test-company-001';
}
const hash = crypto.createHash('sha1').update(username).digest('hex').slice(0, 12);
return `test-company-${hash}`;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Align helper declarations with arrow-function guideline.

These helpers are currently function declarations; convert them to const arrow functions for guideline compliance.

Proposed refactor
-function deriveCompanyId(username) {
+const deriveCompanyId = (username) => {
 	// Single-username case (e.g. plain "proxy_user") keeps the legacy id so existing
 	// tests/clients that don't randomize still hit a stable companyId.
 	if (username === PROXY_USERNAME_PREFIX) {
 		return 'test-company-001';
 	}
 	const hash = crypto.createHash('sha1').update(username).digest('hex').slice(0, 12);
 	return `test-company-${hash}`;
-}
+};

-function deriveConnectionId(username) {
+const deriveConnectionId = (username) => {
 	if (username === PROXY_USERNAME_PREFIX) {
 		return 'test-connection-001';
 	}
 	const hash = crypto.createHash('sha1').update(username).digest('hex').slice(0, 12);
 	return `test-connection-${hash}`;
-}
+};

-function deriveHostedDbPlan(level) {
+const deriveHostedDbPlan = (level) => {
 	if (level === 'frozen') return 'frozen';
 	if (level === 'TEST_TINY_PLAN') return 'TEST_TINY_PLAN';
 	if (level === 'HOSTED_DB_FREE' || level === 'FREE_PLAN') return 'HOSTED_DB_FREE';
 	return 'HOSTED_DB_PAID';
-}
+};
As per coding guidelines, "Prefer arrow functions over function declarations".

Also applies to: 24-30, 53-58

🤖 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 `@test/proxy-mock-api/server.js` around lines 14 - 22, Convert the function
declaration deriveCompanyId into a const arrow function (const deriveCompanyId =
(username) => { ... }) and do the same for the other helper function
declarations flagged in this file (the two other helpers noted in the review);
preserve the existing logic, return values and any references/exports, and
ensure you don't rely on hoisting (move declarations earlier if they are used
before definition).

Comment on lines +74 to +83
if (req.method === 'PUT' && parsedUrl.pathname === '/api/test/subscription-level') {
let body = '';
req.on('data', (chunk) => (body += chunk));
req.on('end', () => {
const parsed = JSON.parse(body);
currentSubscriptionLevel = parsed.subscriptionLevel;
console.log(`[mock-api] Subscription level changed to: ${currentSubscriptionLevel}`);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ok: true, subscriptionLevel: currentSubscriptionLevel }));
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle malformed JSON explicitly in subscription-level endpoint.

JSON.parse(body) on Line 78 is unguarded; malformed input can throw and break this request path. Return a 400 with an error payload instead.

Proposed fix
 	if (req.method === 'PUT' && parsedUrl.pathname === '/api/test/subscription-level') {
 		let body = '';
 		req.on('data', (chunk) => (body += chunk));
 		req.on('end', () => {
-			const parsed = JSON.parse(body);
-			currentSubscriptionLevel = parsed.subscriptionLevel;
-			console.log(`[mock-api] Subscription level changed to: ${currentSubscriptionLevel}`);
-			res.writeHead(200, { 'Content-Type': 'application/json' });
-			res.end(JSON.stringify({ ok: true, subscriptionLevel: currentSubscriptionLevel }));
+			try {
+				const parsed = JSON.parse(body);
+				currentSubscriptionLevel = parsed.subscriptionLevel;
+				console.log(`[mock-api] Subscription level changed to: ${currentSubscriptionLevel}`);
+				res.writeHead(200, { 'Content-Type': 'application/json' });
+				res.end(JSON.stringify({ ok: true, subscriptionLevel: currentSubscriptionLevel }));
+			} catch (e) {
+				res.writeHead(400, { 'Content-Type': 'application/json' });
+				res.end(JSON.stringify({ error: 'Invalid JSON body' }));
+			}
 		});
 		return;
 	}
As per coding guidelines, "Ensure all error handling is explicit - use try/catch blocks appropriately".
🤖 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 `@test/proxy-mock-api/server.js` around lines 74 - 83, The unguarded JSON.parse
in the PUT handler for '/api/test/subscription-level' can throw on malformed
input; wrap the body parsing/JSON.parse in a try/catch inside the req.on('end')
callback, and on catch respond with res.writeHead(400, { 'Content-Type':
'application/json' }) and res.end(JSON.stringify({ ok: false, error: 'Invalid
JSON' })) so the server doesn't crash; on success continue to set
currentSubscriptionLevel and return the existing 200 response.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support in the proxy mock API to return a hostedDbPlan derived from the configured subscription level, aligning the mock response with how the proxy throttling logic is keyed.

Changes:

  • Introduced deriveHostedDbPlan(level) to map subscription levels to a hostedDbPlan.
  • Updated GET /api/proxy/connections to include hostedDbPlan in the returned connection payload and logs.
  • Re-indented/reformatted the file (notably switching indentation style).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 14 to +18
function deriveCompanyId(username) {
// Single-username case (e.g. plain "proxy_user") keeps the legacy id so existing
// tests/clients that don't randomize still hit a stable companyId.
if (username === PROXY_USERNAME_PREFIX) {
return 'test-company-001';
}
const hash = crypto.createHash('sha1').update(username).digest('hex').slice(0, 12);
return `test-company-${hash}`;
// Single-username case (e.g. plain "proxy_user") keeps the legacy id so existing
// tests/clients that don't randomize still hit a stable companyId.
if (username === PROXY_USERNAME_PREFIX) {
return 'test-company-001';
Comment on lines +74 to +82
if (req.method === 'PUT' && parsedUrl.pathname === '/api/test/subscription-level') {
let body = '';
req.on('data', (chunk) => (body += chunk));
req.on('end', () => {
const parsed = JSON.parse(body);
currentSubscriptionLevel = parsed.subscriptionLevel;
console.log(`[mock-api] Subscription level changed to: ${currentSubscriptionLevel}`);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ok: true, subscriptionLevel: currentSubscriptionLevel }));
return 'HOSTED_DB_PAID';
}

// Store received usage reports so tests can verify them via GET /api/proxy/usage-reports
@Artuomka Artuomka merged commit 48030d0 into main May 13, 2026
22 of 23 checks passed
@Artuomka Artuomka deleted the backend_stripe_proxy_usage_reports branch May 13, 2026 14:43
if (username === PROXY_USERNAME_PREFIX) {
return 'test-company-001';
}
const hash = crypto.createHash('sha1').update(username).digest('hex').slice(0, 12);
if (username === PROXY_USERNAME_PREFIX) {
return 'test-connection-001';
}
const hash = crypto.createHash('sha1').update(username).digest('hex').slice(0, 12);
);
} else {
console.log(
`[mock-api] -> 404: username/database mismatch (expected ${PROXY_USERNAME_PREFIX}[_*]/${PROXY_DATABASE})`,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants