Skip to content

fix: add input validation for sn and price_id fields#12

Open
Washio20 wants to merge 1 commit intostayforge:mainfrom
Washio20:fix/bug-3-4-input-validation
Open

fix: add input validation for sn and price_id fields#12
Washio20 wants to merge 1 commit intostayforge:mainfrom
Washio20:fix/bug-3-4-input-validation

Conversation

@Washio20
Copy link

@Washio20 Washio20 commented Feb 23, 2026

Summary

  • Add regex pattern validation (^[a-zA-Z0-9_-]+$) to the sn (serial number) field to reject Chinese characters and other non-ASCII input
  • Add the same regex pattern validation to the price_id field to enforce Stripe-compatible pricing ID format
  • Validation applied across all relevant schemas: DeviceProperties, DeviceInput, DeviceUpdate, and DeviceInfo

Root Cause

The sn and price_id fields in the OpenAPI spec had no pattern constraint, allowing any string input including Chinese characters and other non-ASCII text. This is invalid because:

  • Serial numbers should only contain alphanumeric characters, hyphens, and underscores
  • Stripe price IDs follow a strict alphanumeric format (e.g., price_1ABC2DEF)

Changes

  • openapi.yaml: Added pattern: ^[a-zA-Z0-9_-]+$ to all sn and price_id field definitions
  • openapi.json: Added "pattern": "^[a-zA-Z0-9_-]+$" to all corresponding sn and price_id field definitions

Affected schemas:

Schema Field Change
DeviceProperties sn Added pattern
DeviceProperties price_id Added pattern
DeviceInput sn Added pattern
DeviceUpdate sn Added pattern
DeviceUpdate price_id Added pattern
DeviceInfo sn Added pattern

Test Plan

  • Verify that POST /v1/devices rejects sn values containing Chinese characters (e.g., {"sn": "测试设备"})
  • Verify that POST /v1/devices accepts valid sn values (e.g., {"sn": "SFVA78RABZ12345678"})
  • Verify that price_id rejects Chinese characters (e.g., {"price_id": "价格"})
  • Verify that price_id accepts valid Stripe IDs (e.g., {"price_id": "price_1ABC2DEF"})
  • Verify that null values are still accepted for nullable fields
  • Validate the OpenAPI spec with a linter to confirm no syntax errors

Closes #3
Closes #4

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Enhanced API input validation on identifier fields (serial numbers, organization IDs, tenant IDs, etc.) to enforce consistent formatting rules, requiring alphanumeric characters with hyphens and underscores.

, Closes stayforge#4)

Add regex pattern validation (^[a-zA-Z0-9_-]+$) to sn and price_id
fields across DeviceProperties, DeviceInput, DeviceUpdate, and
DeviceInfo schemas in both openapi.yaml and openapi.json. This
prevents Chinese characters and other non-ASCII input from being
accepted in these fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 23, 2026 08:07
@coderabbitai
Copy link

coderabbitai bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

This PR adds input validation patterns to OpenAPI specification files, constraining string fields across device, card, tenant, organization, and API key schemas to alphanumeric characters with hyphens and underscores, enforcing stricter validation rules on previously unvalidated identifiers.

Changes

Cohort / File(s) Summary
OpenAPI Specification Updates
openapi.json, openapi.yaml
Added regex pattern ^[a-zA-Z0-9_-]+$ validation constraints to multiple string fields: Device sn fields (DeviceProperties, DeviceInput, DeviceUpdate, DeviceInfo, CardInput), price_id fields in DeviceProperties and DeviceUpdate, and identifier fields across tenant, organization, invitation, and API key schemas.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 Patterns so tight, validation so right,
No Chinese chars shall pass through tonight,
Serial numbers and prices aligned,
Alphanumeric bliss we shall find!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding input validation patterns for sn and price_id fields in the OpenAPI specification.
Linked Issues check ✅ Passed The PR adds regex pattern ^[a-zA-Z0-9_-]+$ to sn and price_id fields across DeviceProperties, DeviceInput, DeviceUpdate, and DeviceInfo schemas, directly addressing the validation requirements from issues #3 and #4.
Out of Scope Changes check ✅ Passed All changes are scoped to adding pattern validation to sn and price_id fields in OpenAPI specs, directly addressing the linked issues without introducing unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds input validation to the sn (serial number) and price_id fields in the OpenAPI specification to prevent non-ASCII characters (particularly Chinese characters) from being accepted. The validation is implemented using the regex pattern ^[a-zA-Z0-9_-]+$, which restricts these fields to alphanumeric characters, underscores, and hyphens.

Changes:

  • Added pattern validation ^[a-zA-Z0-9_-]+$ to sn field across DeviceProperties, DeviceInput, DeviceUpdate, and DeviceInfo schemas
  • Added pattern validation ^[a-zA-Z0-9_-]+$ to price_id field in DeviceProperties and DeviceUpdate schemas
  • Changes applied consistently to both openapi.yaml and openapi.json files

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
openapi.yaml Added pattern validation to sn and price_id fields in all relevant device schemas
openapi.json Applied the same pattern validation as YAML file, maintaining consistency between specification formats

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
openapi.yaml (1)

1039-1048: ⚠️ Potential issue | 🟠 Major

/v1/devices/sn/{sn} path parameter is missing the new pattern constraint.

The PR adds ^[a-zA-Z0-9_-]+$ to all sn body fields to block non-ASCII input, but the path parameter for the GET /v1/devices/sn/{sn} endpoint was not updated. A request like GET /v1/devices/sn/中文字符 will still pass OpenAPI validation here, directly undermining the goal of Issue #3.

🐛 Proposed fix
  - name: sn
    in: path
    required: true
    schema:
      type: string
      minLength: 1
      maxLength: 256
+     pattern: ^[a-zA-Z0-9_-]+$
    description: Device serial number
    example: SFVA78RABZ12345678
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.yaml` around lines 1039 - 1048, The path parameter schema for the GET
/v1/devices/sn/{sn} endpoint is missing the new pattern constraint; update the
parameter named "sn" in openapi.yaml (the parameters block for the
/v1/devices/sn/{sn} path) to include "pattern": "^[a-zA-Z0-9_-]+$" alongside the
existing type/minLength/maxLength so the path parameter enforces the same ASCII
alphanumeric/underscore/dash restriction as the body fields.
🧹 Nitpick comments (3)
openapi.yaml (1)

5776-5791: sn and price_id fields in DeviceProperties are missing minLength/maxLength.

The pattern: ^[a-zA-Z0-9_-]+$ uses + so it implicitly enforces minLength=1, but maxLength is unconstrained. The /v1/devices/sn/{sn} path parameter already sets maxLength: 256 for the same field — these should be consistent. The same gap applies to DeviceInput.sn, DeviceUpdate.sn, DeviceInfo.sn, and DeviceUpdate.price_id.

♻️ Proposed fix for `DeviceProperties.sn` and `DeviceProperties.price_id`
     sn:
       type: string
       nullable: true
+      minLength: 1
+      maxLength: 256
       pattern: ^[a-zA-Z0-9_-]+$
       description: Serial number of the device.
     ...
     price_id:
       type: string
       nullable: true
+      minLength: 1
+      maxLength: 256
       pattern: ^[a-zA-Z0-9_-]+$
       description: Stripe price ID for billing purposes.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.yaml` around lines 5776 - 5791, Add explicit minLength: 1 and
maxLength: 256 to the sn property in DeviceProperties and mirror the same
constraints for DeviceInput.sn, DeviceUpdate.sn, and DeviceInfo.sn so they match
the /v1/devices/sn/{sn} path parameter; likewise add minLength: 1 and maxLength:
256 to DeviceUpdate.price_id (and any other price_id declarations) to constrain
the pattern-based fields consistently. Locate the YAML schemas for
DeviceProperties, DeviceInput, DeviceUpdate, and DeviceInfo and update the sn
and price_id entries to include minLength: 1 and maxLength: 256.
openapi.json (2)

7506-7510: Align /v1/devices/sn/{sn} path param with the SN regex.

Right now the path parameter schema doesn’t include the new constraint, so the docs are inconsistent with the schema objects. Consider adding the same pattern.

🔧 Suggested update (path parameter)
 "schema": {
   "type": "string",
   "minLength": 1,
-  "maxLength": 256
+  "maxLength": 256,
+  "pattern": "^[a-zA-Z0-9_-]+$"
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.json` around lines 7506 - 7510, The path parameter definition for
/v1/devices/sn/{sn} is missing the serial-number pattern defined in the shared
schema 'sn'; update the path parameter (parameter name "sn" on the
/v1/devices/sn/{sn} operation) to include the same "pattern": "^[a-zA-Z0-9_-]+$"
(and type: "string" and description matching the shared schema) so the path
parameter validation and docs match the "sn" schema object.

7308-7325: Reconsider strict format validation for Stripe price_id.

The pattern ^[a-zA-Z0-9_-]+$ is actually too restrictive for Stripe price IDs. Stripe generates Price IDs as opaque identifiers (e.g., price_1MoBy5LkdIwHu7ixZhnattbh) and does not publish a strict regex. Per Stripe's official guidance, avoid format validation in your schema; instead, rely on API-level validation when a price is actually used. If you must validate in the schema, use a minimal check (non-empty string, optionally prefixed with price_) rather than character-set restrictions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.json` around lines 7308 - 7325, The "price_id" schema currently
enforces pattern "^[a-zA-Z0-9_-]+$", which is too restrictive for Stripe price
IDs; update the OpenAPI schema entry for the price_id property to remove or
relax the pattern validation (e.g., remove the pattern and rely on
nullable/string types with minLength:1 or replace with a minimal pattern like
'^price_.+' if you must enforce a prefix), keeping the existing "type":"string"
and "nullable":true and the description intact so API-level Stripe validation
handles actual ID correctness; locate the "price_id" property in the schema to
apply this change.
ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a61a3a4 and 03f3e72.

📒 Files selected for processing (2)
  • openapi.json
  • openapi.yaml
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@openapi.yaml`:
- Around line 1039-1048: The path parameter schema for the GET
/v1/devices/sn/{sn} endpoint is missing the new pattern constraint; update the
parameter named "sn" in openapi.yaml (the parameters block for the
/v1/devices/sn/{sn} path) to include "pattern": "^[a-zA-Z0-9_-]+$" alongside the
existing type/minLength/maxLength so the path parameter enforces the same ASCII
alphanumeric/underscore/dash restriction as the body fields.

---

Nitpick comments:
In `@openapi.json`:
- Around line 7506-7510: The path parameter definition for /v1/devices/sn/{sn}
is missing the serial-number pattern defined in the shared schema 'sn'; update
the path parameter (parameter name "sn" on the /v1/devices/sn/{sn} operation) to
include the same "pattern": "^[a-zA-Z0-9_-]+$" (and type: "string" and
description matching the shared schema) so the path parameter validation and
docs match the "sn" schema object.
- Around line 7308-7325: The "price_id" schema currently enforces pattern
"^[a-zA-Z0-9_-]+$", which is too restrictive for Stripe price IDs; update the
OpenAPI schema entry for the price_id property to remove or relax the pattern
validation (e.g., remove the pattern and rely on nullable/string types with
minLength:1 or replace with a minimal pattern like '^price_.+' if you must
enforce a prefix), keeping the existing "type":"string" and "nullable":true and
the description intact so API-level Stripe validation handles actual ID
correctness; locate the "price_id" property in the schema to apply this change.

In `@openapi.yaml`:
- Around line 5776-5791: Add explicit minLength: 1 and maxLength: 256 to the sn
property in DeviceProperties and mirror the same constraints for DeviceInput.sn,
DeviceUpdate.sn, and DeviceInfo.sn so they match the /v1/devices/sn/{sn} path
parameter; likewise add minLength: 1 and maxLength: 256 to DeviceUpdate.price_id
(and any other price_id declarations) to constrain the pattern-based fields
consistently. Locate the YAML schemas for DeviceProperties, DeviceInput,
DeviceUpdate, and DeviceInfo and update the sn and price_id entries to include
minLength: 1 and maxLength: 256.

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

Labels

None yet

Projects

None yet

2 participants