Application config-schema

When you publish a software release through Dev2M, you may declare an application config-schema: the set of shared configuration keys your application reads on the device, with their types, defaults, and validation.

The schema is your published statement of what your application reads. It is validated when you create the release, stored as part of that release’s immutable evidence, and returned whenever the release is read back — so the contract a device owner configures against is the one you shipped with that exact version, and it cannot drift from it.

You declare the contract; the device owner (or the owner’s delegate) authors the per-device values. A publisher never writes per-device configuration.

Declaring a config-schema is optional — a release without one is valid.

Where it goes

The config-schema is a field on the release body you submit when creating a release:

POST /software-publishing/v1/products/{productId}/releases

or, with the CLI:

fgai publisher release-create --product <product-id> --body-file release.json

Shape

{
  "configSchema": {
    "namespace": "clean-suite",
    "keys": [
      { "key": "cleaning_schedule", "type": "string", "default": "nightly",
        "enum": ["nightly", "hourly", "manual"], "description": "when to run" },
      { "key": "max_speed", "type": "number", "default": 0.8 },
      { "key": "site_id", "type": "string", "required": true }
    ]
  }
}

Rules

Field

Rule

namespace

required; ^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$; 3–63 chars

keys

required, non-empty; at most 64 entries

keys[].key

required, unique; ^[a-z][a-z0-9_]*$; 1–64 chars

keys[].type

required; one of string, integer, number, boolean

keys[].default

required on a non-required key — it is the value your application must assume when the owner has set nothing; forbidden on a required: true key (the operator must set it)

keys[].enum

optional (not allowed for boolean); non-empty, de-duplicated, every member type-matched; any default must be a member

keys[].required

optional boolean

keys[].description

optional string; at most 200 chars

Unknown top-level or per-key fields are rejected.

Validation errors

A malformed declaration is rejected before it is persisted, with HTTP 400 and a stable validation_failed error whose fields list points at the exact offending path — so you can surface a precise message:

{ "error": "validation_failed",
  "fields": ["configSchema.namespace", "configSchema.keys[0].default"] }

Example field tokens: configSchema.namespace, configSchema.keys[2].default, configSchema.keys[0].enum, configSchema.keys[1].type.

Release immutability

A release’s published evidence — including its config-schema — is immutable. Re-publishing the same product version + artifact digest returns HTTP 409:

{ "error": "immutable_release_exists" }

To change a config-schema, publish a new release version.

Who writes the values

The schema is a contract, not a write channel. Configuration values live on the device’s own attribute surface, and exactly one party may write them for a given scope: the device owner, or the single delegate the owner has appointed. A publisher is never that writer, even for its own application’s keys.

Two consequences to design for:

  • Read your keys defensively. A key the owner has never set is absent on the device, not present-with-your-default. Apply the default you declared yourself; treat a required: true key that is missing as a configuration error your application reports, not as a value to invent.

  • The namespace is your vocabulary everywhere. Use the same slug for your application’s config-schema namespace that you use for its telemetry app namespace, so one name spans what your application reads, what it reports, and what an owner grants you access to.