Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-company-type-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"adcontextprotocol": patch
---

Fix company profile modal stuck on "Saving..." when selecting Data & Measurement or AI & Tech Platforms company types. Backend validation now uses centralized COMPANY_TYPE_VALUES to accept all 7 company types.
4 changes: 2 additions & 2 deletions .markdown-link-check.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
"pattern": "https://adcontextprotocol.org/docs/"
}
],
"timeout": "20s",
"timeout": "30s",
"retryOn429": true,
"retryCount": 5,
"fallbackRetryDelay": "5s",
"fallbackRetryDelay": "10s",
"aliveStatusCodes": [200, 206]
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions server/src/addie/mcp/admin-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
isLushaConfigured,
mapIndustryToCompanyType,
} from '../../services/lusha.js';
import { COMPANY_TYPE_VALUES } from '../../config/company-types.js';
import { createProspect } from '../../services/prospect.js';
import {
getAllFeedsWithStats,
Expand Down Expand Up @@ -395,8 +396,8 @@ This replaces find_prospect and lookup_organization with a unified view.`,
},
company_type: {
type: 'string',
enum: ['adtech', 'agency', 'brand', 'publisher', 'other'],
description: 'Type of company (adtech, agency, brand, publisher, or other)',
enum: COMPANY_TYPE_VALUES,
description: 'Type of company',
},
domain: {
type: 'string',
Expand Down Expand Up @@ -455,7 +456,7 @@ This replaces find_prospect and lookup_organization with a unified view.`,
},
company_type: {
type: 'string',
enum: ['adtech', 'agency', 'brand', 'publisher', 'other'],
enum: COMPANY_TYPE_VALUES,
description: 'Type of company',
},
status: {
Expand Down Expand Up @@ -525,7 +526,7 @@ This replaces find_prospect and lookup_organization with a unified view.`,
},
company_type: {
type: 'string',
enum: ['adtech', 'agency', 'brand', 'publisher', 'other'],
enum: COMPANY_TYPE_VALUES,
description: 'Filter by company type',
},
limit: {
Expand Down
11 changes: 11 additions & 0 deletions server/src/db/migrations/144_update_company_type_constraint.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- Migration: Update company_type CHECK constraint to include 'data' and 'ai' types
-- These types were added to the frontend but the database constraint was not updated

-- Drop the old constraint (using IF EXISTS for idempotency)
ALTER TABLE organizations
DROP CONSTRAINT IF EXISTS organizations_company_type_check;

-- Add updated constraint with all valid company types
ALTER TABLE organizations
ADD CONSTRAINT organizations_company_type_check
CHECK (company_type IS NULL OR company_type IN ('adtech', 'agency', 'brand', 'data', 'ai', 'publisher', 'other'));
11 changes: 3 additions & 8 deletions server/src/routes/billing-public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
mapIndustryToCompanyType,
mapRevenueToTier,
} from "../services/lusha.js";
import { COMPANY_TYPE_VALUES } from "../config/company-types.js";
import { WorkOS } from "@workos-inc/node";

const logger = createLogger("billing-public-routes");
Expand Down Expand Up @@ -627,14 +628,8 @@ export function createPublicBillingRouter(): Router {
const { orgId } = req.params;
const { company_type, revenue_tier } = req.body;

// Validate inputs - must match CompanyType in organization-db.ts
const validCompanyTypes = [
"brand",
"publisher",
"agency",
"adtech",
"other",
];
// Validate inputs - use centralized company types config
const validCompanyTypes = COMPANY_TYPE_VALUES;
const validRevenueTiers = [
"under_1m",
"1m_5m",
Expand Down
11 changes: 5 additions & 6 deletions server/src/routes/organizations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { invitationRateLimiter, orgCreationRateLimiter } from "../middleware/rate-limit.js";
import { validateOrganizationName, validateEmail } from "../middleware/validation.js";
import { OrganizationDatabase, CompanyType, RevenueTier } from "../db/organization-db.js";
import { COMPANY_TYPE_VALUES } from "../config/company-types.js";
import { JoinRequestDatabase } from "../db/join-request-db.js";
import { SlackDatabase } from "../db/slack-db.js";
import { getCompanyDomain } from "../utils/email-domain.js";
Expand Down Expand Up @@ -747,11 +748,10 @@ export function createOrganizationsRouter(): Router {
}

// Validate company_type if provided
const validCompanyTypes = ['brand', 'publisher', 'agency', 'adtech', 'other'];
if (company_type && !validCompanyTypes.includes(company_type)) {
if (company_type && !COMPANY_TYPE_VALUES.includes(company_type)) {
return res.status(400).json({
error: 'Invalid company type',
message: `company_type must be one of: ${validCompanyTypes.join(', ')}`,
message: `company_type must be one of: ${COMPANY_TYPE_VALUES.join(', ')}`,
});
}

Expand Down Expand Up @@ -1083,11 +1083,10 @@ export function createOrganizationsRouter(): Router {
}

// Validate company_type if provided
const validCompanyTypes = ['brand', 'publisher', 'agency', 'adtech', 'other'];
if (company_type !== undefined && company_type !== null && !validCompanyTypes.includes(company_type)) {
if (company_type !== undefined && company_type !== null && !COMPANY_TYPE_VALUES.includes(company_type)) {
return res.status(400).json({
error: 'Invalid company type',
message: `company_type must be one of: ${validCompanyTypes.join(', ')}`,
message: `company_type must be one of: ${COMPANY_TYPE_VALUES.join(', ')}`,
});
}

Expand Down