Skip to content

docs(api-reference): type remaining nullable/object org fields - #256

Merged
aaitor merged 2 commits into
mainfrom
docs/org-spec-nullable-object-cleanup
Jul 29, 2026
Merged

docs(api-reference): type remaining nullable/object org fields#256
aaitor merged 2 commits into
mainfrom
docs/org-spec-nullable-object-cleanup

Conversation

@aaitor

@aaitor aaitor commented Jul 29, 2026

Copy link
Copy Markdown
Member

Mirrors nevermined-io/nvm-monorepo#2538 — completes the Organizations OpenAPI object-type cleanup so no field renders as a bare type: object.

Adds 3 component schemas (BrandingDto, OrganizationStripeConfigDto, OrganizationActivitySubjectDto) and re-types 10 fields:

Field Was Now
OrganizationMemberWithProfileDto.name / .stripeAccountId object string, nullable
CustomerResponseDto.userName / .userEmail object string, nullable
OrganizationActivityEventResponseDto.actorUserId object string, nullable
CreateOrganizationDto.branding object $ref BrandingDto
CreateOrganizationDto.live / .sandbox object $ref OrganizationStripeConfigDto
OrganizationActivityEventResponseDto.subject object $ref OrganizationActivitySubjectDto
OrganizationActivityEventResponseDto.metadata object object + additionalProperties (free-form)

Field defs copied verbatim from the generated schemas (verified against the backend DTOs). All $refs resolve; a full scan confirms zero structureless type: object properties remain in the spec.

Test plan

  • All $refs resolve; 89 schemas; 0 remaining bare type: object
  • Mintlify validation

Mirrors nvm-monorepo #2538 — completes the org-spec object-type cleanup.

Adds BrandingDto, OrganizationStripeConfigDto, OrganizationActivitySubjectDto
and re-types 10 fields that rendered as bare `type: object`:

- Scalars -> string: OrganizationMemberWithProfileDto.name/.stripeAccountId,
  CustomerResponseDto.userName/.userEmail, ActivityEvent.actorUserId
- Nested DTOs: CreateOrganizationDto.branding/live/sandbox, ActivityEvent.subject
- Free-form map: ActivityEvent.metadata -> additionalProperties
Copilot AI review requested due to automatic review settings July 29, 2026 09:16
@aaitor
aaitor requested a review from a team as a code owner July 29, 2026 09:16
@mintlify

mintlify Bot commented Jul 29, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Nevermined 🟢 Ready View Preview Jul 29, 2026, 9:17 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Copilot AI 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.

Pull request overview

Updates the Organizations OpenAPI spec to eliminate “bare” type: object fields by introducing explicit component schemas and retyping previously-ambiguous properties, improving generated API docs and client/schema tooling.

Changes:

  • Re-typed several previously-object fields to string with nullable: true where the backend returns null.
  • Replaced inline type: object blobs with $ref-based component schemas for organization branding, Stripe config, and activity subjects.
  • Made metadata explicitly free-form via additionalProperties: true to avoid structureless object rendering.
Comments suppressed due to low confidence (1)

docs/api-reference/organizations-openapi.json:7512

  • accountUpdatedAt is described as an ISO timestamp but is missing format: "date-time" (other ISO timestamp fields in this spec include the date-time format), which can reduce schema clarity and tooling support.
          "accountUpdatedAt": {
            "type": "string",
            "description": "ISO timestamp the account was last updated"
          },

Comment thread docs/api-reference/organizations-openapi.json

@r-marques r-marques left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Automated PR review — 🟡 Mergeable with nits

Reviewed origin/main...HEAD (1 file, +155/−23) with a read-only panel: general code review, a source-accuracy cross-check against the nvm-monorepo backend, and a spec-consistency sweep.

Rather than trust the "copied verbatim / verified against the backend DTOs" claim, I checked all three new schemas field-by-field against the source — and they hold up. BrandingDto matches apps/api/src/organizations/dto/save-branding-dto.ts exactly (13 fields, same descriptions and examples); OrganizationStripeConfigDto matches the Stripe interface at libs/commons/src/lib/types/MetadataTypes.ts:107 exactly (6 fields, correct optionality/nullability — accountType really is 'express' | 'standard' | null); the retyped scalars match the type: String additions in nvm-monorepo#2538. No invented fields, none missing. The required arrays line up precisely with the decorators too: actorUserId/metadata/userName/userEmail correctly stay optional, name/stripeAccountId/subject/kind/id correctly required.

Mechanically it's clean: JSON parses, no duplicate keys, every $ref resolves, no name collisions with the sibling openapi.json, no .mdx page left stale, and the spec is openapi: 3.0.0 so nullable: true is legal here.

Measured effect: I ran @redocly/cli lint on base vs. HEAD. Base reports no-invalid-schema-examples: 4; HEAD reports zero, with every other rule count identical (29 warnings → 25, 0 new findings, no new unused components). This PR does exactly what it says.

No blockers. Three things worth fixing, mostly because they'd propagate into generated clients.

🟡 Should fix (3)

  • OrganizationActivitySubjectDto is a closed schema, but the contract is opendocs/api-reference/organizations-openapi.json:7520. The description advertises { kind, id, ...extra }, the backend field is typed subject!: { kind: string; id: string; [key: string]: unknown } (an index signature — extras are genuinely part of the contract), and the upstream class JSDoc even says "event types may attach extra keys, so the object is open (additionalProperties)" — yet neither this schema nor the upstream DTO actually declares it. Anything generating types from this spec will silently drop every extra key, which is precisely the payload that makes an activity event useful. Wants "additionalProperties": true. Since the source contradicts itself, fix it in #2538 and mirror down rather than patching only the docs side.

  • accountType is a nullable enum that doesn't list null:7491. It's {"type": "string", "enum": ["express","standard"], "nullable": true}, but in OpenAPI 3.0 nullable: true does not add null to an enum; per the OAS docs, "null must be explicitly included in the list of enum values. Using nullable: true alone is not enough." The backing type is 'express' | 'standard' | null, so as written the documented type can't express the real one. Worth noting neither redocly nor spectral's core ruleset flags this, so no tooling will ever catch it. Same fix belongs upstream.

  • The upstream source PR is still open, and nothing here would detect divergence — nvm-monorepo#2538 is OPEN, this file is hand-maintained, and the repo's only workflow is publish-skill-clawhub.yml (no spec lint or diff gate). Both fixes above live upstream, so #2538 will likely move. Merging this first is safe for correctness — #2538 changes only Swagger annotations, not runtime response shapes, so nothing here misdescribes the live API — but it does mean silent drift if the upstream shape shifts. Suggest gating on #2538 landing, or re-diffing once it does.

💡 Good to have (4)

  • Two of the three new schemas are unreachable from any endpoint. BrandingDto (:7412) and OrganizationStripeConfigDto (:7482) are referenced only by CreateOrganizationDto, and no path in this spec references that schema — /organizations documents only putUpdateOrganizationDto. So 3 of the 10 retyped fields (branding, live, sandbox) won't render for readers at all. The orphan pre-dates this PR (redocly flags the same 2 unused components on base), but since the PR is about what readers see, it's worth deciding: is a create-organization endpoint missing from the spec, or should CreateOrganizationDto be pruned? (OrganizationActivitySubjectDto is reachable, so that third of the change does land.)

  • The sandbox example regressed, and it's recoverable without dropping the $ref. The removed inline examples distinguished acct_1234567890 (live) from acct_test_1234567890 (sandbox); both now point at one shared schema, so readers see a live-looking ID in the sandbox slot. OAS 3.0 allows example as an allOf sibling — and this file already does exactly that at CustomerResponseDto.status (:5904, description + example + allOf). So a per-property example can go straight back on live/sandbox.

  • The two new timestamps carry neither format nor an example:7505, :7509. accountCreatedAt/accountUpdatedAt are type: string described as "ISO timestamp". In fairness the file is genuinely split on this (10 *At string props with format: date-time, 10 without), so it's not a convention violation — but these two are the only *At properties with neither, leaving the wire format in prose alone. Same for accountType and additionalInformation, which have no examples.

  • One bare type: object still renders shapeless:3074, the 200 response of GET /organizations/{orgId}/ai-catalog.json. The description's claim of "zero structureless type: object properties" is accurate as worded (this is a response body, not a property), but it's the last thing in the spec rendering without structure — worth either sweeping in or explicitly scoping out.

📌 Repo hygiene (unrelated to this diff)

CLAUDE.md:392 and :590 both say not to modify docs/api-reference/, and the "Generated files — never edit by hand" list (:21-27) doesn't mention organizations-openapi.json. #253#256 have established the opposite in practice. One line naming organizations-openapi.json and openapi.json as hand-maintained mirrors of the NestJS Swagger output would stop the next contributor (or agent) either refusing to touch this file or clobbering it with a fresh export.

✅ Strengths

  • The accuracy claim in the description genuinely holds — every field of all three schemas checked against source, including optionality and nullability, with no drift found.
  • Correctly did not add branding/stripe fields to UpdateOrganizationDto: the backend has none, so the asymmetry is faithful rather than an oversight.
  • The absent required arrays on BrandingDto/OrganizationStripeConfigDto are right, not sloppy — every backing field is @ApiPropertyOptional.
  • Modelling metadata as object + additionalProperties: true is the correct call for a genuinely free-form payload, and strictly better for readers than the previous bare object.
  • Measurably zero regression: 4 lint findings fixed, 0 introduced.
  • The upstream PR pairs this with a regression guard (registering these DTOs in the response-envelopes.spec.ts object sweep), so this defect class shouldn't quietly return.

r-marques
r-marques previously approved these changes Jul 29, 2026
…ivitySubjectDto

Mirrors nvm-monorepo #2538 review fix: the activity `subject` is now an
inline open object (`{ kind, id }` + additionalProperties) matching its
description, instead of a `$ref` to a closed DTO that dropped the extra keys.
@aaitor
aaitor merged commit d7ca571 into main Jul 29, 2026
3 checks passed
@aaitor
aaitor deleted the docs/org-spec-nullable-object-cleanup branch July 29, 2026 10:45
@mintlify

mintlify Bot commented Jul 29, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Nevermined 🟡 Building Jul 29, 2026, 9:16 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

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.

3 participants