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
57 changes: 57 additions & 0 deletions ci/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# V3 Schema Configuration
# This file defines valid enum values for schema fields
# Validation rules and logic live in validate_v3.py

version: 3

# Valid availability states for plugins and connectors
availability:
- IDEA
- VALIDATED
- BUILT_IN
- INSTALLABLE
- IMPOSSIBLE

# Valid agent capabilities (multi-select for plugins)
# Note: "Polling Required" is being migrated to "Ambient Agent"
agent_capabilities:
- Ambient Agent
- Structured Data Analyzer

# Valid solution tags (business categorization, multi-select for plugins)
# Extracted from existing solution_tags and domain fields across all files
solution_tags:
- Access Management
- Approvals
- Customer Success
- Data Analysis
- Engineering
- Facilities
- Finance - Expense Management
- Finance - Other
- Finance - Payroll
- Finance - Procurement
- General
- HR - Benefits
- HR - Employee Records
- HR - Learning & Development
- HR - Onboarding
- HR - Other
- HR - Performance Management
- HR - Recruiting & Talent
- HR - Talent Management
- HR - Time & Absence
- HR - Workplace Culture
- IT
- Legal
- Manager
- Marketing
- Product
- Product Management
- Productivity
- Project Management
- Sales
- Support
- Ticketing
- Troubleshoot
- Workday
58 changes: 58 additions & 0 deletions ci/config_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
Configuration loader for V3 schema validation.
Loads and caches config.yaml to provide enum value lists.
"""

import yaml
import os
from typing import List, Dict, Any

# Path to config file relative to this module
CONFIG_FILE = os.path.join(os.path.dirname(__file__), "config.yaml")

# Cache the loaded config
_config_cache = None


def load_config() -> Dict[str, Any]:
"""Load and cache config.yaml"""
global _config_cache
if _config_cache is None:
with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
_config_cache = yaml.safe_load(f)
return _config_cache


def get_valid_values(field: str) -> List[str]:
"""
Get valid enum values for a config field.

Args:
field: Field name (e.g., 'availability', 'agent_capabilities', 'solution_tags')

Returns:
List of valid values, or empty list if field not in config
"""
config = load_config()
return config.get(field, [])


def is_valid_value(field: str, value: str) -> bool:
"""
Check if a value is valid for a given field.

Args:
field: Field name
value: Value to check

Returns:
True if value is in the valid list, False otherwise
"""
valid_values = get_valid_values(field)
return value in valid_values


def get_config_version() -> int:
"""Get the schema version from config"""
config = load_config()
return config.get('version', 3)
80 changes: 74 additions & 6 deletions ci/model.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from enum import Enum


# V2 Schema Enums (kept for backwards compatibility during migration)
class Fidelity(Enum):
IDEA = "Idea"
VALIDATED = "Validated"
Expand All @@ -20,14 +22,80 @@ class DifficultyLevel(Enum):
ADVANCED = "Advanced"


DIRECTORY_MAP = {ContentTypes.CONNECTOR: "connectors", ContentTypes.PLUGIN: "plugins"}
class Availability(Enum):
IDEA = "Idea"
VALIDATED = "Validated"
BUILT_IN = "Built-In"
INSTALLABLE = "Installable"


# Common constants
DIRECTORY_MAP = {
ContentTypes.CONNECTOR: "connectors",
ContentTypes.PLUGIN: "plugins"
}

MARKDOWN_EXTENSION = '.md'
README_FILENAME = f"README{MARKDOWN_EXTENSION}"
LOGO_FILE = "logo.png"

class Availability(Enum):
IDEA = "Idea"
VALIDATED = "Validated"
BUILT_IN = "Built-In"
INSTALLABLE = "Installable"

# ============================================================================
# V3 Schema Constants
# ============================================================================

# V3 Schema Version
V3_SCHEMA_VERSION = 3

# Path to config file
CONFIG_FILE = "ci/config.yaml"

# Regex patterns for V3 validation
KEBAB_CASE_PATTERN = r'^[a-z0-9]+(?:-[a-z0-9]+)*$'
# Simplified Title Case pattern - actual validation more complex
TITLE_CASE_PATTERN = r'^[A-Z][a-z]*(?:\s+[A-Z][a-z]*)*$'

# Description validation constants
PLUGIN_DESCRIPTION_PREFIX = "A plugin that"
CONNECTOR_DESCRIPTION_PREFIX = "A connector for"
DESCRIPTION_SUFFIX = "."

# Purple Chat Link validation
PURPLE_CHAT_URL_PREFIX = (
"https://marketplace.moveworks.com/purple-chat?conversation="
)

# V3 Required Fields by Content Type
CONNECTOR_REQUIRED_FIELDS = {
"name", # Title Case name
"availability", # Enum from config.yaml
"logo", # Logo URL (required)
}

PLUGIN_REQUIRED_FIELDS = {
"name", # Title Case name
"description", # Must start with prefix and end with period
"availability", # Enum from config.yaml
"systems", # List of connector slugs (must exist as directories)
"purple_chat_link", # Must be valid URL
"solution_tags", # List from config.yaml
}

# V3 Optional Fields by Content Type
CONNECTOR_OPTIONAL_FIELDS = {
"description", # Should end with period if present
"video", # Video URL
"redirects", # List of old slugs
}

PLUGIN_OPTIONAL_FIELDS = {
"agent_capabilities", # List from config.yaml
"installation_asset_uuid", # UUID for installable plugins
"video", # Video URL
"redirects", # List of old slugs
}

# All valid V3 fields (for strict schema validation)
# Any fields NOT in these sets will cause validation to FAIL
ALL_CONNECTOR_FIELDS = CONNECTOR_REQUIRED_FIELDS | CONNECTOR_OPTIONAL_FIELDS
ALL_PLUGIN_FIELDS = PLUGIN_REQUIRED_FIELDS | PLUGIN_OPTIONAL_FIELDS