Skip to main content

integer

Whole numbers only. Floats and strings are rejected.
"amount": { "type": "integer" }
ValueValid?Error
100-
-50-
0-
1.5VAL-007
"100"VAL-007
nullVAL-007

boolean

Must be exactly true or false. Truthy values like 1 or "true" are rejected.
"verified": { "type": "boolean" }
ValueValid?Error
true-
false-
1VAL-006
"true"VAL-006
nullVAL-006

string

Any string value, including empty string.
"user_id": { "type": "string" }
ValueValid?Error
"abc"-
""-
123VAL-008
nullVAL-008

enum

String value restricted to a declared set of values. The values array is required.
"status": {
  "type": "enum",
  "values": ["active", "inactive", "pending"]
}
ValueValid?Error
"active"-
"pending"-
"unknown"VAL-011
""VAL-011
nullVAL-009
VAL-009 is thrown when the value is not a string at all (e.g. null, 1, true). VAL-011 is thrown when the value is a string but is not in the declared values array. Missing values array in the signal definition raises POL-012 at compile time.

Why float is not allowed

Floating-point arithmetic is non-deterministic across platforms — 0.1 + 0.2 can yield different bit representations on different CPUs, runtimes, and JavaScript engines. Since every Parmana execution must be byte-for-byte reproducible, floating-point signals would break the determinism guarantee. Use scaled integers instead: multiply your float value by a power of 10 and work in integer space.
"signalsSchema": {
  "rate_bps": { "type": "integer" }
}
// Signal value: 3.75% → store as 375 basis points
{ "rate_bps": 375 }
// Condition in policy: greater than 5.00% = 500 bps
{ "signal": "rate_bps", "greater_than": 500 }
The scaling factor (100 for percentages, 100 for cents, 1000 for per-mille, etc.) is an application-layer contract that you document alongside your policy.

Common validation errors

CodeSignal typeCause
VAL-003anySignal not declared in signalsSchema
VAL-004anyRequired signal missing from input
VAL-005anyInvalid schema definition: signal definition missing type field
VAL-006booleanNon-boolean value
VAL-007integerNon-integer (float or string)
VAL-008stringNon-string value
VAL-009enumNon-string value (e.g. null, 1, true)
VAL-011enumString value not in declared values array
VAL-012anyUnsupported signal type — use integer, boolean, string, or enum

Scaled integer conversion table

Common financial values that require fractions and their integer equivalents:
Real-world valueSignal nameInteger encodingScale factor
3.75% interest raterate_bps375× 100 (basis points)
₹82,000.50 incomemonthly_income8200050× 100 (paise)
0.97 confidence scoreconfidence_pct97× 100 (percentage)
1.5x debt-to-income ratiodti_ratio_bps15000× 10000
87.3% LTV ratioltv_ratio_pct8730× 100
₹4,200,000 loan amountloan_amount4200000× 1 (rupees, integers only)
For rupee amounts that are always whole numbers, no scaling is needed — loan_amount: 4200000 is already a valid integer.

Use Cases

Personal loan signal schema

An NBFC evaluates personal loans using the following signal schema. All fractional values are scaled to integers:
"signalsSchema": {
  "monthly_income":    { "type": "integer" },
  "loan_amount":       { "type": "integer" },
  "credit_score":      { "type": "integer" },
  "emi_obligations":   { "type": "integer" },
  "employed":          { "type": "boolean" },
  "employment_type":   { "type": "enum", "values": ["salaried", "self_employed", "government"] },
  "blacklisted":       { "type": "boolean" }
}
Signal values sent with each request:
{
  "monthly_income":  82000,
  "loan_amount":     500000,
  "credit_score":    720,
  "emi_obligations": 18000,
  "employed":        true,
  "employment_type": "salaried",
  "blacklisted":     false
}

UPI fraud detection with scaled risk score

A payment processor evaluates each UPI transaction with a risk score from a fraud model. The model outputs a float (0.0–1.0); it is scaled to an integer (0–100) before being passed as a signal:
"signalsSchema": {
  "transaction_amount": { "type": "integer" },
  "risk_score":         { "type": "integer" },
  "is_foreign":         { "type": "boolean" }
}
{
  "transaction_amount": 50000,
  "risk_score":         87,
  "is_foreign":         false
}
The policy rule uses "greater_than": 75 to match high-risk transactions. The scaling factor (× 100) is documented in the policy’s README — not embedded in the signal schema, which has no concept of units.

Catching type errors at the validation boundary

A developer accidentally passes credit_score: "750" (a string) instead of credit_score: 750 (an integer). The signal schema declares { "type": "integer" }. Validation throws VAL-007 before evaluation begins — the error is caught at the boundary, not silently coerced. This is the intended behavior: type safety is enforced structurally, not by convention.

See also