Nimblesite / Nimblesite/typeDiagram

[CRITICAL] Express field metadata (constraints, defaults, descriptions, aliases, config) so generated DTOs need zero hand-maintenance

Open
#39 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

CRITICAL
Dominant language
TypeScript
Stars
63
Forks
4
PR merge metrics
No merged PRs in 30d

Description

Make typeDiagram a complete single source of truth for API DTOs — full requirements

Companion to #38 (scalar types) and #29 (optional-vs-null). This is the complete list of what a contract-first DTO generator must express so consumers never hand-maintain a parallel copy. Every item below is something we currently CANNOT put in the .td and are therefore forced to hand-write in Python (Pydantic) — which then drifts from the contract. Each maps cleanly to Pydantic Field(...), C# DataAnnotations/JSON attributes, and OpenAPI.

1. Field-level constraints (validation metadata) — HIGHEST PRIORITY

Real fields we hand-maintain solely for these:

our field needed metadata
ChatRequest.message min_length=1, max_length=100_000
SshKeyRequest.public_key min_length=1, max_length=10_000
BundleFileWriteRequest.content max_length=2_000_000
ConversationSummary.message_count ge=0
ToolFileWriteRequest.mode ge=0, le=0o777
Manifest.build_command min_length=1, max_length=1000

Proposed syntax (attributes on the field):

type ChatRequest {
  message: Option<String> @minLen(1) @maxLen(100000)
}
type ConversationSummary {
  message_count: Int @min(0)
}

Constraint vocabulary: @minLen/@maxLen, @min/@max (inclusive), @exclusiveMin/@exclusiveMax, @multipleOf, @pattern("regex").
Lowering: Pydantic Field(min_length=, max_length=, ge=, le=, gt=, lt=, multiple_of=, pattern=); C# [MinLength]/[MaxLength]/[Range]/[RegularExpression]; OpenAPI minLength/maxLength/minimum/maximum/pattern.

2. Explicit default values (not just Option→null)

Fields whose default is a non-null literal — currently un-expressible:
ToolEntry.method = "POST", Manifest.template_dir = "template", ProvisionRequest.workspace_git_push_mode = "manual_only", ToolResultIn.ok = true.

type ToolEntry { method: String @default("POST") }

Lowering: Pydantic field default; C# property initializer; OpenAPI default.

3. String formats

@format(email|uri|uuid|date-time|hostname|ipv4|ipv6|byte) → Pydantic EmailStr/AnyUrl/Field(pattern=...), OpenAPI format.

4. Field descriptions / doc comments

Doc comments must survive into the output (Pydantic Field(description=...), C# XML ///, OpenAPI description). Example we hand-maintain: MessageResponse.tool_calls has a paragraph explaining the content/tool_calls split.

type MessageResponse {
  /// Tool calls emitted this turn, separate from `content` so UIs can hide tool activity.
  tool_calls: List<ToolCallOut>
}
5. Field aliases (wire name ≠ language name)

We have from_: str = Field(alias="from", serialization_alias="from") because from is a Python keyword. Need @alias("from") → Pydantic alias + populate_by_name, C# [JsonPropertyName].

6. Model-level config

@extra(forbid|ignore|allow), @frozen. We use extra="forbid" on request DTOs to reject typos (ConversationSummary, WorkspaceInstanceSummary) and extra="ignore" elsewhere. Lowering: Pydantic model_config = ConfigDict(extra=, frozen=); C# record immutability / JsonExtensionData.

7. @example(...) and @deprecated

For OpenAPI/docs quality: per-field examples and a deprecation marker.

8. (from #38) native DateTime/Uuid/Decimal scalars + fail-closed on unknown type identifiers.
Why this is critical infrastructure

With items 1–6 NAP can delete its entire hand-written DTO module and generate 100% from the .td. Without them, every constrained/aliased/defaulted/documented field forces a hand copy, the hand copy drifts, and we ship incidents (the conversation-history leak we just fixed was exactly this failure mode). We will adopt a patch build the moment 1, 2, and 4 land — those three remove ~90% of our hand-maintenance.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the existing .td syntax and the lowering requirements for Pydantic, C# attributes, and OpenAPI described here; review #38 and #29 for related scalar and optional/null behavior. Done means the requested field constraints, defaults, and doc comments can be expressed in the contract and preserved in generated DTO outputs, with the remaining metadata requirements clearly covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, openapi, python, typescript
Domain
backend-api-design, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.