feat: enforce production pricing provider config
Quality / test (push) Canceled after 0s

This commit is contained in:
2026-09-10 01:46:58 -04:00
parent f837324cf5
commit 4f0e3d89f6
6 changed files with 66 additions and 4 deletions
+10 -1
View File
@@ -51,7 +51,10 @@ import { createProviderMappingRepository } from "../modules/pricing/repositories
import { createProviderMappingService } from "../modules/pricing/services/provider-mapping-service.js";
import { createPricingProviderRegistry } from "../modules/pricing/providers/pricing-provider.js";
import { createFixturePricingProvider } from "../modules/pricing/providers/fixture-pricing-provider.js";
import { createHttpPricingProvider } from "../modules/pricing/providers/http-pricing-provider.js";
import {
assertProductionPricingProviderConfig,
createHttpPricingProvider,
} from "../modules/pricing/providers/http-pricing-provider.js";
import { createAdminExportService } from "../modules/exports/services/admin-export-service.js";
import { createInventoryExportJobRepository } from "../modules/exports/repositories/inventory-export-job-repository.js";
import { createSellerSettingsRepository } from "../modules/settings/repositories/seller-settings-repository.js";
@@ -70,6 +73,12 @@ function parsePort(value) {
}
async function startServer() {
if (process.env.NODE_ENV === "production") {
assertProductionPricingProviderConfig({
fixtureEnabled: process.env.PRICING_FIXTURE_PROVIDER_ENABLED === "true",
endpoint: process.env.PRICING_HTTP_PROVIDER_ENDPOINT,
});
}
const imageStorageRoot = resolveProjectImageStorageRoot(
process.env.IMAGE_STORAGE_ROOT ?? ".local/image-storage",
import.meta.url,
@@ -1,5 +1,23 @@
import { createPricingProvider } from './pricing-provider.js';
export function assertProductionPricingProviderConfig({ fixtureEnabled, endpoint }) {
if (fixtureEnabled) {
throw new Error('The fixture pricing provider must be disabled in production.');
}
if (typeof endpoint !== 'string' || endpoint.trim().length === 0) {
throw new Error('A production pricing provider endpoint is required.');
}
let parsedUrl;
try {
parsedUrl = new URL(endpoint);
} catch {
throw new Error('The production pricing provider endpoint must be a valid HTTPS URL.');
}
if (parsedUrl.protocol !== 'https:') {
throw new Error('The production pricing provider endpoint must use HTTPS.');
}
}
export function createHttpPricingProvider({
id,
endpoint,
@@ -6,7 +6,10 @@ import {
createPricingProviderRegistry,
} from "../../src/modules/pricing/providers/pricing-provider.js";
import { createFixturePricingProvider } from "../../src/modules/pricing/providers/fixture-pricing-provider.js";
import { createHttpPricingProvider } from "../../src/modules/pricing/providers/http-pricing-provider.js";
import {
assertProductionPricingProviderConfig,
createHttpPricingProvider,
} from "../../src/modules/pricing/providers/http-pricing-provider.js";
test("registers pricing providers behind a validated adapter contract", async () => {
const provider = createPricingProvider({
@@ -78,6 +81,25 @@ test("http provider rejects insecure or malformed external provider URLs", () =>
);
});
test("requires a secure external provider in production", () => {
assert.throws(
() => assertProductionPricingProviderConfig({ fixtureEnabled: true, endpoint: "https://provider.example/prices" }),
/fixture pricing provider must be disabled/i,
);
assert.throws(
() => assertProductionPricingProviderConfig({ fixtureEnabled: false, endpoint: "" }),
/endpoint is required/i,
);
assert.throws(
() => assertProductionPricingProviderConfig({ fixtureEnabled: false, endpoint: "http://provider.example/prices" }),
/must use HTTPS/i,
);
assert.doesNotThrow(() => assertProductionPricingProviderConfig({
fixtureEnabled: false,
endpoint: "https://provider.example/prices",
}));
});
test("http provider sends mapping context and normalizes its response", async () => {
let request;
const provider = createHttpPricingProvider({
+10 -1
View File
@@ -18,7 +18,10 @@ import { createPricingRefreshJobRepository } from "../../api/src/modules/pricing
import { createPricingService } from "../../api/src/modules/pricing/services/pricing-service.js";
import { createPricingProviderRegistry } from "../../api/src/modules/pricing/providers/pricing-provider.js";
import { createFixturePricingProvider } from "../../api/src/modules/pricing/providers/fixture-pricing-provider.js";
import { createHttpPricingProvider } from "../../api/src/modules/pricing/providers/http-pricing-provider.js";
import {
assertProductionPricingProviderConfig,
createHttpPricingProvider,
} from "../../api/src/modules/pricing/providers/http-pricing-provider.js";
import { createInventoryItemRepository } from "../../api/src/modules/inventory/repositories/inventory-item-repository.js";
import { createInventoryItemService } from "../../api/src/modules/inventory/services/inventory-item-service.js";
import { createInventoryExportJobRepository } from "../../api/src/modules/exports/repositories/inventory-export-job-repository.js";
@@ -45,6 +48,12 @@ const pricingJobCleanupIntervalMs = Number.parseInt(
);
async function runWorker() {
if (process.env.NODE_ENV === "production") {
assertProductionPricingProviderConfig({
fixtureEnabled: process.env.PRICING_FIXTURE_PROVIDER_ENABLED === "true",
endpoint: process.env.PRICING_HTTP_PROVIDER_ENDPOINT,
});
}
const imageStorageRoot = resolveProjectImageStorageRoot(
process.env.IMAGE_STORAGE_ROOT ?? ".local/image-storage",
import.meta.url,