Skip to main content

Define catalog specifications

A catalog specification defines the structure, validation rules, and display behavior for metadata attached to entities in nullplatform—like applications, builds, and namespaces.

Each specification acts as a template: it tells the platform what fields should be available for a given entity, how those fields should behave (e.g., enum vs. free text), and how they should be displayed.

Once a spec is defined, nullplatform can:

  • Autogenerate form sections during entity creation
  • Render editable metadata in dashboards
  • Enforce validation for all updates—whether from the UI or API
Catalog specs are created via API

Once defined, they automatically power the UI for forms and metadata display.

What a catalog specification includes

Each spec is a JSON object with the following fields:

FieldDescription
entityThe entity type the spec applies to (e.g. build, application, namespace)
metadataA unique key for this metadata group (e.g. coverage, quality_insights)
schemaA JSON Schema defining the fields and rules
nrnThe scope this spec applies to (e.g. an org, namespace, or account)
nameHuman-readable name (used in forms and dashboards)
descriptionOptional description for users filling out the metadata

How to create a specification (API)

You can create a spec with a POST request to create a catalog specification

curl -L -X POST 'https://api.nullplatform.com/metadata/metadata_specification' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token>' \
-d '{
"name": "Namespace tags",
"description": "Add tags as key-value object to namespace entities",
"nrn": "organization=1",
"entity": "namespace",
"metadata": "tags",
"schema": {
"type": "object",
"properties": {
"my_string_property": {
"type": "string",
"tag": true
},
"my_number_property": {
"type": "number",
"default": 0,
"tag": "my_custom_tag_name"
},
"my_object_property": {
"type": "object",
"properties": {
"my_nested_property": {
"type": "string"
}
}
}
},
"required": [
"my_string_property"
],
"additionalProperties": false
}
}'

Example: autogenerate forms during entity creation

When you create an application, build, or namespace, nullplatform checks for a matching catalog specification. If one exists, it automatically adds a metadata form to the creation flow—no manual UI work needed.

Users fill out fields defined in the schema, with live validation. Once saved, metadata is attached to the entity and available in dashboards or for editing later.

This means structured data collection becomes a natural part of onboarding — no extra steps.

A metadata form is shown if:

  • A catalog spec exists for the entity type (application, build, or namespace)
  • The spec has at least one field
  • That field is visible on creation (visibleOn: ["create"]) or has no visibleOn at all

If no matching spec is found, the form step is skipped.

Example of a form the create a namespace:

{
"entity": "namespace",
"metadata": "operational",
"nrn": "organization=1:account=2",
"description": "Add operational and organizational information as tags to namespace entities",
"name": "Namespace Operational Tags",
"schema": {
"type": "object",
"properties": {
"business_unit": {
"type": "string",
"title": "Business Unit",
"description": "The business unit or division owning this namespace",
"tag": true
},
"compliance": {
"type": "string",
"visibleOn": [
"read",
"update",
"create",
"list"
],
"enum": [
"PCI",
"HIPAA",
"GDPR",
"None"
],
"title": "Compliance Requirements",
"description": "Regulatory standards applicable to this namespace",
"tag": "compliance_tag"
},
"deployment_frequency": {
"type": "string",
"enum": [
"daily",
"weekly",
"monthly",
"on_demand"
],
"title": "Deployment Frequency",
"description": "How often this namespace is deployed",
"tag": true
},
"incident_history": {
"type": "number",
"title": "Incident Count (Last 90 days)",
"description": "Number of incidents involving this namespace in the last 90 days",
"tag": true
},
"last_audit": {
"type": "string",
"format": "date",
"title": "Last Audit Date",
"description": "The most recent date this namespace was audited"
}
},
"required": [
"business_unit",
"deployment_frequency"
],
"additionalProperties": false
}
}

Example: application type spec

This example defines a simple dropdown for selecting an application type when creating or editing an app.

{
"name": "Application type",
"entity": "application",
"metadata": "apptype",
"nrn": "organization=123",
"schema": {
"type": "object",
"properties": {
"application_type": {
"type": "string",
"oneOf": [
{ "const": "public", "title": "Public Application" },
{ "const": "private", "title": "Private Application" },
{ "const": "internal", "title": "Internal Application" }
],
"visibleOn": ["create", "read", "update"]
}
},
"required": ["application_type"],
"additionalProperties": false
}
}

Once saved, this spec:

  • Renders a dropdown during app creation.
  • Appears under the Metadata panel on the application dashboard.
  • Can be edited later using the Show all button.

Example: build quality insights

This spec defines metrics shown in the build detail view (like coverage_percent, technical_debt_minutes, and complexity):

{
"name": "Build Quality Insights",
"entity": "build",
"metadata": "quality_insights",
"nrn": "organization=123",
"schema": {
"type": "object",
"properties": {
"coverage_percent": {
"type": "integer",
"description": "Coverage % for this build",
"visibleOn": ["create", "update", "read", "list"]
},
"technical_debt_minutes": {
"type": "integer",
"description": "Time-based tech debt metric",
"visibleOn": ["create", "update", "read"]
},
"complexity": {
"type": "integer",
"description": "Code complexity score",
"visibleOn": ["read"]
},
"vulnerabilities": {
"type": "integer",
"description": "Known vulnerabilities in this build",
"visibleOn": ["read", "update"]
}
},
"required": ["coverage_percent", "technical_debt_minutes", "complexity", "vulnerabilities"],
"additionalProperties": false
}
}

Once attached to a build, this spec:

  • Renders directly in the "Quality Insights" section of the build dashboard.
  • Some fields editable, some read-only.
  • Taggable and usable in filters if tag is also defined

Tagging fields for filters and dashboards

You can mark any field in a schema as a tag, which makes it available for:

  • Dashboard filtering
  • Metadata-based search
  • Integration with third-party tools (e.g., FinOps, inventory systems)

To tag a field, use the "tag" key:

{
"business_unit": {
"type": "string",
"tag": true
},
"platform_type": {
"type": "string",
"enum": ["web", "mobile"],
"tag": "platform"
}
}
  • "tag": true uses the field name as the tag key.
  • "tag": "custom_name" lets you define your own key.

Next steps

Once your catalog spec is defined: