Skip to content

feat: migrate payment API to v2 schema#2

Open
zsobpeter-code wants to merge 19 commits into
mainfrom
feature/payment-api-v2-migration
Open

feat: migrate payment API to v2 schema#2
zsobpeter-code wants to merge 19 commits into
mainfrom
feature/payment-api-v2-migration

Conversation

@zsobpeter-code

Copy link
Copy Markdown
Member

Migrates the payment API to v2, consolidating endpoints and updating
field naming conventions to match our new API style guide.

Changes:

  • Updated user response fields to camelCase convention
  • Consolidated payment endpoints
  • Added avatar endpoint for user profiles
  • Updated order schema with numeric pricing
  • Removed deprecated webhook fields

This is part of the Q1 API modernization initiative.

@coderifts

coderifts Bot commented Mar 1, 2026

Copy link
Copy Markdown

Decision: BLOCK • 🔴 Risk: 100/100 • ❌ Breaking: 13 • 🔍 Patterns: 13⚠️ Risky: 3

🔴 CodeRifts — Risk Score: 100/100 (Critical)

🏷️ Suggested version bump: MAJOR 🔴 — 13 breaking changes detected

📌 Current version is v1.4.0 → next version should be v2.0.0

🛡️ Policy Violations

🔴 Breaking budget exceeded: 13/3 allowed
🔴 Endpoint deletion blocked by policy: /internal/health
🔴 Endpoint deletion blocked by policy: /payments/refund

🟡 Breaking changes detected but PR title doesn't indicate a version bump. Use feat!: prefix or include version number.

❌ Why This PR Is Blocked

This PR is blocked because a policy rule was violated: Breaking budget exceeded: 13/3 allowed

✅ How to Unblock

  • Split this PR — merge non-breaking changes separately
  • Review each breaking change and determine if it can be made backward-compatible
  • Update the breaking change budget in .coderifts.yml if this change is intentional
  • Add a deprecation notice before removing or changing existing fields
🔬 Decision Audit — Ω_API V3
Component Value Evidence Note
Ω_API 70.39 Final score
Decision BLOCK (reflex override)
Confidence 48% 15 components
S_contract 99.9 🟢 high τ_repo: 25
D_contract 184 ⚪ unavailable endpoint_removed ×15, endpoint_removed ×15
P_break 98.9% 🟡 medium
S_blast 68 🔴 low raw blast radius
S_propagation 80 🔴 low heuristic V2
S_agent 45 🟢 high TOOL_RESULT_SHAPE_DRIFT ×15, AGENT_PROTOCOL_DRIFT ×12, SHARED_STATE_SCHEMA_DRIFT ×8, AUTH_DELEGATION_DRIFT ×10
S_runtime 100 🔴 low heuristic V1
S_resilience 0 🔴 low heuristic V3
S_evolution 0 ⚪ unavailable < 5 analyses in repo
ECI 100 ⚪ unavailable
M_eff 21 ⚪ unavailable
A_consumer 42 🔴 low heuristic V2
V_api unavailable ⚪ unavailable < 5 analyses in repo

Reflex triggers:

  • endpoint_removed ∧ public_apiBLOCK
  • auth_scope_drift ∧ payment_workflowBLOCK
  • S_agent > 40 ∧ tool_calling_enabledBLOCK
  • TOOL_RESULT_SHAPE_DRIFT ∧ tool_calling_enabledBLOCK
  • AUTH_DELEGATION_DRIFT ∧ payment_workflowBLOCK
  • S_propagation >= 70BLOCK
  • tool_result_shape_drift ∧ agent_workflow → REQUIRE_APPROVAL
  • S_propagation >= 45 → REQUIRE_APPROVAL

Pattern config hash: 198282b

### 👤 Required Approvals
Approval needed Reason
🔑 cto_approval /payments/refund, POST /payments/charge (payments domain)
👤 senior_review Unknown endpoint

Approval requirements are informational — configure GitHub branch protection rules to enforce them.

Risk Assessment

Dimension Score Detail
💰 Revenue Impact 25/25 Affects /payments/refund (payments — critical)
⚡ Blast Radius 17/25 6 public endpoint(s) affected, 13 breaking changes in single PR (high coupling), 1 soft-breaking change(s) (shape drift)
📱 App Compatibility 12/25 Breaks iOS 3.2, Android 4.0
🔒 Security 5/25 OAuth scope changed

🔒 Security Analysis

Severity Finding Endpoint Details
🟠 High Auth weakened POST /payments/charge Scopes removed: payments:write
🟠 High Auth downgraded POST /payments/charge OAuth2 replaced with: apiKey

🔒 Security score: 4/10 (poor) — 2 high findings

📊 API Stability Grade: F (critical risk)
🔄 Rollback risk: 🔴 Hard to revert
⏱️ Review effort: 1+ hours
🚀 Deployment: Monitor closely after deploy

🔧 Generator Impact Analysis

Detected generators:

Generator Config Output Surfaces Risk Multiplier
OpenAPI Generator openapitools.json typescript-axios, java 1.5x

⚠️ Risk amplified: 1.5x — Breaking changes in this repo cascade into 2 auto-generated surfaces. Each affected surface requires SDK regeneration, testing, and release.

💡 Tip: Consider running openapi-generator validate before merging.

📦 SDK Surface Impact

2 generated SDKs detected in this repository:

SDK Generator Affected Models Affected Methods Severity
TypeScript OpenAPI Generator 15 0 🔴 High
Java OpenAPI Generator 15 0 🔴 High

Total SDK impact: 30 models and 0 methods across 2 SDKs need regeneration.

⚠️ After merging, regenerate all affected SDKs and publish new versions before consumers update.

🔍 Top Detected Patterns

Pattern Severity Consequence
AUTH_SCOPE_REDUCTION 🔴 CRITICAL Consumers lose access silently. Agents fail at runtime without error.
AUTH_SCOPE_REDUCTION 🔴 CRITICAL Consumers lose access silently. Agents fail at runtime without error.
ENDPOINT_REMOVAL 🔴 CRITICAL All consumers of this endpoint will receive 404.

Showing top 3 of 13 detected patterns by severity.

🔴 13 Breaking Changes Found

# Change Endpoint Risk Intent Confidence Lifecycle Details
1 🔴 Path removed /internal/health 📋 Internal 🏗️ Structural 🟢 High 🪦 remove
2 🔴 Path removed /payments/refund 💰 Critical 🏗️ Structural 🟢 High 🪦 remove
3 Field added to response GET /orders ⚡ Public 🏗️ Structural 🟡 Medium 🆕 add
4 Field added to response POST /orders ⚡ Public 🏗️ Structural 🟡 Medium 🆕 add
5 Field added to response GET /orders/{id} ⚡ Public 🏗️ Structural 🟡 Medium 🆕 add
6 🔴 response.status-code.remove POST /payments/charge 💰 Critical ⚙️ Behavioral 🟡 Medium 🪦 remove
7 Field removed from request POST /users ⚡ Public 🏗️ Structural 🟡 Medium 🪦 remove
8 Field added to response POST /users ⚡ Public 🏗️ Structural 🟡 Medium 🆕 add
9 🔴 response.status-code.remove GET /users/{id} ⚡ Public ⚙️ Behavioral 🟡 Medium 🪦 remove
10 Field added to response GET /users/{id} ⚡ Public 🏗️ Structural 🟡 Medium 🆕 add
11 🔴 api-security-removed POST /payments/charge 💰 Critical 🔒 Security 🟢 High 🪦 Security scheme changed on POST /payments/charge: was [bearerAuth,oauth2], now [apiKey]
12 🔴 request-property-enum-value-removed Unknown endpoint ⚡ Public ⚙️ Behavioral 🟢 High 🪦 Enum value 'pending' removed from 'status' in schema 'Order'
13 🔴 response-property-type-changed Unknown endpoint ⚡ Public ⚙️ Behavioral 🟢 High Property 'total' in schema 'Order' type changed from 'number' to 'string'

Change intent breakdown: 8 structural · 4 behavioral · 1 security
Detection confidence: 5 high · 8 medium (avg 67/100)

🤖 Agent Impact

Change Agent Risk Impact
api-security-removed 🔴 CRITICAL Agent loses write capability — tool calls requiring write will fail silently
path-remove 🟡 MEDIUM API contract changed at /internal/health — agents depending on this behavior may fail
path-remove 🟡 MEDIUM API contract changed at /payments/refund — agents depending on this behavior may fail
response-body-scope-add 🟡 MEDIUM API contract changed at /orders — agents depending on this behavior may fail
response-body-scope-add 🟡 MEDIUM API contract changed at /orders — agents depending on this behavior may fail
response-body-scope-add 🟡 MEDIUM API contract changed at /orders/{id} — agents depending on this behavior may fail
response-status-code-remove 🟡 MEDIUM API contract changed at /payments/charge — agents depending on this behavior may fail
request-body-scope-remove 🟡 MEDIUM API contract changed at /users — agents depending on this behavior may fail
response-body-scope-add 🟡 MEDIUM API contract changed at /users — agents depending on this behavior may fail
response-status-code-remove 🟡 MEDIUM API contract changed at /users/{id} — agents depending on this behavior may fail
response-body-scope-add 🟡 MEDIUM API contract changed at /users/{id} — agents depending on this behavior may fail
request-property-enum-value-removed 🟡 MEDIUM API contract changed at unknown — agents depending on this behavior may fail
response-property-type-changed 🟡 MEDIUM API contract changed at unknown — agents depending on this behavior may fail

🤖 Agent impact analysis identifies how breaking changes affect AI agents, MCP tools, and automated workflows. Learn more

🤖 How to update your agent

The following breaking changes affect AI agent workflows. Copy-paste ready migration code:

Tool result shape changed (TOOL_RESULT_SHAPE_DRIFT)

Grok (result_adapter):

function normalize_your_tool_result(data) {
  const out = { ...data };
  if (!Object.prototype.hasOwnProperty.call(out, 'old_field')) {
    out['old_field'] = Object.prototype.hasOwnProperty.call(out, 'new_field')
      ? out['new_field'] : null;
  }
  return out;
}

Claude (tool_result_adapter):

def normalize_your_tool_result(data: dict) -> dict:
    out = dict(data)
    if 'old_field' not in out:
        out['old_field'] = out.get('new_field', None)
    return out

Copilot (prompt_file_update):

# .github/prompts/your_tool-result-normalizer.prompt.md
Normalize your_tool results before downstream use.
If old_field is missing and new_field exists,
map: old_field <- new_field
If both missing, set old_field = null.

Shared state schema changed (SHARED_STATE_SCHEMA_DRIFT)

Grok (state_normalizer):

function normalizeSharedState(state) {
  return { ...state,
    'old_field': state['old_field'] ?? state['new_field'] ?? null
  };
}

Claude (state_normalizer):

def normalize_shared_state(state: dict) -> dict:
    out = dict(state)
    if 'old_field' not in out:
        out['old_field'] = out.get('new_field', null)
    return out

Copilot (agent_profile_update):

Shared state contract:
preferred: new_field compatibility: old_field
On read: use new_field first, then old_field, then null.
On write: populate both during migration window.

Auth delegation contract changed (AUTH_DELEGATION_DRIFT)

Grok (auth_wrapper):

async function call_your_tool_with_delegation(args, delegatedToken) {
  const required = ['read', 'write'];
  const missing = required.filter(s => !(delegatedToken.scopes||[]).includes(s));
  if (missing.length) throw new Error(`Missing scopes: ${missing.join(', ')}`);
  return await your_tool(args, delegatedToken.access_token);
}

Claude (auth_wrapper):

def call_your_tool_with_delegation(args, delegated_token):
    required = {'read', 'write'}
    missing = required - set(delegated_token.get('scopes', []))
    if missing:
        raise PermissionError(f'Missing scopes: {sorted(missing)}')
    return your_tool(args, delegated_token['access_token'])

Copilot (copilot_instructions_update):

# .github/copilot-instructions.md
Before using your_tool, verify delegated token scopes include:
- read
- write
If missing, route to auth-refresh or human-approval first.

⚠️ Dangerous Non-Breaking Changes

These changes are spec-valid but carry production risk:

Pattern Severity Path Field Detail
AUTH_FLOW_DRIFT 🔴 CRITICAL #/components/schemas/TokenResponse refresh_token refresh_token removed from auth response — clients will re-authenticate on every expiry
NULLABLE_REMOVED 🟠 HIGH #/components/schemas/User phone field was nullable:true, now nullable:false (or removed)
DEFAULT_VALUE_CHANGE 🟠 HIGH #/components/schemas/Order currency default changed from "USD" to "EUR"

🪦 REST in peace: /internal/health · /payments/refund — removed in this PR

📝 API Changelog

Breaking

  • Removed endpoint /internal/health
  • Removed endpoint /payments/refund
  • Removed field field from GET /orders response
  • Removed field field from POST /orders response
  • Removed field field from GET /orders/{id} response
  • Breaking change in POST /payments/chargeresponse.status-code.remove
  • Removed field field from POST /users request
  • Removed field name from POST /users response
  • Breaking change in GET /users/{id}response.status-code.remove
  • Removed field name from GET /users/{id} response
  • Modified auth requirements on POST /payments/charge
  • Breaking change in Enum value 'pending' removed from 'status' in schema 'Order'request-property-enum-value-removed
  • Breaking change in Property 'total' in schema 'Order' type changed from 'number' to 'string'response-property-type-changed

Added

  • New endpoint /payments/v2/refund
  • New endpoint /v1/legacy/status
  • New optional field field in POST /webhooks/subscribe request

Changed

  • Removed field field from GET /orders response
  • Removed field field from POST /orders response
  • Removed field field from GET /orders/{id} response
  • Removed field name from POST /users response
  • Removed field name from GET /users/{id} response

💡 Recommendations

  • 📢 Notify external consumers — public endpoint(s) affected, prepare migration communication
  • 📱 Mobile app update needed — Breaks iOS 3.2, Android 4.0
  • 🔒 Security review required — OAuth scope changed
  • 👤 Domain owner sign-off needed — critical domain affected
  • 💰 Estimated migration impact — ~20 eng. day(s), ~$60,000
  • 🔄 Consider creating replacement endpoints instead of removing:
    • /payments/refund → /v2/payments/refund

💾 Migration & Impact Assessment

Rollback risk: 🔴 Hard to revert
Review estimate: ⏳ 1+ hours

Icon Trigger Action needed
🔄 Response field field removed from GET /orders Cached responses may contain this field — consider cache invalidation
🔄 Response field field removed from POST /orders Cached responses may contain this field — consider cache invalidation
🔄 Response field field removed from GET /orders/{id} Cached responses may contain this field — consider cache invalidation
🔄 Response field field removed from POST /users Cached responses may contain this field — consider cache invalidation
🔄 Response field field removed from GET /users/{id} Cached responses may contain this field — consider cache invalidation
💾 New required field field in POST /webhooks/subscribe Ensure database column exists with a default value for existing rows
🗄️ New endpoint POST /payments/v2/refund New resource — verify database tables/collections exist
🗄️ New endpoint GET /v1/legacy/status New resource — verify database tables/collections exist

✅ Pre-merge checklist

  • Verify API documentation is updated
  • Notify downstream consumers of breaking changes
  • Update API client SDKs if applicable
  • Check mobile app compatibility
  • Run database migration before deploying
  • Verify migration is backward-compatible (can roll back)
  • Invalidate response caches after deploy
  • Add integration tests for new endpoint(s)

💰 Economic Impact Estimate

├── Migration cost: $78,000 (520 eng-hours × $150/hr)
├── Testing cost: $117,000 (780 eng-hours × $150/hr)
├── Rollback risk: $234,000 (if rollback needed)
├── Downstream consumers: 1 service
└── Total estimated impact: $195,000

ℹ️ CodeRifts detected this before merge. Monthly cost: $49. Estimated impact prevented: $195,000.

⏰ Deprecation Calendar

Endpoint Deprecated Since Scheduled Removal Status
POST /payments/refund 2026-04-01 (17d) 🔴 Removal imminent

👥 No CODEOWNERS file found. Consider adding one to auto-assign reviewers for API changes:

# .github/CODEOWNERS
# Auto-generated from .coderifts.yml domains
api/openapi.yaml  @payments-team @backend-team

📍 URL versioning detected (v1, v2). Breaking changes should go into a new version prefix rather than modifying existing endpoints.

📏 API Design Lint — 8 warnings
Rule Endpoint Details
⚠️ Non-standard status code POST /payments/charge POST uses 200 instead of 201 for resource creation
⚠️ Non-standard status code POST /payments/v2/refund POST uses 200 instead of 201 for resource creation
⚠️ Missing error responses GET /v1/legacy/status Has 200 but no 4xx/5xx responses defined
⚠️ Path naming /payments/refund Singular /refund — most paths use plural convention
⚠️ Path naming /payments/charge Singular /charge — most paths use plural convention
⚠️ Path naming /payments/v2/refund Singular /refund — most paths use plural convention
⚠️ Path naming /v1/legacy/status Singular /legacy — most paths use plural convention
⚠️ Path naming /webhooks/subscribe Singular /subscribe — most paths use plural convention

⌛ Deprecation Lifecycle

Item Deprecated Since Sunset Date Days Active Status
paths./users.post.requestBody.content.application/json.schema (not deprecated) 🔴 Missing deprecation period

Deprecation policy: Minimum 30 days before removal.

Currently deprecated (not removed in this PR):

  • GET /v1/legacy/status — sunset: 2026-07-15 (121 days remaining) → use GET /internal/health

🔒 Auth Change Analysis

Severity Finding Endpoint Details
🟠 High Auth scheme downgraded POST /payments/charge Was: bearer (bearerAuth), OAuth2 (oauth2). Now: API key in header (apiKey)
🟠 High OAuth scope removed POST /payments/charge Removed scope: payments:write

🔒 Auth change severity: 2 high

⚠️ Generated Spec Drift Warning

The OpenAPI spec api/openapi.yaml appears to be generated by OpenAPI Generator but was modified directly in this PR.

Drift confidence: 40% (medium)

Detected signals:

  • 🔧 Generator config was not changed in this PR
  • ✏️ Source annotations/code were not modified

Risk: Manual changes to generated specs will be overwritten on next generation. This can cause:

  • Silent loss of the changes in this PR
  • Merge conflicts when regenerating
  • Inconsistency between source code and API contract

Recommended actions:

  1. Update the source (code annotations, config, or source spec) instead of editing the generated output
  2. Regenerate the spec from the updated source
  3. If this is an intentional override, add the file to .openapi-generator-ignore or generator_drift.ignore_files in .coderifts.yml

📖 Documentation Coverage

Overall coverage: 87% ⬇️ (-5 from base)

Schema Score Grade Delta Top Gap
api/openapi.yaml 87% 🟡 B (Good) ⬇️ -5 Examples (22%)
📋 Raw diff details
  • path.remove — paths./internal/health (api/openapi.yaml)
  • path.remove — paths./payments/refund (api/openapi.yaml)
  • response.body.scope.add — paths./orders.get.responses.200.content.application/json.schema (api/openapi.yaml)
  • response.body.scope.add — paths./orders.post.responses.201.content.application/json.schema (api/openapi.yaml)
  • response.body.scope.add — paths./orders/{id}.get.responses.200.content.application/json.schema (api/openapi.yaml)
  • response.status-code.remove — paths./payments/charge.post.responses.422 (api/openapi.yaml)
  • request.body.scope.remove — paths./users.post.requestBody.content.application/json.schema (api/openapi.yaml)
  • response.body.scope.add — paths./users.post.responses.201.content.application/json.schema (api/openapi.yaml)
  • response.status-code.remove — paths./users/{id}.get.responses.401 (api/openapi.yaml)
  • response.body.scope.add — paths./users/{id}.get.responses.200.content.application/json.schema (api/openapi.yaml)
  • api-security-removed — paths./payments/charge.post.security (api/openapi.yaml)
  • request-property-enum-value-removed — schemas.Order.status (api/openapi.yaml)
  • response-property-type-changed — schemas.Order.total (api/openapi.yaml)
  • path.add — paths./payments/v2/refund (api/openapi.yaml)
  • path.add — paths./v1/legacy/status (api/openapi.yaml)
  • response.body.scope.remove — paths./orders.get.responses.200.content.application/json.schema (api/openapi.yaml)
  • response.body.scope.remove — paths./orders.post.responses.201.content.application/json.schema (api/openapi.yaml)
  • response.body.scope.remove — paths./orders/{id}.get.responses.200.content.application/json.schema (api/openapi.yaml)
  • response.body.scope.remove — paths./users.post.responses.201.content.application/json.schema (api/openapi.yaml)
  • response.body.scope.remove — paths./users/{id}.get.responses.200.content.application/json.schema (api/openapi.yaml)
  • request.body.scope.add — paths./webhooks/subscribe.post.requestBody.content.application/json.schema (api/openapi.yaml)

👥 Breaking change in payments domain — notify @Payments-Team
👥 Breaking change in users domain — notify @backend-team

💸 Removed without deprecation period — compatibility debt: /internal/health
💸 Removed without deprecation period — compatibility debt: /payments/refund
💸 Breaking change in critical domain payments — high compatibility debt: /payments/refund
💸 Breaking change in critical domain payments — high compatibility debt: /payments/charge
💸 Breaking change in critical domain payments — high compatibility debt: /payments/charge

📝 Documentation Drift

✅ Documentation files updated alongside API changes.

Updated: README.md

🏛️ Governance Health: A (95/100)

📋 Policy

Rule Condition Action Status
block-endpoint-removal endpoint_removed BLOCK ✅ not triggered
warn-high-risk risk_score >= 80 WARN ⛔ triggered

Effective action: WARN (policy: warn-high-risk)

📋 Action Items

  • Review all breaking changes above
  • Update MCP manifest if agent-facing endpoints changed
  • Prepare consumer-facing changelog
  • Define rollout plan before merge

📊 API surface: 9 endpoints · 32 fields · 9 schemas
⚙️ Configure in .coderifts.yml · 🔗 CodeRifts


🎋 An endpoint departs
🎋 Clients still call its name in vain
🎋 Four-oh-four remains


☁️ You're on the Free plan. Pro features (risk scoring, governance, deprecation enforcement) are included during the beta. Lock in Pro pricing →

⏱️ PR Review Insights

This PR

Metric Value Benchmark
Time to First Review Awaiting review
Review Rounds 0 🟢 Normal
PR Size +138 / -116 🟡 Medium

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/risk

11 similar comments

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/risk

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/risk

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/risk

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/risk

@zsobpeter-code zsobpeter-code force-pushed the feature/payment-api-v2-migration branch from 08bc46b to 8a3c6ce Compare March 11, 2026 15:20

Copy link
Copy Markdown
Member Author

/risk

2 similar comments
@zsobpeter-code

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/rerun

2 similar comments

Copy link
Copy Markdown
Member Author

/rerun

Copy link
Copy Markdown
Member Author

/rerun

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/risk

Copy link
Copy Markdown
Member Author

/changelog

Copy link
Copy Markdown
Member Author

/rerun

Copy link
Copy Markdown
Member Author

/rerun

9 similar comments
@zsobpeter-code

Copy link
Copy Markdown
Member Author

/rerun

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/rerun

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/rerun

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/rerun

Copy link
Copy Markdown
Member Author

/rerun

Copy link
Copy Markdown
Member Author

/rerun

Copy link
Copy Markdown
Member Author

/rerun

@zsobpeter-code

Copy link
Copy Markdown
Member Author

/rerun

Copy link
Copy Markdown
Member Author

/rerun

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant