FlowDrop Workflow Specification 1.0-draft

The published contract carries structure and nothing else

What a caller is told about an input is built from the bound port's own schema, reduced to the keys that describe the value's shape. Annotations are re-attached when the contract is read, not stored in it.

The rule

Normative: this is the rule
  1. Each contract fragment is built from the schema of the port its entry binds, and reduced to exactly these keys: type, enum, format, default, required, properties, items, minimum, maximum, minLength, maxLength and pattern.
  2. Every other key is dropped, at every depth, recursing into each declared property and into an item schema.
  3. Annotations such as title, description and examples, and any extension key, therefore never reach the stored contract; annotations are re-attached only when the contract is read with annotation requested.

What it means

A contract fragment is a reduction of the bound port's own schema down to a fixed set of structural keys — the shape of the value, never the words around it. The strip is not a top-level filter: it recurses into every declared property and into an item schema, so an annotation or an extension key buried two levels inside an object's own properties is dropped exactly as one sitting at the top would be. A non-annotation key at that same depth — maxLength, pattern — survives, because the rule drops a closed set of keys, not "annotations" as a category.

Author-facing words are never baked into the stored snapshot, even when the caller asks nothing special: they are re-attached only when the contract is read with annotation explicitly requested (MAN-6). The stored contract itself stays the same either way.

Example

A port's own schema carries a title and two extension keys, one nested inside properties and one inside items.

A port's declared schema, annotated at every depth
{
  "type": "object",
  "title": "Payload",
  "x-exposed-by-default": false,
  "properties": {
    "inner": { "type": "string", "title": "Inner", "x-config-order": 3, "maxLength": 10 }
  },
  "items": { "type": "string", "description": "An item.", "x-port-order": 2, "pattern": "^a" }
}
What the published contract keeps
{
  "type": "object",
  "properties": { "inner": { "type": "string", "maxLength": 10 } },
  "items": { "type": "string", "pattern": "^a" },
  "x-data-type": "json"
}

Asking the same workflow for its contract with annotation requested fills the words back in, without changing what is stored:

Fetching the contract as stored200 — unannotated
GET /api/flowdrop/workflows/{workflow}/schema

{"parameter_schema": {"properties": {"name": {"type": "string"}}}}
Fetching the same contract with annotation requested200 — filled
GET /api/flowdrop/workflows/{workflow}/schema?annotated=1

{"parameter_schema": {"properties": {"name": {"type": "string", "title": "Text value", "description": "A plain text field."}}}}
Rule identifiers are permanent and are never renumbered. Each implementation publishes its own standing against these rules; this specification does not.spec 1.0-draft · MAN-5 · changed in spec 1.0