Skip to main content

Special JSON schema keys

Inside your services and scopes (and their links/actions), and catalogs, you define JSON schemas that specify the attributes of each specification. Within those schemas, a set of keys has special meaning across the platform. Get familiar with them to implement specs effectively.

List of special keys​

These are the special keys you should know about:

KeywordDescriptionApplicable toMore
secretMark attributes within a service or link as secret.• Services
• Scopes
See the secret section.
exportExport an attribute value as an application parameter.• Services
• Scopes
See the export section.
exportIgnoreExclude attributes when exporting values to application parameters.• Services
• Scopes
See export ignore.
targetMap an action result to an attribute in a service, catalog, scope, or link.• Services
• Scopes
See target.
configUse it to determine whether an attribute or action parameter retrieves its value from an NRN entry.• Services
• Scopes
See config.
additionalKeywordsPopulate schema keywords dynamically from runtime context (instance, application, services, scopes) or external data.• Services
• Scopes
See additional keywords.
comparableExclude attributes from diff/compare views to avoid noisy changes.• Services
• Scopes
See comparable.
visibleOnControl property visibility by lifecycle stage (create, read, update).• Services
• Scopes
• Catalogs
See visibleOn.
editableOnControl when a property is editable by lifecycle stage.• Services
• Scopes
• Catalogs
See editableOn.
comparableExclude attributes from diff/compare views to avoid noisy changes.• Services
• Scopes
See comparable.
$dataReference other fields in validation keywords to enforce cross-property rules.• Services
• Scopes
See cross-property validation.

Secret​

Use secret: true to mark sensitive attributes within a service, scope, or link as secret so they're hidden/redacted in responses and the UI.

{
"attributes": {
"schema": {
"password": {
"type": "string",
"secret": true,
"readOnly": true
}
}
}
}
note

If you have an action, remember to add the secret keyword to the parameters and results of the associated secret attribute.

Export​

Export an attribute’s value as an application parameter. The field can be either boolean or an object.

  • Boolean form
    • true: export as an environment variable using the spec slug and the attribute name.
    • false: do not export (equivalent to omitting the field).
  • Object form
{
"type": "environment_variable" | "file",
"target": "name-of-the-env-var-or-file",
"secret": true | false
}

When using the object variant, note that:

  • The target parameter allows expression evaluation using the service and link as variables, for example:
    {
    "type": "environment_variable",
    "target": "${service.slug}_${link.slug}",
    "secret": false
    }

Exporting a secret​

If you need to export a sensitive value, set secret: true so the platform generates a secret parameter in your application.

{
"attributes": {
"schema": {
"password": {
"type": "integer",
"export": {
"secret": true
},
"readOnly": true
}
}
}
}

Export ignore​

Use exportIgnore at the object level to exclude attributes when exporting values to application parameters.

exportIgnore: "my_attribute"
// or
exportIgnore: ["my_attribute", "another_attribute"]

Target​

Use target to map an action result to an attribute in your service or link.

 {
"id": "12341234-4321-abcd-134-abcd1324bdcda",
"name": "S3 Bucket Update Action",
"slug": "s3-bucket-update-action",
"type": "update",
// ... more properties
"results": {
"schema": {
"type": "object",
"required": [
"bucket_arn",
"bucket_id"
],
"properties": {
"bucket_id": {
"type": "string",
"target": "bucket_id"
// <== the action's result 'bucket_id' will be assigned to the service's 'bucket_id'
},
"bucket_arn": {
"type": "string",
"target": "bucket_arn"
// <== the action's result 'bucket_arn' will be assigned to the service's 'bucket_arn'
}
}
},
"values": {}
}
}
Targets must be explicit

Attributes are not auto-mapped. You must declare a target for each result you want to persist.

Config​

This config keyword tells nullplatform to map a field to an NRN key.

Here's an example where the account_id field will be filled with the aws.account_id key from the NRN API:

{
"id": "12ced23430-bbff-495b-bbff-02fed729b0",
"name": "Dynamo DB",
"slug": "dynamodb",
"type": "dependency",
// ... service spec
"attributes": {
"schema": {
"account_id": {
"type": "string",
"config": {
// Here account_id will automatically take
// the value from NRN's aws.account_id key
"key": "aws.account_id"
},
"export": false,
"readOnly": true
}
}
}
}

Additional keywords​

Use additionalKeywords to make schema keywords dynamic using data from the current service instance, link, application, scopes, or the parent namespace and account.

Example: building enums dynamically​

{
"roles": {
"type": "array",
"items": {
"type": "string",
"additionalKeywords": {
"enum": ".service.attributes.availableRoles"
}
}
}
}

You can apply additionalKeywords to any JSON Schema keyword (enum, default, minimum, maximum, …). Values are jq filters applied to a context of the form:

{
"service": { ... },
"link": { ... },
"scope": { ... },
"application":{ ... },
"scopes": [{ ... }, { ... }],
"services": [{ ... }, { ... }],
"namespace": { ... },
"account": { ... },
"dimensions": { ... },
"external": { ... }
}
keyword details

Each key is only present when the request carries the matching context parameter (service_id, link_id, scope_id, application_id, dimensions). The namespace and account keys are derived automatically from whichever entity you pass — you don't need to request them explicitly.

  • service: The attributes of a specific service. You can reference values directly within the service. Present when service_id is passed.
  • link: The attributes of a service link. You can reference values directly within the link. Present when link_id is passed.
  • scope: The attributes of a specific scope. Present when scope_id is passed.
  • application: The attributes of the application. You can reference values directly within the application. Present when application_id is passed.
  • scopes: All active scopes within the application. For example, it allows you to select services by scope_slug. Present when application_id is passed.
  • services: All active services within the application. For example, it allows you to select services by specification_id. Present when application_id is passed.
  • namespace: The namespace the resolved entity belongs to. Derived automatically by walking up the NRN of the service, link, scope, or application in context. Use it to reference namespace-level metadata (e.g. .namespace.slug).
  • account: The account the resolved entity belongs to. Derived automatically from the same NRN cascade as namespace. Use it to reference account-level metadata (e.g. .account.slug).
  • dimensions: The resolved dimensions for the request, taken (in priority order) from the scope, the explicit dimensions query parameter, the link, or the service.
  • external: Data fetched from your infrastructure via the nullplatform agent. Only available when the specification has an external field configured. Use it to populate dropdowns with real-time values like database users, DNS zones, or cloud resources.
  • Practical examples of using additionalKeywords with different jq filters:

    {
    "additionalKeywords": {
    "enum": ".service.attributes.availableRoles",
    "enum": ". | [.scopes[]?.slug // \"You need to create an scope\"]",
    "enum": "[.services[] | select(.specification_id == \"xxx\") | .slug] | if length == 0 then [\"You need to create a yyyy\"] else . end",
    "default": ".application.metadata.my_metadata",
    "default": ".namespace.slug",
    "default": ".account.slug"
    }
    }

visibleOn​

Control visibility by lifecycle stage of the instance (service, catalog entity, or scope).

  • create: visible when creating the instance
  • read: visible when reading/viewing
  • update: visible when editing
  • list: visible as list columns (only available for builds right now)
{
"attributes": {
"schema": {
"my_property": {
"type": "string",
"visibleOn": ["create", "update"]
}
}
}
}
note

If empty, the default setting is "visibleOn": ["read", "create", "update"].

editableOn​

Control when a property is editable by lifecycle stage.

  • create, read, update

If empty, the property is not editable in any stage.

{
"attributes": {
"schema": {
"my_property": {
"type": "string",
"editableOn": ["create"]
}
}
}
}

This indicates that my_property is only available to be set when the instance is being created.

note

If empty, the default setting is "editableOn": ["read", "create", "update"].

comparable​

To avoid noisy diffs, you can mark attributes non-comparable in your service specification using the comparable: false flag.

  • Default is true.

Example:

{
"attributes": {
"schema": {
"account_id": {
"type": "string",
"config": { "key": "aws.account_id" },
"export": false,
"readOnly": true,
"comparable": false
}
}
}
}

These attributes will be excluded from diff outputs.

Cross-property validation ($data)​

Forms generated from JSON Schema support cross-property validation using AJV’s $data extension. Use it to express rules like “field A must be greater than field B” directly in the schema.

Example: interval must be greater than timeout​

{
"type": "object",
"properties": {
"timeout": {
"type": "number",
"title": "Timeout (seconds)"
},
"interval": {
"type": "number",
"title": "Interval (seconds)",
"exclusiveMinimum": { "$data": "1/timeout" }
}
}
}
  • "$data": "1/timeout" is a relative JSON Pointer: 1 = parent object, timeout = property.
  • Because this uses exclusiveMinimum, interval must be strictly greater than timeout.

Other keywords such as minimum, maximum, minLength, and maxLength can also use $data for cross-field rules.