@@ -250,3 +250,154 @@ local pcall_ok, valid, val_err = pcall(validator, { "a", "b", "c" })
250250assert (pcall_ok , " fail: validator threw an error: " .. tostring (valid ))
251251assert (valid , " fail: validator returned false: " .. tostring (val_err ))
252252ngx .say (" passed: recursive datatype is not shared across calls" )
253+
254+ ---- ------------------------------------------------- test case 10
255+ -- skip_validation: type bypass - string value passes integer schema
256+ local skip_fn = function (val , schema )
257+ return type (val ) == " string" and val :sub (1 , 10 ) == " $secret://"
258+ end
259+
260+ rule = {
261+ type = " object" ,
262+ properties = {
263+ host = { type = " string" },
264+ port = { type = " integer" },
265+ enabled = { type = " boolean" },
266+ },
267+ required = { " host" , " port" },
268+ }
269+
270+ validator = jsonschema .generate_validator (rule , { skip_validation = skip_fn })
271+ ok , err = validator ({ host = " $secret://vault/host" , port = " $secret://vault/port" , enabled = " $secret://vault/flag" })
272+ assert (ok , " fail: skip_validation should bypass type checks: " .. tostring (err ))
273+ ngx .say (" passed: skip_validation bypasses type checks" )
274+
275+ ---- ------------------------------------------------- test case 11
276+ -- skip_validation: enum bypass
277+ rule = {
278+ type = " object" ,
279+ properties = {
280+ scheme = { type = " string" , enum = { " http" , " https" } },
281+ },
282+ }
283+ validator = jsonschema .generate_validator (rule , { skip_validation = skip_fn })
284+ ok , err = validator ({ scheme = " $secret://vault/scheme" })
285+ assert (ok , " fail: skip_validation should bypass enum: " .. tostring (err ))
286+ -- non-secret string should still be validated
287+ ok , err = validator ({ scheme = " ftp" })
288+ assert (not ok , " fail: non-secret value should still fail enum" )
289+ ngx .say (" passed: skip_validation bypasses enum but normal values validated" )
290+
291+ ---- ------------------------------------------------- test case 12
292+ -- skip_validation: default values still set for nil fields
293+ rule = {
294+ type = " object" ,
295+ properties = {
296+ host = { type = " string" },
297+ port = { type = " integer" , default = 6379 },
298+ },
299+ }
300+ validator = jsonschema .generate_validator (rule , { skip_validation = skip_fn })
301+ local conf = { host = " $secret://vault/host" }
302+ ok , err = validator (conf )
303+ assert (ok , " fail: skip_validation with defaults: " .. tostring (err ))
304+ assert (conf .port == 6379 , " fail: default value should still be set" )
305+ ngx .say (" passed: skip_validation preserves default values" )
306+
307+ ---- ------------------------------------------------- test case 13
308+ -- skip_validation: nested object properties still validated
309+ rule = {
310+ type = " object" ,
311+ properties = {
312+ upstream = {
313+ type = " object" ,
314+ properties = {
315+ host = { type = " string" },
316+ port = { type = " integer" },
317+ },
318+ required = { " host" },
319+ },
320+ },
321+ }
322+ validator = jsonschema .generate_validator (rule , { skip_validation = skip_fn })
323+ -- nested secret ref should pass
324+ ok , err = validator ({ upstream = { host = " $secret://vault/host" , port = " $secret://vault/port" } })
325+ assert (ok , " fail: nested skip_validation: " .. tostring (err ))
326+ -- whole object as secret ref should pass
327+ ok , err = validator ({ upstream = " $secret://vault/upstream" })
328+ assert (ok , " fail: object-level skip_validation: " .. tostring (err ))
329+ ngx .say (" passed: skip_validation works for nested objects" )
330+
331+ ---- ------------------------------------------------- test case 14
332+ -- skip_validation: array items bypass
333+ rule = {
334+ type = " object" ,
335+ properties = {
336+ tags = {
337+ type = " array" ,
338+ items = { type = " string" , minLength = 3 },
339+ },
340+ },
341+ }
342+ validator = jsonschema .generate_validator (rule , { skip_validation = skip_fn })
343+ ok , err = validator ({ tags = { " abc" , " $secret://vault/tag" } })
344+ assert (ok , " fail: array items skip_validation: " .. tostring (err ))
345+ ngx .say (" passed: skip_validation works for array items" )
346+
347+ ---- ------------------------------------------------- test case 15
348+ -- skip_validation: not configured - normal validation applies
349+ rule = {
350+ type = " object" ,
351+ properties = {
352+ port = { type = " integer" },
353+ },
354+ }
355+ validator = jsonschema .generate_validator (rule )
356+ ok , err = validator ({ port = " $secret://vault/port" })
357+ assert (not ok , " fail: without skip_validation, string should fail integer type check" )
358+ ngx .say (" passed: without skip_validation, normal validation applies" )
359+
360+ ---- ------------------------------------------------- test case 16
361+ -- skip_validation: schema-aware hook - only bypass for string-typed fields
362+ -- This demonstrates using the schema parameter to make smart decisions:
363+ -- secret refs in string fields bypass constraints (enum, pattern, format),
364+ -- but secret refs in non-string fields (integer/boolean) are rejected.
365+ local schema_aware_skip = function (val , schema )
366+ if type (val ) ~= " string" or val :sub (1 , 10 ) ~= " $secret://" then
367+ return false
368+ end
369+ -- Only bypass when the schema expects a string type.
370+ -- For non-string fields, do not skip — we don't allow string
371+ -- placeholders in integer/boolean/object fields at validation time.
372+ if not schema or schema .type ~= " string" then
373+ return false
374+ end
375+ return true
376+ end
377+
378+ rule = {
379+ type = " object" ,
380+ properties = {
381+ host = { type = " string" , pattern = " ^[a-z]+%.com$" },
382+ scheme = { type = " string" , enum = { " http" , " https" } },
383+ port = { type = " integer" , minimum = 1 , maximum = 65535 },
384+ enabled = { type = " boolean" },
385+ },
386+ }
387+ validator = jsonschema .generate_validator (rule , { skip_validation = schema_aware_skip })
388+ -- secret ref in string+pattern field: bypassed (schema.type == "string")
389+ ok , err = validator ({ host = " $secret://vault/host" })
390+ assert (ok , " fail: schema-aware skip should bypass string+pattern: " .. tostring (err ))
391+ -- secret ref in string+enum field: bypassed (schema.type == "string")
392+ ok , err = validator ({ scheme = " $secret://vault/scheme" })
393+ assert (ok , " fail: schema-aware skip should bypass string+enum: " .. tostring (err ))
394+ -- secret ref in integer field: NOT bypassed (schema.type == "integer")
395+ ok , err = validator ({ port = " $secret://vault/port" })
396+ assert (not ok , " fail: schema-aware skip should NOT bypass integer field" )
397+ -- secret ref in boolean field: NOT bypassed (schema.type == "boolean")
398+ ok , err = validator ({ enabled = " $secret://vault/flag" })
399+ assert (not ok , " fail: schema-aware skip should NOT bypass boolean field" )
400+ -- non-secret invalid enum value: still fails
401+ ok , err = validator ({ scheme = " ftp" })
402+ assert (not ok , " fail: non-secret should still fail enum" )
403+ ngx .say (" passed: skip_validation schema-aware hook only skips string-typed fields" )
0 commit comments