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
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:
Field | Description |
---|---|
entity | The entity type the spec applies to (e.g. build , application , namespace ) |
metadata | A unique key for this metadata group (e.g. coverage , quality_insights ) |
schema | A JSON Schema defining the fields and rules |
nrn | The scope this spec applies to (e.g. an org, namespace, or account) |
name | Human-readable name (used in forms and dashboards) |
description | Optional 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
, ornamespace
) - The spec has at least one field
- That field is visible on creation (
visibleOn: ["create"]
) or has novisibleOn
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: