Skip to content

Conversation

hekike
Copy link
Contributor

@hekike hekike commented Sep 17, 2025

This PR replaces the key in the Feature API with the ExternalKey type, which allows for UUIDs.

Summary by CodeRabbit

  • New Features

    • Feature keys now support up to 256 characters and no longer require a specific pattern, enabling external IDs.
  • Documentation

    • Added clearer descriptions for feature name and optional metadata.
    • Clarified meter association text to explain how usage is calculated.
  • Refactor

    • Public API inputs updated to accept an external-friendly feature key; removed the deprecated meterKey field while keeping meterSlug supported.

@hekike hekike requested a review from a team as a code owner September 17, 2025 21:14
Copy link
Contributor

coderabbitai bot commented Sep 17, 2025

📝 Walkthrough

Walkthrough

OpenAPI and client schema docs expand and relax validation for feature keys, add descriptions for name and metadata, and update meter/meterSlug descriptions. TypeSpec changes adjust public inputs: FeatureCreateInputs.key becomes ExternalKey and meterKey is removed. Zod runtime validation is updated to match the new constraints.

Changes

Cohort / File(s) Summary of changes
OpenAPI spec updates
api/openapi.yaml, api/openapi.cloud.yaml
Feature key maxLength increased 64→256; feature key pattern removed in openapi.cloud.yaml; key, name, and metadata descriptions expanded/added; meterSlug/meter descriptions updated to reference associated meter and usage calculation.
TypeSpec feature inputs
api/spec/src/entitlements/feature.tsp
FeatureCreateInputs.key type changed from KeyExternalKey. meterKey?: Key property removed. Feature (which extends FeatureCreateInputs) is implicitly updated.
Client JS JSDoc updates
api/client/javascript/src/client/schemas.ts
JSDoc descriptions for key, name, metadata, and meterSlug updated to longer/multiline descriptions; no type or signature changes.
Client Zod validation
api/client/javascript/src/zod/index.ts
createFeatureBodyKeyMax changed 64→256; exported regex constant removed; .regex(...) on key removed; key, name, metadata, and meterSlug .describe(...) text updated to match OpenAPI docs.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "fix(api): use external key for feature" is concise and accurately captures the primary change—replacing the feature key with an ExternalKey (to allow UUIDs)—and follows conventional commit style and scope, making it clear to reviewers scanning the history.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/feature-external-key

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
Contributor

@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.

Actionable comments posted: 3

♻️ Duplicate comments (2)
api/openapi.cloud.yaml (2)

16688-16702: Same as earlier key change: LGTM; verify downstream constraints.

Duplicate block of the feature key/name/metadata fields—feedback from Lines 16632–16646 applies here as well.


16707-16712: Repeat typo in meterSlug description.

Same “and and” issue; apply the same fix here.

-          description: The meter that the feature is associated with and and based on which usage is calculated.
+          description: The meter associated with the feature and used to calculate usage.
🧹 Nitpick comments (4)
api/spec/src/entitlements/feature.tsp (2)

103-105: Optional: capture constraints for name.

If you have a shared alias (e.g., Name/NonEmptyString), use it; otherwise consider a simple minLength to prevent empty names.

Example (outside this hunk):

@minLength(1)
name: string;

116-121: Fix doc mismatch and typo; remove stray meterKey lines.

Doc currently says “and and”, mentions @summary/@example inside the block, and includes a stale meterKey?: Key; which will surface as plain text in generated docs. Clean it up.

Apply:

-  /**
-   * The meter that the feature is associated with and and based on which usage is calculated.
-   * @summary("Meter key")
-   * @example("tokens_total")
-   * meterKey?: Key;
-   */
+  /**
+   * The meter that the feature is associated with and based on which usage is calculated.
+   * Example: "tokens_total".
+   */

Also sanity‑check that using Key for meterSlug?: Key; is intentional; if a distinct Slug alias exists, consider using it.

api/openapi.yaml (2)

17023-17029: Typo in meterSlug description (“and and”)

Fix duplication.

- description: The meter that the feature is associated with and and based on which usage is calculated.
+ description: The meter that the feature is associated with and based on which usage is calculated.

17079-17085: Typo in meterSlug description (second occurrence)

Same “and and” duplication here.

- description: The meter that the feature is associated with and and based on which usage is calculated.
+ description: The meter that the feature is associated with and based on which usage is calculated.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aaa6d52 and 7331d5c.

📒 Files selected for processing (3)
  • api/openapi.cloud.yaml (4 hunks)
  • api/openapi.yaml (4 hunks)
  • api/spec/src/entitlements/feature.tsp (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Artifacts / Container image
  • GitHub Check: Code Generators
  • GitHub Check: Lint
  • GitHub Check: Migration Checks
  • GitHub Check: Test
  • GitHub Check: Build
  • GitHub Check: Analyze (go)
🔇 Additional comments (3)
api/spec/src/entitlements/feature.tsp (2)

109-111: LGTM: clearer metadata docs.

The description and example improve the schema without behavior change.


95-101: Switch to ExternalKey for feature.key — verified constraints; confirm remaining Key usages

  • ExternalKey is declared in api/spec/src/types.tsp and feature.key now references ExternalKey (api/spec/src/entitlements/feature.tsp:101).
  • OpenAPI shows ULIDOrExternalKey anyOf → ExternalKey branch = string, minLength: 1, maxLength: 256 and no pattern (see api/openapi.yaml around the ULIDOrExternalKey component).
  • There are remaining Key usages (scalar Key in api/spec/src/types.tsp; meterKey?: Key and other key: Key occurrences). Confirm callers/clients that depended on Key-specific pattern/semantics are updated or regenerated.
api/openapi.yaml (1)

17060-17074: Duplicate schema block: keep in lockstep with hunk 1 — verified

Verified: components.schemas "Feature" and "FeatureCreateInputs" have identical key/name/metadata; no action required.

Comment on lines +16632 to 16646
maxLength: 256
description: |-
The unique key of the feature
Useful to reference the feature in external systems.
For example, your database ID.
title: The unique key of the feature
name:
type: string
description: The human-readable name of the feature
title: The human-readable name of the feature
metadata:
allOf:
- $ref: '#/components/schemas/Metadata'
description: Optional metadata
title: Optional metadata
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

External feature key: change looks good; please verify backend/storage and SDK impacts.

Removing the pattern and increasing maxLength to 256 aligns with using an external key. Please verify:

  • DB column sizes, indexes, and unique constraints can handle 256 (and any chars).
  • Server-side validators/DTOs no longer enforce the old snake_case regex.
  • Generated SDKs/docs don’t rely on the old pattern text.

Run this to find lingering 64-char limits or the old regex:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Find 64-length constraints
rg -n -C2 -g '!**/dist/**' -g '!**/build/**' -P '\b(maxLength|varchar|VARCHAR|length)\s*[:( ]\s*64\b'
# Find old snake_case pattern
rg -n -C2 -g '!**/dist/**' -g '!**/build/**' '^[ ]*pattern:\s*\^\[a-z0-9\]\+\(\?:_\[a-z0-9\]\+\)\*\$' api
# Find custom validations mentioning 64 or snake_case
rg -n -C2 -P '\b(64|snake[_ -]?case|slug)\b' --type go --type ts --type tsx --type rs --type py

Length of output: 148


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "PWD: $(pwd)"
echo "Top-level files:"
ls -la | sed -n '1,200p' || true

echo "Git branch (if available):"
git rev-parse --abbrev-ref HEAD 2>/dev/null || true

echo
echo "Show snippet of api/openapi.cloud.yaml (if exists):"
if [ -f api/openapi.cloud.yaml ]; then
  sed -n '16620,16650p' api/openapi.cloud.yaml || true
else
  echo "api/openapi.cloud.yaml not found at that path; searching for openapi*.yaml files..."
  rg -n --hidden --no-ignore-vcs -S 'openapi.*\.ya?ml' || true
fi

echo
echo "Searching for common 64-length constraints (SQL, YAML, code) across repo:"
rg -n --no-ignore-vcs -S -P 'varchar\s*\(\s*64\s*\)|VARCHAR\s*\(\s*64\s*\)|character varying\s*\(?64\)?|\b(maxLength|max_length|maxlength|length)\b[^0-9\n]*\b64\b' || true

echo
echo "Searching for the snake_case regex or YAML 'pattern:' lines that might enforce it:"
rg -n --no-ignore-vcs -S -P '\^\[a-z0-9\]\+(\?:_\[a-z0-9\]\+)*\$|pattern:\s*\^' || true

echo
echo "Searching for mentions of 'snake_case', 'slug', or related validator terms in common source files:"
rg -n --no-ignore-vcs -S -P '\b(snake[_ -]?case|slug|slugify|slug_)\b' --type-add 'code:*.{go,ts,tsx,rs,py,java,kt,sql,yaml,yml,json}' --type code || true

Length of output: 70551


Action required — backend, validators and SDKs must be updated after increasing feature key to 256

Change is present in api/openapi.cloud.yaml (key maxLength: 256) but verification shows many remaining 64-char constraints and snake_case patterns; update everything end-to-end. Key findings and next steps:

  • Specs: many "maxLength: 64" and "pattern: ^[a-z0-9]+(?:_[a-z0-9]+)*$" entries remain in api/openapi.yaml and api/openapi.cloud.yaml; api/spec/src/types.tsp contains @maxlength(64). Update schema/type definitions where they apply to key/slug.
  • DB/migrations: migrations reference "slug" (tools/migrate/migrations/20250305025807_add_meter_table.up.sql and 20250306040407_resource_meter.*). Confirm the actual DB column type/length and any unique/index definitions can accept 256 characters and adjust migrations/indexes if needed.
  • Server code: runtime still uses and validates "slug" (e.g., openmeter/meter/meter.go, openmeter/meter/service.go, openmeter/productcatalog/*). Update DTOs/validators and mapstructure/json tags/logic that enforce 64/snake_case.
  • Generated clients & docs: api/client/* (javascript zod, go gen, python) still reference slug and old constraints — regenerate clients and update docs to reflect maxLength=256 and removed pattern.
  • Required actions: replace remaining spec constraints and types.tsp entries, adjust DB/migration/indexes if necessary, update server validators/struct tags, re-generate SDKs, run migrations and full test suite. If backward compatibility is needed, add a compatibility path that accepts both old slug format and the new external key.

Comment on lines 16651 to 16656
minLength: 1
maxLength: 64
pattern: ^[a-z0-9]+(?:_[a-z0-9]+)*$
description: A key is a unique string that is used to identify a resource.
description: The meter that the feature is associated with and and based on which usage is calculated.
title: Meter slug
example: tokens_total
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo and tighten phrasing in meterSlug description.

“and and” is a typo. Suggest clearer wording.

Apply:

-          description: The meter that the feature is associated with and and based on which usage is calculated.
+          description: The meter associated with the feature and used to calculate usage.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
minLength: 1
maxLength: 64
pattern: ^[a-z0-9]+(?:_[a-z0-9]+)*$
description: A key is a unique string that is used to identify a resource.
description: The meter that the feature is associated with and and based on which usage is calculated.
title: Meter slug
example: tokens_total
minLength: 1
maxLength: 64
pattern: ^[a-z0-9]+(?:_[a-z0-9]+)*$
description: The meter associated with the feature and used to calculate usage.
title: Meter slug
example: tokens_total
🤖 Prompt for AI Agents
In api/openapi.cloud.yaml around lines 16651 to 16656, the description for
meterSlug contains a typo ("and and") and is worded awkwardly; update the
description to remove the duplicate word and tighten the phrasing to something
concise and clear such as: "The meter associated with the feature, used to
calculate usage." Replace the existing description line with the corrected text.

Comment on lines +17004 to 17018
maxLength: 256
description: |-
The unique key of the feature
Useful to reference the feature in external systems.
For example, your database ID.
title: The unique key of the feature
name:
type: string
description: The human-readable name of the feature
title: The human-readable name of the feature
metadata:
allOf:
- $ref: '#/components/schemas/Metadata'
description: Optional metadata
title: Optional metadata
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

🧩 Analysis chain

Key maxLength 256: confirm backing-store/index limits and validation stay in sync

Good widening for ExternalKey use. Please verify:

  • DB column and unique index for feature.key allow 256 chars (incl. collation/byte limits).
  • Any server-side/type-level validations (TypeSpec ExternalKey) also reflect 256 to avoid drift.

Run to check consistency across specs:

Also consider clarifying the example to “external system identifier” vs “database ID” to avoid implying numeric-only IDs.


🏁 Script executed:

#!/bin/bash
# Locate TypeSpec defs and OpenAPI lengths
fd -a -e tsp
rg -n "type\s+ExternalKey|type\s+Key|maxLength" -g "api/**"
rg -n "key:\s*\n[^\n]*\n[^\n]*\n\s*maxLength:\s*256" -n -g "api/**/*.yaml"

Length of output: 22461


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== Search for ExternalKey/type and @maxLength(256) in TypeSpec ==="
rg -nP --hidden -S "ExternalKey|type\s+ExternalKey" api/spec || true
rg -nP --hidden -S "@maxLength\(256\)" api/spec -n -C2 || true

echo
echo "=== types.tsp head (first 220 lines) ==="
nl -ba api/spec/src/types.tsp | sed -n '1,220p' || true

echo
echo "=== entitlements/feature.tsp ==="
nl -ba api/spec/src/entitlements/feature.tsp | sed -n '1,240p' || true

echo
echo "=== openapi.yaml around 16990-17030 ==="
nl -ba api/openapi.yaml | sed -n '16990,17030p' || true

echo
echo "=== Search for DB migrations or schema references mentioning 'feature' or 'key' lengths ==="
rg -n --hidden -S "CREATE TABLE.*feature|CREATE TABLE.*features|ALTER TABLE.*feature|ALTER TABLE.*features|CREATE INDEX.*feature|CREATE UNIQUE INDEX.*feature" || true
rg -n --hidden -S "key.*varchar\([0-9]+\)|key.*character varying\([0-9]+\)" || true

echo
echo "=== Search for model/ORM definitions referencing Feature or 'key' column ==="
rg -n --hidden -S "type\s+Feature\b|struct\s+Feature\b|class\s+Feature\b|FeatureModel|features\s*table" || true

Length of output: 8467


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== features table from initial migration ==="
awk '/CREATE TABLE "features" \(/,/\);/ {print}' tools/migrate/migrations/20240826120919_init.up.sql || true

echo
echo "=== lines containing \"key\" in that migration ==="
rg -n --hidden -S '"key"' tools/migrate/migrations/20240826120919_init.up.sql || true

echo
echo "=== unique index on features (fix-unique-indexes migration) ==="
sed -n '1,240p' tools/migrate/migrations/20250218103055_fix-unique-indexes.up.sql || true
rg -n --hidden -S 'feature_namespace_key|feature_key' tools/migrate || true

echo
echo "=== any migrations mentioning feature_key (types) ==="
rg -n --hidden -S '"feature_key"|feature_key' tools/migrate -n -C2 || true

echo
echo "=== ent schema: openmeter/ent/schema/feature.go ==="
sed -n '1,240p' openmeter/ent/schema/feature.go || true

echo
echo "=== ent db model: openmeter/ent/db/feature.go ==="
sed -n '1,240p' openmeter/ent/db/feature.go || true

echo
echo "=== TypeSpec ExternalKey (@maxLength) ==="
sed -n '1,120p' api/spec/src/types.tsp || true
rg -n --hidden -S "@maxLength\\(256\\)" api/spec || true

echo
echo "=== entitlements feature TypeSpec ==="
sed -n '1,220p' api/spec/src/entitlements/feature.tsp || true
rg -n --hidden -S "key:\\s*ExternalKey" api/spec || true

echo
echo "=== openapi.yaml around 16990-17030 ==="
sed -n '16990,17030p' api/openapi.yaml || true

echo
echo "=== search code for schema/validation references to 'key' length ==="
rg -n --hidden -S "MaxLen\\(|MaxLength|size\\(|Length\\(|VARCHAR\\(|character varying\\(|varchar\\(|@maxLength|@minLength" || true

echo
echo "=== done ==="

Length of output: 48954


Add server-side validation to match ExternalKey maxLength=256 (DB/index already compatible)

  • TypeSpec/OpenAPI: ExternalKey has @maxlength(256) (api/spec/src/types.tsp) and openapi.yaml shows key maxLength: 256.
  • DB: features.key is character varying (no length) in tools/migrate/migrations/20240826120919_init.up.sql and a unique index on (namespace, key) exists in tools/migrate/migrations/20250218103055_fix-unique-indexes.up.sql — 256-char values are supported.
  • Action required: update openmeter/ent/schema/feature.go — change field.String("key").NotEmpty().Immutable() to include .MaxLen(256) (optionally set SchemaType to varchar(256) and add a migration if DB-enforced limit is desired).
  • Nit: replace “For example, your database ID.” in api/spec/src/entitlements/feature.tsp with wording like “e.g., an external system identifier” to avoid implying numeric-only IDs.
🤖 Prompt for AI Agents
api/openapi.yaml around lines 17004-17018: the OpenAPI shows ExternalKey
maxLength=256 but the Ent schema does not enforce this; update
openmeter/ent/schema/feature.go to change
field.String("key").NotEmpty().Immutable() to include .MaxLen(256) (optionally
also call
.SchemaType(map[string]string{"mysql":"varchar(256)","postgres":"varchar(256)"})
and create a DB migration if you want DB-enforced length), and also update
api/spec/src/entitlements/feature.tsp to replace the phrase “For example, your
database ID.” with something like “e.g., an external system identifier.”

Copy link
Contributor

@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.

Actionable comments posted: 1

🧹 Nitpick comments (7)
api/client/javascript/src/client/schemas.ts (6)

5453-5455: Clarify ExternalKey semantics (UUIDs allowed, length, uniqueness, and safety).

Recommend documenting that this is an ExternalKey: accepts UUIDs, up to 256 chars, unique per workspace; avoid secrets/PII. Add clear examples.

Apply:

- * @description The unique key of the feature
- *     Useful to reference the feature in external systems.
- *     For example, your database ID.
+ * @description External identifier for this feature (ExternalKey).
+ *     String up to 256 characters; may be a UUID or any stable key your system owns.
+ *     Must be unique within the workspace. Avoid secrets/PII.
+ * @example "feat:chat-1k"
+ * @example "d290f1ee-6c54-4b01-90e6-d701748f0851"

5465-5465: Tighten metadata guidance (avoid sensitive data).

Suggest explicitly warning against storing secrets/PII in metadata since it may be logged or surfaced in UIs.

- * @description Optional metadata
+ * @description Optional metadata. Do not include secrets or PII.

5473-5473: Fix typo in meter description (“and and”).

- * @description The meter that the feature is associated with and and based on which usage is calculated.
+ * @description The meter this feature is associated with and on which usage is calculated.

5502-5505: Mirror ExternalKey details in create inputs.

Same clarification as above for the create payload to set expectations for clients.

- * @description The unique key of the feature
- *     Useful to reference the feature in external systems.
- *     For example, your database ID.
+ * @description External identifier for this feature (ExternalKey).
+ *     String up to 256 characters; may be a UUID or any stable key your system owns.
+ *     Must be unique within the workspace. Avoid secrets/PII.
+ * @example "feat:chat-1k"
+ * @example "d290f1ee-6c54-4b01-90e6-d701748f0851"

5514-5514: Repeat metadata safety note in create inputs.

- * @description Optional metadata
+ * @description Optional metadata. Do not include secrets or PII.

5522-5522: Fix repeated “and and” in create inputs meter description.

- * @description The meter that the feature is associated with and and based on which usage is calculated.
+ * @description The meter this feature is associated with and on which usage is calculated.
api/client/javascript/src/zod/index.ts (1)

7916-7921: Avoid whitespace‑only keys; merge duplicate metadata descriptions

  • Keys like " " will pass .min(1). Trim before validating to prevent accidental blanks.
  • Two consecutive .describe() calls on metadata: the latter overwrites the former. Merge into one final description.

If whitespace is intentionally allowed for ExternalKey, ignore the trim change.

Apply:

       .string()
+      .trim()
       .min(1)
       .max(createFeatureBodyKeyMax)
       .describe(
         'The unique key of the feature\nUseful to reference the feature in external systems.\nFor example, your database ID.'
       ),
     metadata: zod
       .record(zod.string(), zod.coerce.string())
-      .describe(
-        'Set of key-value pairs.\nMetadata can be used to store additional information about a resource.'
-      )
       .optional()
-      .describe('Optional metadata'),
+      .describe('Optional metadata. Set of key-value pairs. Metadata can be used to store additional information about a resource.'),

Also applies to: 7922-7929

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7331d5c and 5602d63.

📒 Files selected for processing (2)
  • api/client/javascript/src/client/schemas.ts (2 hunks)
  • api/client/javascript/src/zod/index.ts (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (4)
api/client/javascript/src/client/schemas.ts (2)

5458-5461: LGTM on name docs.


5508-5510: LGTM on name docs (create).

api/client/javascript/src/zod/index.ts (2)

7906-7906: Confirm OpenAPI/server parity for feature key maxLength (256) and remove stragglers

  • Found createFeatureBodyKeyMax = 256 and .max(createFeatureBodyKeyMax) in api/client/javascript/src/zod/index.ts (lines 7906, 7918).
  • No references to createFeatureBodyKeyRegExp were found.
  • api/openapi*.yaml wasn’t present at api/openapi*.yaml so OpenAPI parity couldn’t be verified — ensure OpenAPI specs and all server/client codepaths use maxLength: 256 and sweep for any remaining maxLength: 64 or legacy key-regex usages.

7939-7946: Fix typo in meterSlug description; optionally normalize name

  • Typo: "and and" → "and".
  • Optional: trim name input to avoid leading/trailing spaces; if name must be non‑empty add .min(1) after .trim().
  • Location: api/client/javascript/src/zod/index.ts (lines 7939-7946).

Apply:

       .describe(
-        'The meter that the feature is associated with and and based on which usage is calculated.'
+        'The meter associated with the feature and based on which usage is calculated.'
       ),
-    name: zod.coerce
-      .string()
+    name: zod.coerce
+      .string()
+      .trim()
       .describe('The human-readable name of the feature'),

If name must be non‑empty, additionally:

-      .trim()
+      .trim()
+      .min(1)

Verification: search for api/openapi*.yaml returned "No such file or directory"; cannot confirm OpenAPI contract — confirm whether "name" requires minLength:1.

Comment on lines 5450 to 5476
readonly archivedAt?: Date
/**
* The unique key of the feature
* @description A key is a unique string that is used to identify a resource.
* @description The unique key of the feature
* Useful to reference the feature in external systems.
* For example, your database ID.
*/
key: string
/** The human-readable name of the feature */
/**
* The human-readable name of the feature
* @description The human-readable name of the feature
*/
name: string
/**
* Optional metadata
* @description Optional metadata
* @example {
* "key": "value"
* }
*/
metadata?: components['schemas']['Metadata']
/**
* Meter slug
* @description A key is a unique string that is used to identify a resource.
* @description The meter that the feature is associated with and and based on which usage is calculated.
* @example tokens_total
*/
meterSlug?: string
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

Confirm source-of-truth (generated vs. hand-edited).

If this file is generated from OpenAPI/TypeSpec, ensure these doc changes originate in the spec and the client was re-generated; otherwise they’ll be overwritten on the next generation. Also confirm other language clients were regenerated to keep docs in sync.

Run:


🏁 Script executed:

#!/bin/bash
# Verify spec changes and regen consistency

# 1) ExternalKey constraints present (e.g., maxLength: 256) and no leftover key regex
rg -nC2 -e 'ExternalKey' -e 'maxLength:\s*256' -e 'pattern:' api/openapi*.yaml

# 2) No lingering meterKey in specs or clients
rg -nC2 -e '\bmeterKey\b' api/ spec/ packages/ clients/ -g '!**/node_modules/**'

# 3) JS zod validators reflect widened key (256) and no regex
rg -nC2 -e 'z\.\s*string\(\).*max\(\s*256' -e 'regex\(' api/client/javascript/src/zod

# 4) Other clients regenerated (adjust paths if different)
fd -H -t f -g 'schemas.*' api/client | sed -n '1,200p'

Length of output: 278130


Action required — spec/client mismatch: OpenAPI widened ExternalKey to 256 but JS validators still enforce old regex/64‑char constraints

api/openapi.yaml contains ULIDOrExternalKey / ExternalKey with minLength:1 maxLength:256 (e.g. the ULIDOrExternalKey component and the feature "key"), but api/client/javascript/src/zod/index.ts still has .regex() checks and 64‑length constraints and api/client/javascript/src/client/schemas.ts (lines 5450–5476) looks like generated docs that will be overwritten. Regenerate the JavaScript client (and any other language clients), or put the doc/constraint changes into the OpenAPI spec and then regenerate; confirm whether schemas.ts is generated or hand‑edited.

🤖 Prompt for AI Agents
In api/client/javascript/src/client/schemas.ts around lines 5450 to 5476, the
OpenAPI spec widened ULIDOrExternalKey/ExternalKey to minLength:1 maxLength:256
but the generated JS client still enforces the old 64‑char regex/length
constraints (and the docs in schemas.ts appear generated and will be
overwritten). Fix by regenerating the JavaScript client from the updated OpenAPI
spec so schemas.ts and api/client/javascript/src/zod/index.ts reflect the new
1–256 length and remove the old regex checks; if any zod validators were
hand‑edited instead of generated, revert them to generation or update the
OpenAPI component definitions and then regenerate all language
clients-consumers, and confirm whether schemas.ts is generated (if not, update
the source generator/templates) before committing.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant