Skip to content
endpoint-validator logo

MikoPBX Endpoint Validating

endpoint-validator

Валидация REST API эндпоинтов на соответствие OpenAPI схеме и консистентность параметров. Использовать при реализации эндпоинтов, ревью кода или перед слиянием изменений API.

SKILL.md

Full skill instructions

MikoPBX Endpoint Validating

Validate MikoPBX REST API endpoints for OpenAPI compliance, parameter consistency, and proper implementation.

What This Skill Does

  1. Validates DataStructure.php - Checks parameter definitions completeness
  2. Validates SaveRecordAction.php - Ensures 7-phase pattern compliance
  3. Tests Schema Validation - Verifies SCHEMA_VALIDATION_STRICT mode
  4. Generates Compliance Report - Provides actionable recommendations

When to Use

Use this skill when:

  • Implementing new API endpoints
  • Modifying existing endpoints
  • Reviewing API code changes
  • Before merging API-related pull requests
  • User asks "validate my API changes"
  • After making changes to DataStructure.php files

Quick Start

Step 1: Identify Files

# Find DataStructure and SaveRecordAction for a resource
RESOURCE="Extensions"  # Or: Providers, IncomingRoutes, etc.

find src/​PBXCoreREST/​Lib -name "DataStructure.php" | grep -i "$RESOURCE"
find src/​PBXCoreREST/​Lib -name "SaveRecordAction.php" | grep -i "$RESOURCE"

Expected locations:

  • src/​PBXCoreREST/​Lib/​{Resource}/​DataStructure.php
  • src/​PBXCoreREST/​Lib/​{Resource}/​SaveRecordAction.php

Step 2: Validate DataStructure

Check for required structure:

class DataStructure
{
    public static function getParameterDefinitions(): array
    {
        return [
            'request' => [
                'param_name' => [
                    'type' => 'string',           // Required
                    'description' => '...',        // Required
                    'example' => 'example_value',  // Required
                    'required' => true,            // Required
                    // Optional constraints:
                    'maxLength' => 255,
                    'pattern' => '^regex$',
                    'enum' => ['value1', 'value2'],
                    'default' => 'default_value',
                ],
            ],
            'response' => [
                // Similar structure for response fields
            ],
        ];
    }
}

Quick Checks:

  • ✅ Has getParameterDefinitions() method
  • ✅ Every parameter has: type, description, example, required
  • ✅ Validation constraints present (min/​max, pattern, enum)
  • ❌ NO getParametersConfig() method (legacy)
  • ❌ NO ParameterSanitizationExtractor usage

See: Complete DataStructure Specification

Step 3: Validate SaveRecordAction

Check for 7-phase pattern compliance:

class SaveRecordAction extends BaseSaveAction
{
    public function __invoke(ServerRequestInterface $request): ResponseInterface
    {
        // PHASE 1: Load DataStructure definitions
        $definitions = DataStructure::getParameterDefinitions();

        // PHASE 2: Parse request & detect HTTP method
        $requestData = $this->parseRequest($request);
        $httpMethod = $request->getMethod();

        // PHASE 3: Validate ID if present
        $id = $requestData['id'] ?? null;

        // PHASE 4: Load existing record for PUT/​PATCH/​DELETE
        $existingRecord = null;
        if (in_array($httpMethod, ['PUT', 'PATCH', 'DELETE']) && $id) {
            $existingRecord = $this->findRecordById($id);
        }

        // PHASE 5: Sanitize & apply defaults (POST only!)
        $sanitized = [];
        foreach ($requestDefs as $param => $def) {
            if (isset($requestData[$param])) {
                $sanitized[$param] = $this->sanitizeValue(...);
            } elseif ($httpMethod === 'POST' && isset($def['default'])) {
                $sanitized[$param] = $def['default'];  // Only on POST!
            }
        }

        // PHASE 6: Validate parameters
        $errors = $this->validateParameters($sanitized, $requestDefs, $httpMethod);

        // PHASE 7: Business logic & persistence
        if ($httpMethod === 'POST') {
            return $this->respondSuccess($this->createRecord($sanitized), 201);
        }
        // ... PUT/​PATCH/​DELETE handling
    }
}

Critical Checks:

  • ✅ Defaults applied ONLY on POST, never on PATCH
  • ✅ Required validation on POST and PUT, but NOT on PATCH
  • ✅ HTTP method detection present
  • ✅ Comprehensive WHY comments
  • ❌ NO defaults on PATCH (common bug!)

See: Complete 7-Phase Pattern Guide

Top 5 Common Issues

1. 🔴 CRITICAL: Defaults Applied on PATCH

Problem:

// ❌ WRONG - Applies defaults on PATCH too!
$value = $requestData[$param] ?? $def['default'] ?? null;

Why Bad: PATCH is for partial updates. Defaults overwrite existing values.

Fix:

// ✅ CORRECT - Only on POST
if ($httpMethod === 'POST' && !isset($requestData[$param]) && isset($def['default'])) {
    $sanitized[$param] = $def['default'];
}

See: All Anti-Patterns

2. 🔴 CRITICAL: Required Validation on PATCH

Problem:

// ❌ WRONG - Validates required on all methods
if ($def['required'] && !isset($data[$param])) {
    $errors[] = "Required";
}

Why Bad: PATCH allows partial updates. User should update one field without sending all.

Fix:

// ✅ CORRECT - Skip required check for PATCH
if (in_array($httpMethod, ['POST', 'PUT']) && $def['required'] && !isset($data[$param])) {
    $errors[] = "Required";
}

3. 🟡 HIGH: Hardcoded Validation

Problem: Validation rules in SaveRecordAction instead of DataStructure.

Fix: Move all validation constraints to DataStructure:

// In DataStructure.php
'number' => [
    'type' => 'string',
    'pattern' => '^\d{2,8}$',  // Define here
    'maxLength' => 8,
]

// SaveRecordAction uses these constraints automatically

4. 🟡 HIGH: Legacy Methods

Problems:

  • Using getParametersConfig() instead of getParameterDefinitions()
  • Using ParameterSanitizationExtractor class

Fix: Remove legacy code, use modern approach.

5. 🟢 MEDIUM: Missing Validation Constraints

Problem: Parameters missing min/​max, pattern, enum constraints.

Fix: Add constraints to DataStructure:

'email' => [
    'type' => 'string',
    'format' => 'email',        // Add format
    'maxLength' => 255,         // Add length limit
]

Validation Workflow

1. Quick Visual Inspection

Read through files looking for:

  • DataStructure has getParameterDefinitions() ✅
  • SaveRecordAction has method detection ($httpMethod) ✅
  • Defaults only in POST conditional ✅
  • Required validation skips PATCH ✅
  • WHY comments present ✅

2. Test with CURL

CONTAINER_ID=$(docker ps --filter "ancestor=mikopbx/​mikopbx" --format "{{.ID}}" | head -1)

# Get auth token
TOKEN="your-bearer-token"

# Test POST (should apply defaults)
curl -X POST "https://mikopbx-php83.localhost:8445/​pbxcore/​api/​v3/​extensions" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/​json" \
  -d '{"number": "201", "type": "SIP"}' \
  -k -v

# Test PATCH (should NOT apply defaults)
curl -X PATCH "https://mikopbx-php83.localhost:8445/​pbxcore/​api/​v3/​extensions/​{id}" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"number": "202"}' \
  -k -v

# Verify: status should remain unchanged, not reset to default

3. Generate Report

Use the report template to document findings:

  • DataStructure compliance score
  • SaveRecordAction compliance score
  • Critical issues found
  • Prioritized recommendations

Testing Checklist

Essential tests to verify endpoint behavior:

POST Tests

  • POST with all required succeeds (201)
  • POST with missing required fails (400)
  • POST applies defaults correctly

PUT Tests

  • PUT with all required succeeds (200)
  • PUT with missing required fails (400)
  • PUT on non-existent fails (404)

PATCH Tests (Most Important!)

  • PATCH with partial data succeeds (200)
  • PATCH does NOT apply defaults (verify existing values preserved)
  • PATCH does NOT require all required fields
  • PATCH on non-existent fails (404)

DELETE Tests

  • DELETE existing succeeds (200/​204)
  • DELETE non-existent fails (404)

See: Complete Validation Checklist

Output Format

Always provide structured compliance reports:

📋 API Endpoint Validation Report
==================================

🎯 Endpoint: POST /​pbxcore/​api/​v3/​extensions
📁 Resource: Extensions

📂 Files Analyzed:
   ✅ DataStructure.php: src/​PBXCoreREST/​Lib/​Extensions/​DataStructure.php
   ✅ SaveRecordAction.php: src/​PBXCoreREST/​Lib/​Extensions/​SaveRecordAction.php

---

## 🔍 DataStructure Analysis

✅ Structure: COMPLIANT
⚠️  Missing constraints on 3 parameters:
   - user_username: Add pattern validation
   - email: Add format => 'email'

DataStructure Score: 85/​100 ✅

---

## 🔍 SaveRecordAction Analysis

❌ CRITICAL ISSUES:
1. Defaults applied on PATCH (Line 87)
   Impact: Partial updates overwrite existing values
   Fix: Wrap default logic in `if ($httpMethod === 'POST')`

2. Missing required validation for PUT (Line 145)
   Impact: PUT allows missing required fields
   Fix: Change to `if (in_array($httpMethod, ['POST', 'PUT']))`

SaveRecordAction Score: 55/​100 ❌

---

## 📊 Overall Compliance Score

Total Score: 72/​100 ⚠️  Needs Improvement

---

## ✅ Recommendations (Priority Order)

🔴 CRITICAL (Must Fix):
1. Fix PATCH defaults bug (Line 87) - 15 min
2. Add PUT required validation (Line 145) - 10 min

🟡 HIGH PRIORITY:
3. Add validation constraints to DataStructure - 15 min

---

📝 Action Items:
- [ ] Fix PATCH defaults bug
- [ ] Add PUT required validation
- [ ] Add missing constraints
- [ ] Add regression test for PATCH
- [ ] Run full test suite

Full Template: report-template.md

Pro Tips

  1. Always Check PATCH First - Most bugs are in PATCH handling
  2. Look for WHY Comments - They explain critical decisions
  3. Test Actual Behavior - Don't trust code inspection alone
  4. Use Schema Validation - Enable SCHEMA_VALIDATION_STRICT=1
  5. Focus on Defaults - Default application logic is #1 bug source
  6. Check Method Detection - Ensure $httpMethod is actually used

Troubleshooting

Issue: Can't find DataStructure.php

# Search entire codebase
find src -name "DataStructure.php" | grep -i "YourResource"

# If not found, check if resource exists
ls -la src/​PBXCoreREST/​Lib/ | grep -i "YourResource"

Issue: Schema validation not working

# Check if enabled
docker exec $CONTAINER_ID env | grep SCHEMA_VALIDATION

# If not set, add to docker-compose.yml:
# environment:
#   SCHEMA_VALIDATION_STRICT: 1

Issue: Tests show unexpected behavior

# Check container logs for validation errors
docker exec $CONTAINER_ID tail -100 /​storage/​usbdisk1/​mikopbx/​log/​php/​error.log

Additional Resources

Complete Documentation:

Related Skills:

  • mikopbx-openapi-analyzer - Fetch and analyze OpenAPI spec
  • mikopbx-api-test-generator - Generate pytest tests from spec
  • mikopbx-docker-restart-tester - Test after container restart

Success Criteria

Validation is successful when:

  • ✅ DataStructure has complete parameter definitions
  • ✅ No legacy patterns found
  • ✅ SaveRecordAction follows 7-phase pattern
  • ✅ Defaults only applied on POST
  • ✅ Required validation only on POST/​PUT (not PATCH)
  • ✅ All validation from DataStructure, not hardcoded
  • ✅ Schema validation tests pass
  • ✅ PATCH preserves existing values (doesn't apply defaults)
  • ✅ Compliance score ≥ 90/​100

Quick Reference Card

CheckDataStructureSaveRecordAction
Has modern structuregetParameterDefinitions()7-phase pattern
No legacy codeNo getParametersConfig()No ParameterSanitizationExtractor
Complete metadatatype, description, exampleWHY comments
Validation constraintsmin/​max, pattern, enumUses DataStructure rules
Defaults handlingDefined in request sectionOnly applied on POST
Required validationMarked with required: truePOST & PUT only, not PATCH

Example Validation Session

# 1. Locate files
RESOURCE="Extensions"
find src/​PBXCoreREST/​Lib -path "*/​$RESOURCE/​DataStructure.php"
# Output: src/​PBXCoreREST/​Lib/​Extensions/​DataStructure.php

# 2. Check DataStructure structure
grep -n "getParameterDefinitions" src/​PBXCoreREST/​Lib/​Extensions/​DataStructure.php
# Output: Line 15: public static function getParameterDefinitions(): array

# 3. Check for legacy methods
grep -n "getParametersConfig\|ParameterSanitizationExtractor" \
  src/​PBXCoreREST/​Lib/​Extensions/​DataStructure.php
# Output: (none) - Good!

# 4. Check SaveRecordAction for PATCH defaults bug
grep -A 2 "httpMethod.*POST" src/​PBXCoreREST/​Lib/​Extensions/​SaveRecordAction.php
# Look for: if ($httpMethod === 'POST' && isset($def['default']))

# 5. Run PATCH test
curl -X PATCH "https://mikopbx-php83.localhost:8445/​pbxcore/​api/​v3/​extensions/​123" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"number": "202"}' -k | jq '.data.status'
# Verify status didn't change to default value

More DevOps & CI/CD skills

Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.

6K 472.6K
View

Set up tracing, logging, and monitoring for deployed ADK agents across Cloud Trace, BigQuery, and third-party platforms.

6K 472.6K
View

Enterprise Azure infrastructure architect generating Bicep or Terraform from workload descriptions.

1.5K 454.3K
View
azure-kubernetes logo
DevOps & CI/CD

azure-kubernetes

Plan and configure production-ready Azure Kubernetes Service clusters with Day-0 and Day-1 best practices.

1.5K 447.1K
View

Raw mechanical interfaces fusing Swiss typographic print with military terminal aesthetics. Rigid grids, extreme type scale contrast, utilitarian color, analog degradation effects. For data-heavy dashboards, portfolios, or editorial sites that need to feel like declassified blueprints.

92.7K 354.9K
View
just-scrape logo
DevOps & CI/CD

just-scrape

Web search, scraping, extraction, crawling, and monitoring via ScrapeGraph AI CLI.

69 245K
View

Skill for working with Firebase Hosting (Classic). Use this when you want to deploy static web apps, Single Page Apps (SPAs), or simple microservices. Do NOT use for Firebase App Hosting.

462 159.7K
View

Deploy and manage web apps with Firebase App Hosting. Use this skill when deploying Next.js/Angular apps with backends.

462 159.1K
View
deploy-to-vercel logo
DevOps & CI/CD

deploy-to-vercel

Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".

31.9K 146.6K
View
programmatic-seo logo
DevOps & CI/CD

programmatic-seo

Build SEO-optimized pages at scale using templates, data, and proven playbook patterns.

53.3K 140.1K
View

Design and build isolated, reusable Convex backend components with clear boundaries and app-facing wrappers.

63 123.5K
View

Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".

31.9K 116.1K
View

Coding & apps AI tools

Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View
I
Coding & apps

Imagica

Build a no-code AI app in minutes.

Freemium
View
E
Coding & apps

Emergent.sh

An IDE for code migration from legacy to modern frameworks through coding agents.

Freemium
View
Wonder Dynamics logo
Coding & apps

Wonder Dynamics

Automate CGI animation in live-action scenes

Paid
View
M
Coding & apps

Mixo

Launch a website in seconds with AI.

Paid
View
AI Code Convert logo
Coding & apps

AI Code Convert

Streamline Your Coding Experience with AI Code Helper

Free
View