Context
#127 added runtime prompting for unresolved ${name} placeholders.
The current behavior is useful for interactive runs:
discover unresolved placeholder
-> prompt for a string value
-> merge with contexts
-> substitute before execution
The remaining production requirement is an optional typed parameter contract that is shared by every execution surface.
Problem
Without declarations, Duckle cannot reliably determine:
- whether a value is missing;
- whether
false, 0, a date and a string were intended;
- whether an unexpected parameter name is a typo;
- whether a parameter is safe to record in run history;
- how schedules, Plans, API clients, MCP and backfills should render and validate the same input;
- whether a secret value must never be persisted.
This becomes important for pipelines such as:
jurisdiction = BE | NL | GB
effective_date = DATE
full_refresh = BOOLEAN
api_token = SECRET
Proposed solution
Allow an optional pipeline-level parameter schema.
parameters:
jurisdiction:
type: string
enum: [BE, NL, GB]
required: true
description: Registry jurisdiction
effective_date:
type: date
required: true
full_refresh:
type: boolean
default: false
max_companies:
type: integer
minimum: 1
api_token:
type: secret
required: true
Useful initial types:
string
integer
number
boolean
date
datetime
enum
secret
Useful constraints:
required
default
enum
minimum / maximum
pattern
description
One normalization boundary
Normalize and validate parameters once before compilation/execution.
Every execution surface should receive the same typed result:
desktop
web console
CLI
HTTP API
MCP
scheduler
Plans
partitions/backfills
retry
Reject:
unknown parameter
missing required parameter
invalid type
invalid enum/range/pattern
conflicting duplicate input
Errors should be machine-readable and identify the parameter and expected contract.
Secret handling
A secret parameter value must never be written to:
pipeline JSON
run history
logs
previews
manifests
MCP responses
audit payloads
release files
It can be supplied through an authorized runtime surface or secret reference.
Non-secret normalized parameters should be recorded in run metadata so a run can be reproduced and compared.
SQL safety
A typed parameter must not automatically become an arbitrary raw SQL fragment.
Where a parameter is used in SQL, prefer parameter binding or a deterministic type-aware literal representation. Raw SQL fragments should require a separate explicit mechanism.
Precedence
Define and document precedence, for example:
declared default
< context/environment binding
< Plan/schedule parameter set
< explicit run input
The final normalized values should be visible before execution, with secrets redacted.
UI and machine-readable schema
The same declaration should drive:
- text, number, date and checkbox controls;
- enum dropdowns;
- required/default indicators;
- CLI help;
- HTTP/MCP input schemas;
- validation;
- generated documentation.
A command/API such as this would also be useful:
duckle parameters schema pipeline.json --json
Backward compatibility
Pipelines without a declaration should retain the current unresolved-placeholder discovery and string prompt behavior.
Migration to typed declarations can therefore be incremental.
Relationships
This should compose with:
Acceptance criteria
- A declared boolean/date/integer is normalized identically through desktop, CLI, API and MCP.
- Unknown, missing and invalid values fail before execution.
- Secret values never appear in persisted or inspection surfaces.
- Non-secret normalized parameters appear in run provenance.
- Schedules and Plans can bind validated named parameter sets.
- Existing undeclared-placeholder pipelines remain compatible.
Context
#127 added runtime prompting for unresolved
${name}placeholders.The current behavior is useful for interactive runs:
The remaining production requirement is an optional typed parameter contract that is shared by every execution surface.
Problem
Without declarations, Duckle cannot reliably determine:
false,0, a date and a string were intended;This becomes important for pipelines such as:
Proposed solution
Allow an optional pipeline-level parameter schema.
Useful initial types:
Useful constraints:
One normalization boundary
Normalize and validate parameters once before compilation/execution.
Every execution surface should receive the same typed result:
Reject:
Errors should be machine-readable and identify the parameter and expected contract.
Secret handling
A
secretparameter value must never be written to:It can be supplied through an authorized runtime surface or secret reference.
Non-secret normalized parameters should be recorded in run metadata so a run can be reproduced and compared.
SQL safety
A typed parameter must not automatically become an arbitrary raw SQL fragment.
Where a parameter is used in SQL, prefer parameter binding or a deterministic type-aware literal representation. Raw SQL fragments should require a separate explicit mechanism.
Precedence
Define and document precedence, for example:
The final normalized values should be visible before execution, with secrets redacted.
UI and machine-readable schema
The same declaration should drive:
A command/API such as this would also be useful:
Backward compatibility
Pipelines without a declaration should retain the current unresolved-placeholder discovery and string prompt behavior.
Migration to typed declarations can therefore be incremental.
Relationships
This should compose with:
Acceptance criteria