Skip to content

Comments

feat(connectors): support arbitrary OAuth providers#212

Merged
Paveltarno merged 4 commits intopavelta-connectors-1from
task-4-flexible-providers
Feb 10, 2026
Merged

feat(connectors): support arbitrary OAuth providers#212
Paveltarno merged 4 commits intopavelta-connectors-1from
task-4-flexible-providers

Conversation

@Paveltarno
Copy link
Collaborator

@Paveltarno Paveltarno commented Feb 9, 2026

Note

Description

This PR adds comprehensive OAuth connector support to the Base44 CLI, enabling users to configure and manage integrations with various OAuth providers. The key enhancement is flexible provider support - the CLI now accepts both known providers (Google Calendar, Slack, Notion, etc.) and arbitrary custom OAuth providers, allowing users to integrate services without waiting for first-class Base44 support.

Related Issue

Part of: #184

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Other (please describe):

Changes Made

Core Connector Resource Module (src/core/resources/connector/)

  • Schema (schema.ts): Added Zod schemas for 12 OAuth providers (Google Calendar, Google Drive, Gmail, Google Sheets, Google Docs, Google Slides, Slack, Notion, Salesforce, HubSpot, LinkedIn, TikTok) with JSDoc links to official scope documentation
  • Generic Provider Support: Added GenericConnectorSchema to accept arbitrary provider strings, enabling custom OAuth integrations
  • Flexible Type Validation: IntegrationTypeSchema accepts both known enum values and any non-empty string
  • Config Loading (config.ts): Reads connector JSONC files from connectors/ directory with validation
  • API Client (api.ts): Methods for listing, syncing, polling OAuth status, and removing connectors
  • Push Logic (push.ts): Syncs local connectors with remote state, handles OAuth flow redirects, removes upstream-only connectors
  • OAuth Flow (oauth.ts): Browser redirect handling with status polling (5-minute timeout)
  • Resource Interface (resource.ts): Implements Resource<ConnectorResource> pattern

CLI Command (src/cli/commands/connectors/)

  • base44 connectors push: Deploy connectors with OAuth flow handling, browser redirect prompts, and sync result reporting

Project Integration

  • Updated ProjectData type to include connectors?: ConnectorResource[]
  • Integrated connector loading in readProjectConfig()

Test Coverage (137 tests passing)

  • Unit tests (tests/core/connectors.spec.ts): Schema validation (known providers, arbitrary providers, empty string rejection), file reading, push logic, OAuth flow handling
  • Integration tests (tests/cli/connectors_push.spec.ts): CLI command execution, API mocking, error handling
  • Fixtures: with-connectors/, invalid-connector/ directories with sample connector files
  • API Mocks (testkit/Base44APIMock.ts): Mock methods for connector operations

Testing

  • I have tested these changes locally
  • I have added/updated tests as needed
  • All tests pass (npm test)

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings
  • I have updated AGENTS.md if I made architectural changes

Additional Notes

Key architectural decisions:

  1. Discriminated union pattern: Known providers get dedicated schemas with literal types, arbitrary providers use generic schema - provides type safety for known providers while maintaining flexibility
  2. Type validation strategy: IntegrationTypeSchema uses z.union([z.enum(...), z.string().min(1)]) to accept both known and arbitrary providers - only rejects empty strings
  3. OAuth flow handling: Browser-based redirect with polling (5-minute timeout) - gracefully handles PENDING, ACTIVE, and FAILED states
  4. Resource interface compliance: Follows existing patterns in entities/ and functions/ modules for consistency

Build & test verification:

  • Build successful: bun run build
  • All 137 tests passing: bun run test
  • Known providers (12 types) work as expected
  • Arbitrary providers (e.g., "custom-oauth-provider", "facebook") accepted and validated
  • Empty strings properly rejected
  • Push/sync/remove operations function correctly

🤖 Generated by Claude | 2026-02-09 12:30 UTC

Paveltarno and others added 3 commits February 9, 2026 13:11
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Change provider field from closed enum to flexible union that accepts both
known providers (googlecalendar, notion, slack, etc.) and any arbitrary
provider string. This enables users to configure custom OAuth providers
without waiting for first-class Base44 support.

Schema changes:
- Add GenericConnectorSchema for arbitrary provider types
- Update ConnectorResourceSchema to union of specific + generic schemas
- Update IntegrationTypeSchema to accept known enum OR any non-empty string
- Only reject empty strings

Test coverage:
- Verify known providers continue to work
- Verify arbitrary providers are accepted
- Verify empty strings are rejected
- All 137 tests passing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 9, 2026

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/cli@0.0.28-pr.212.81917a6

Prefer not to change any import paths? Install using npm alias so your code still imports base44:

npm i "base44@npm:@base44-preview/cli@0.0.28-pr.212.81917a6"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "base44": "npm:@base44-preview/cli@0.0.28-pr.212.81917a6"
  }
}

Preview published to npm registry — try new features instantly!

@Paveltarno Paveltarno changed the base branch from main to pavelta-connectors-1 February 9, 2026 12:14
@claude
Copy link

claude bot commented Feb 9, 2026

Code Review - Issues Found

I've reviewed PR #212 and found several issues that need attention:


1. 🔴 Security: Path Traversal Vulnerability

Location: src/core/resources/connector/api.ts (lines 53, 114)

Issue: The integrationType parameter is interpolated directly into API URL paths without sanitization. Since GenericConnectorSchema accepts arbitrary strings via z.string(), a malicious connector config file could use types like ../../some-endpoint to traverse to unintended API endpoints.

Vulnerable code:

// In setConnector()
response = await appClient.put(
  `external-auth/integrations/${integrationType}`,
  ...
);

// In removeConnector()
response = await appClient.delete(
  `external-auth/integrations/${integrationType}/remove`
);

Impact: URL resolution would normalize ../ segments, allowing requests to arbitrary endpoints under /api/apps/{app_id}/.

Fix: Add character validation to IntegrationTypeSchema in schema.ts:

export const IntegrationTypeSchema = z.union([
  z.enum(KnownIntegrationTypes),
  z.string().min(1).regex(/^[a-z0-9_-]+$/i),
]);

Reference:

try {
response = await appClient.put(
`external-auth/integrations/${integrationType}`,
{
json: {


2. 🟡 Bug: Error Message Shows Literal 'null' or 'undefined'

Location: src/core/resources/connector/push.ts (lines 69-71)

Issue: When error_message is falsy and other_user_email is null or undefined, the error message becomes "Already connected by null" or "Already connected by undefined".

Vulnerable code:

error:
  response.error_message ||
  `Already connected by ${response.other_user_email}`,

Both fields are typed as z.string().nullable().optional() in the schema.

Fix: Add a fallback for other_user_email:

error:
  response.error_message ||
  `Already connected by ${response.other_user_email ?? 'another user'}`,

Reference:

action: "error",
error:
response.error_message ||
`Already connected by ${response.other_user_email}`,
};


3. 📋 CLAUDE.md Violation: Generic Error Instead of Structured Error

Location: src/core/resources/connector/config.ts (line 48)

Issue: Code throws new Error() instead of using structured error classes.

CLAUDE.md rule #15:

Use structured errors - Never throw new Error(); use specific error classes from @/core/errors.js with appropriate hints

Current code:

throw new Error(`Duplicate connector type "${connector.type}"`);

Fix:

throw new InvalidInputError(
  `Duplicate connector type "${connector.type}"`,
  {
    hints: [
      { message: `Remove duplicate connectors with type "${connector.type}" - only one connector per type is allowed` }
    ]
  }
);

Reference:

if (types.has(connector.type)) {
throw new Error(`Duplicate connector type "${connector.type}"`);
}


4. 📋 CLAUDE.md Violation: Direct chalk Usage Instead of theme

Location: src/cli/commands/connectors/push.ts (line 2 and throughout)

Issue: File imports and uses chalk directly instead of the centralized theme utility.

CLAUDE.md rules (lines 252-253, 672):

All CLI styling is centralized in src/cli/utils/theme.ts. Never use chalk directly - import theme from utils instead.

Violations:

  • Line 2: import chalk from "chalk";
  • Lines 57-110: chalk.bold(), chalk.green(), chalk.yellow(), chalk.red(), chalk.dim()

Fix: Replace with theme utility:

import { theme } from "@/cli/utils/index.js";

// Examples:
chalk.bold()  theme.styles.bold()
chalk.dim()  theme.styles.dim()
chalk.green()  theme.colors.base44Orange() // or appropriate semantic color

Reference: See src/cli/commands/entities/push.ts for examples of proper theme usage.

Link:

import { confirm, isCancel, log } from "@clack/prompts";
import chalk from "chalk";
import { Command } from "commander";


5. 📋 CLAUDE.md Violation: Missing Connector Documentation in AGENTS.md

Location: AGENTS.md

Issue: A new resource type (connectors) was added but not documented in AGENTS.md.

CLAUDE.md rules (line 7, rule #10):

Important: Keep this file updated when making significant architectural changes.

The connector resource should be documented similarly to entity, function, and agent resources:

  1. Folder Structure section (after line 83): Add connector resource entry showing all 7 files:
├── connector/
│   ├── schema.ts
│   ├── config.ts
│   ├── resource.ts
│   ├── api.ts
│   ├── push.ts
│   ├── oauth.ts
│   └── index.ts
  1. CLI commands section (around line 129): Add connectors command entry:
├── connectors/
│   ├── index.ts      # getConnectorsCommand(context) - parent command
│   └── push.ts

Reference: https://github.com/base44/cli/blob/c89ba59cabcb404cb02982294df5402abd030cbf/AGENTS.md


These issues should be addressed before merging to ensure code quality, security, and architectural consistency.

@dor-chaouat dor-chaouat moved this from Backlog to In progress in CLI Development Feb 9, 2026
@Paveltarno Paveltarno merged commit 7bfb43f into pavelta-connectors-1 Feb 10, 2026
2 of 3 checks passed
@Paveltarno Paveltarno deleted the task-4-flexible-providers branch February 10, 2026 11:59
@github-project-automation github-project-automation bot moved this from In progress to Done in CLI Development Feb 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant