Skip to content

fix(api): declare the entity-store name pattern on the remaining models DTOs [ASTD-420] - #921

Merged
marcusds merged 3 commits into
mainfrom
entity-name-pattern-spec/mschwab
Aug 13, 2026
Merged

fix(api): declare the entity-store name pattern on the remaining models DTOs [ASTD-420]#921
marcusds merged 3 commits into
mainfrom
entity-name-pattern-spec/mschwab

Conversation

@marcusds

@marcusds marcusds commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Problem

The entity store enforces ^[a-z](?!.*--)[a-z0-9\-@.+_]{1,62}(?<!-)$, max 63. #978 declared that on three DTOs — CreateModelProviderRequest, CreateFilesetRequest, PlatformSecretCreateRequest — and collapsed the constant into nemo_platform_plugin/entity_naming.py. The rest of the models service is still on the loose rule:

DTO declares on main
CreatePromptRequest ^[\w\-.]+$, max 255
CreateModelEntityRequest ^[\w\-.]+$, max 255
CreateModelAdapterRequest ^[\w\-.]+$, max 255
CreateModelDeploymentConfigRequest ^[\w\-.]+$, max 255
CreateModelDeploymentRequest ^[\w\-.]+$, max 255
ModelEntityBaseModel ^[\w\-.]+$, max 255

So Sparl or My_Prompt validates against the published spec, passes any generated client's validation, and then 422s from the entity store with loc: ['body', 'name'] — pointing at a body the caller never sent.

Change

Declare NAME_PATTERN + NAME_MAX_LENGTH on the six above. Read/lookup DTOs (Get*, List*, Delete*) keep the loose pattern so entities created before the rule stay reachable.

NAME_PATTERN uses lookaround, which pydantic's default rust-regex engine cannot compile, so affected models need regex_engine="python-re". #978 set that inline on the one DTO it touched; this lifts it to a module-level ENTITY_NAME_CONFIG rather than repeating the ConfigDict seven times, and switches the provider DTO over to it.

Not a compatibility break: any name that passes the loose pattern but fails the strict one already 422s at the entity store today. This moves the rejection to the edge, where the error can name the actual field.

Worth a reviewer's eye

ModelEntityBaseModel is a response base (ModelEntity, ModelDeployment subclass it), not a create request. Tightening it means an entity whose stored name predates entity-store enforcement would now fail response validation rather than being returned. The entity store has enforced this rule on the write path for a while, so there should be no such rows — but that assumption is worth confirming before merge. Happy to drop it from this PR and file it separately if you'd rather not carry the risk.

Testing

  • services/core/models/tests/unit — 977 passed, 1 skipped (torch)
  • New test_schemas_entity_names.py: 6 DTOs × invalid/valid names, plus asserts the emitted JSON schema carries the pattern and maxLength — 85 passed together with packages/nemo_platform_plugin/tests/files/test_types.py
  • ruff check, ruff format --check clean; the ty pre-commit hook passes

Note: this repo's shared venv installs the packages editable from the main checkout, so tests run from a worktree need PYTHONPATH pointed at the worktree's src dirs or they silently exercise main's code.

Spec regeneration

openapi/openapi.yaml and the two GA variants are regenerated. The diff is exclusively pattern / maxLength / description — no path or operation changes. Plugin specs regenerate with no diff.

Follow-up

packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/models.py still carries a hand-rewritten lookaround-free variant that has drifted (it accepts names up to 125 characters). Out of scope here — nemo_evaluator_sdk has no dependency on nemo_platform_plugin, so fixing it needs either a new dependency or an equivalence test.

Summary by CodeRabbit

  • Bug Fixes

    • Standardized resource-name validation across APIs and CLI commands.
    • Names must begin with a lowercase letter, contain 2–63 characters, and follow the supported character rules.
    • Invalid names, including uppercase, whitespace, slashes, consecutive hyphens, trailing hyphens, and out-of-range lengths, are now rejected consistently.
  • Documentation

    • Updated CLI help text and API descriptions to clearly explain the naming requirements.

@marcusds
marcusds requested review from a team as code owners July 27, 2026 19:36
@github-actions github-actions Bot added the fix label Jul 27, 2026
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: dc21d9ea-0643-4531-9cc0-53890cf86905

📥 Commits

Reviewing files that changed from the base of the PR and between c1182f7 and 90ac819.

⛔ Files ignored due to path filters (23)
  • sdk/python/nemo-platform/.nmpcontext/openapi.yaml is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/adapters.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployment_configs/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/models/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/models/adapters.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/adapters/adapters.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/inference/deployment_configs/deployment_configs.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/inference/deployments/deployments.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/inference/prompts.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/models/adapters.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/models/models.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/adapters/adapter_create_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/deployment_config_create_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/deployment_create_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/model_deployment.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/model_deployment_config.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/model_provider.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/prompt.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/prompt_create_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/models/adapter_create_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/models/model_create_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/models/model_entity.py is excluded by !sdk/**
📒 Files selected for processing (6)
  • docs/cli/reference.mdx
  • packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/adapters.py
  • packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployment_configs/__init__.py
  • packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.py
  • packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/models/__init__.py
  • packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/models/adapters.py

📝 Walkthrough

Walkthrough

The pull request standardizes entity-name validation across OpenAPI specifications, Pydantic request models, and CLI guidance. Names now use a 63-character lowercase pattern. Tests cover accepted names, rejected names, and generated schema metadata.

Changes

Name validation contract

Layer / File(s) Summary
OpenAPI name constraints
openapi/openapi.yaml, openapi/ga/openapi.yaml, openapi/ga/individual/platform.openapi.yaml
Resource and request name fields now enforce a 63-character maximum and lowercase naming pattern.
Shared runtime validation
services/core/models/src/nmp/core/models/schemas.py
Core request models use shared name constants and the python-re regex engine.
Validation and schema tests
services/core/models/tests/unit/test_schemas_entity_names.py, packages/nemo_platform_plugin/tests/files/test_types.py
Tests cover valid and invalid names and verify generated schema constraints.
CLI naming guidance
packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/..., docs/cli/reference.mdx
CLI help, validation messages, and reference documentation describe the updated naming rules.

Suggested reviewers: a2bondar

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately identifies the main change: applying the entity-store name pattern to remaining model DTOs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch entity-name-pattern-spec/mschwab

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (1)
packages/nemo_platform_plugin/tests/files/test_types.py (1)

13-13: 🚀 Performance & Scalability | 🔵 Trivial

No test guards parity across the 3 inlined NAME_PATTERN copies.

files/types.py, secrets/types.py, and nmp_common.entities.constants each define their own copy of the same pattern/description/max-length. A quick test asserting all three stay identical would catch future drift cheaply.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nemo_platform_plugin/tests/files/test_types.py` at line 13, In the
tests near the existing imports in test_types.py, add a focused parity test
comparing NAME_PATTERN, its associated description, and NAME_MAX_LENGTH from
files/types.py, secrets/types.py, and nmp_common.entities.constants. Import the
corresponding symbols from each module and assert all three definitions remain
identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nemo_platform_plugin/src/nemo_platform_plugin/files/types.py`:
- Around line 77-97: Update NAME_PATTERN_DESCRIPTION in
packages/nemo_platform_plugin/src/nemo_platform_plugin/files/types.py:77-97 to
document that names may also contain @, ., +, and _; make the same description
change to _NAME_DESCRIPTION in
packages/nemo_platform_plugin/src/nemo_platform_plugin/secrets/types.py:18-39 so
both descriptions accurately match the shared regex character class.

---

Nitpick comments:
In `@packages/nemo_platform_plugin/tests/files/test_types.py`:
- Line 13: In the tests near the existing imports in test_types.py, add a
focused parity test comparing NAME_PATTERN, its associated description, and
NAME_MAX_LENGTH from files/types.py, secrets/types.py, and
nmp_common.entities.constants. Import the corresponding symbols from each module
and assert all three definitions remain identical.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d1849205-8af8-487b-8892-1c7179f410c5

📥 Commits

Reviewing files that changed from the base of the PR and between 79b7d21 and ccf0286.

📒 Files selected for processing (11)
  • openapi/ga/individual/platform.openapi.yaml
  • openapi/ga/openapi.yaml
  • openapi/openapi.yaml
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/files/types.py
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/secrets/types.py
  • packages/nemo_platform_plugin/tests/files/test_types.py
  • packages/nmp_common/src/nmp/common/entities/constants.py
  • services/core/models/src/nmp/core/models/schemas.py
  • services/core/models/tests/unit/test_schemas_entity_names.py
  • services/core/secrets/tests/integration/test_secrets_with_auth.py
  • services/core/secrets/tests/test_secrets.py

Comment thread packages/nemo_platform_plugin/src/nemo_platform_plugin/files/types.py Outdated
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 32014/40717 78.6% 63.4%
Integration Tests 18573/38643 48.1% 20.8%

@marcusds
marcusds force-pushed the entity-name-pattern-spec/mschwab branch from ccf0286 to 5055ddb Compare July 28, 2026 20:15

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
openapi/openapi.yaml (1)

9344-9350: 🗄️ Data Integrity & Integration | 🔵 Trivial

Breaking change: maxLength reduced 255→63 on 8 create endpoints.

oasdiff flags these as breaking (request-property-max-length-decreased). Intentional per PR, but SDK/web-SDK regeneration is deferred, so generated clients won't enforce the new limit client-side until regenerated — surface this in release notes / API changelog.

Also applies to: 9401-9406, 9456-9462, 9500-9505, 9551-9556, 9586-9591, 9676-9681, 9808-9813

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openapi/openapi.yaml` around lines 9344 - 9350, Document the intentional
maxLength reduction from 255 to 63 for the adapter name schema across all eight
create endpoints in the release notes or API changelog. Clearly identify this as
a breaking API change and note that generated SDK and web-SDK clients will not
enforce the new limit until regeneration.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openapi/ga/openapi.yaml`:
- Around line 13975-13981: Update the duplicated Name schema definitions at all
referenced locations so the pattern matches the description: allow only
lowercase letters, digits, and hyphens, while preserving the lowercase-start,
2–63 character, no-consecutive-hyphens, and no-trailing-hyphen constraints.
Remove the unsupported @, ., +, and _ characters from each pattern.

In `@openapi/openapi.yaml`:
- Around line 9344-9350: Update the descriptions for all affected name schema
entries to state that names may contain lowercase letters, digits, hyphens,
periods, plus signs, underscores, and @ symbols, while retaining the existing
length, starting-letter, consecutive-hyphen, and trailing-hyphen constraints.
Apply the wording consistently to each listed occurrence without changing the
regex patterns.
- Around line 13975-13981: Relax the inherited name validation for the read DTOs
ModelDeployment, ModelDeploymentConfig, ModelEntity, ModelProvider, and Prompt
so GET/list responses can deserialize legacy uppercase or longer names. Keep the
strict ModelEntityBaseModel.name constraints for write/request validation,
separating read and write schemas where necessary without changing write
behavior.

In `@packages/nemo_platform_plugin/src/nemo_platform_plugin/secrets/types.py`:
- Around line 32-36: Update _NAME_DESCRIPTION in
packages/nemo_platform_plugin/src/nemo_platform_plugin/secrets/types.py:32-36 to
state that ., +, _, and @ are permitted, matching _NAME_REGEX. Regenerate the
PlatformSecretCreateRequest.name description in openapi/openapi.yaml:16464-16469
from the updated constant.

---

Nitpick comments:
In `@openapi/openapi.yaml`:
- Around line 9344-9350: Document the intentional maxLength reduction from 255
to 63 for the adapter name schema across all eight create endpoints in the
release notes or API changelog. Clearly identify this as a breaking API change
and note that generated SDK and web-SDK clients will not enforce the new limit
until regeneration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 71150676-3084-497a-8522-8dfc1d35814f

📥 Commits

Reviewing files that changed from the base of the PR and between ccf0286 and 5055ddb.

📒 Files selected for processing (11)
  • openapi/ga/individual/platform.openapi.yaml
  • openapi/ga/openapi.yaml
  • openapi/openapi.yaml
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/files/types.py
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/secrets/types.py
  • packages/nemo_platform_plugin/tests/files/test_types.py
  • packages/nmp_common/src/nmp/common/entities/constants.py
  • services/core/models/src/nmp/core/models/schemas.py
  • services/core/models/tests/unit/test_schemas_entity_names.py
  • services/core/secrets/tests/integration/test_secrets_with_auth.py
  • services/core/secrets/tests/test_secrets.py
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/nmp_common/src/nmp/common/entities/constants.py
  • services/core/secrets/tests/test_secrets.py
  • packages/nemo_platform_plugin/tests/files/test_types.py
  • services/core/models/tests/unit/test_schemas_entity_names.py
  • services/core/models/src/nmp/core/models/schemas.py
  • services/core/secrets/tests/integration/test_secrets_with_auth.py
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/files/types.py

Comment thread openapi/ga/openapi.yaml Outdated
Comment thread openapi/openapi.yaml Outdated
Comment thread openapi/openapi.yaml Outdated
Comment thread packages/nemo_platform_plugin/src/nemo_platform_plugin/secrets/types.py Outdated
…ls DTOs

#978 tightened three DTOs — `CreateModelProviderRequest`, `CreateFilesetRequest`,
`PlatformSecretCreateRequest` — and collapsed NAME_PATTERN into a single
definition in `nemo_platform_plugin/entity_naming.py`. The rest of the models
service was left on the loose rule.

`CreatePromptRequest`, `CreateModelEntityRequest`, `CreateModelAdapterRequest`,
`CreateModelDeploymentConfigRequest`, `CreateModelDeploymentRequest`, and the
shared `ModelEntityBaseModel` still advertise `^[\w\-.]+$` with max_length 255,
while the entity store enforces `^[a-z](?!.*--)[a-z0-9\-@.+_]{1,62}(?<!-)$` with
max 63. So `Sparl` passes request validation, passes any generated client's
validation, and then 422s from the entity store with `loc: ['body', 'name']`
pointing at a body the caller never sent.

Declare NAME_PATTERN and NAME_MAX_LENGTH on those six. Read and lookup DTOs keep
the looser pattern so entities created before the rule stay reachable.

NAME_PATTERN uses lookaround, which pydantic's default rust-regex engine cannot
compile, so the affected models need `regex_engine="python-re"`. #978 set that
inline on the one DTO it touched; this lifts it to a module-level
ENTITY_NAME_CONFIG rather than repeating the ConfigDict seven times.

Not a compatibility break: any name that passes the loose pattern but fails the
strict one already 422s at the entity store today. This moves the rejection to
the edge, where the error can name the actual field.

Regenerates openapi/openapi.yaml and the two GA variants — the diff is
exclusively pattern, maxLength, and description. Plugin specs regenerate with no
diff.

Signed-off-by: mschwab <mschwab@nvidia.com>
@marcusds
marcusds force-pushed the entity-name-pattern-spec/mschwab branch from 5055ddb to c1182f7 Compare August 12, 2026 16:31
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@marcusds marcusds changed the title fix(api): declare the entity-store name pattern on create requests fix(api): declare the entity-store name pattern on the remaining models DTOs Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openapi/ga/individual/platform.openapi.yaml`:
- Around line 14248-14254: The response schemas for ModelProvider, Prompt,
ModelEntity, ModelDeploymentConfig, and ModelDeployment should stop inheriting
the strict ModelEntityBaseModel name validation; introduce or reuse a permissive
response base model for read conversions from entity.name or entity.base_name,
while retaining the existing strict constraints on create request schemas.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 92ad2d24-c137-4869-b3f4-8a8d34fea184

📥 Commits

Reviewing files that changed from the base of the PR and between a8bd92b and c1182f7.

📒 Files selected for processing (6)
  • openapi/ga/individual/platform.openapi.yaml
  • openapi/ga/openapi.yaml
  • openapi/openapi.yaml
  • packages/nemo_platform_plugin/tests/files/test_types.py
  • services/core/models/src/nmp/core/models/schemas.py
  • services/core/models/tests/unit/test_schemas_entity_names.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • services/core/models/tests/unit/test_schemas_entity_names.py
  • packages/nemo_platform_plugin/tests/files/test_types.py
  • services/core/models/src/nmp/core/models/schemas.py

Comment thread openapi/ga/individual/platform.openapi.yaml
The name pattern and 63-character limit declared on the models DTOs had not
been propagated to the generated Python SDK, so lint-python-sdk failed with
the OpenAPI spec out of sync.

Signed-off-by: mschwab <mschwab@nvidia.com>
@marcusds marcusds changed the title fix(api): declare the entity-store name pattern on the remaining models DTOs fix(api): declare the entity-store name pattern on the remaining models DTOs [ASTD-420] Aug 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@marcusds
marcusds enabled auto-merge August 13, 2026 05:10
@marcusds
marcusds added this pull request to the merge queue Aug 13, 2026
Merged via the queue into main with commit 1941bd5 Aug 13, 2026
103 of 105 checks passed
@marcusds
marcusds deleted the entity-name-pattern-spec/mschwab branch August 13, 2026 05:41
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.

2 participants