ek9_query_service_routes
Answers first: status, programState, routeCount, byService, then routes[] {verb, uri, fullPath, parameters with binding + sanitized, securityGate, cors, auditWarnings} and summary counts.
When to use it
'What is the HTTP attack surface - every route, its inputs, which are unsanitized or unguarded' is one call, no arguments; verb/service/uri/audit narrow it.
When not to use it
- how services get their components wired, DI, not the route list (use
ek9_query_dependency_injection) - whether services declare/require the network capability, not HTTP routes (use
ek9_query_capability_usage) - whether routes ever surface secrets, the secret-handling audit (use
ek9_query_sensitive_reveals) - the full structure of one specific service class, not the route catalogue (use
ek9_query_construct)
Details
status ok | empty (empty = no 'defines service' blocks, or filters matched nothing); needs a prior ek9_compile. parameters[].binding is UPPERCASE (PATH/QUERY/HEADER/CONTENT/REQUEST/CONTEXT); securityGate/cors are the declaring FUNCTION reference {name,fqn,file,line} (usually another file) — the compiler stores only the reference, null = unguarded / no CORS. auditWarnings flags unsanitized-{query,header,content} (PATH excluded, template-constrained) and unguarded-route; reuses the compiler's own ServiceMetadataExtractor, so the inventory never diverges from generated routing.
Arguments
| Argument | Type | Required | What it is |
|---|---|---|---|
audit | string: all | unsanitized | unguarded | Audit-level filter: all (default), unsanitized (routes with >=1 un-sanitized input parameter), unguarded (routes without a security gate). | |
service | string | Optional service-name SUBSTRING filter ('Order' matches OrderService). | |
uri | string | Optional fullPath SUBSTRING filter ('/addresses' matches every route under it). | |
verb | string: all | GET | POST | PUT | DELETE | PATCH | HEAD | OPTIONS | Filter by HTTP verb (default all). |
Recorded calls
Real calls, recorded against small projects and checked on every build - a changed answer fails it.
Inventory
Request
{ }
Response
{
"byService" : {
"CachedService" : 1,
"ClockService" : 1,
"CorsService" : 1,
"LookupService" : 2,
"OrderService" : 4,
"PublicService" : 1,
"ReportService" : 6
},
"meta" : {
"serverMs" : "<timing>"
},
"programState" : "clean",
"routeCount" : 16,
"routes" : [ {
"anySanitized" : false,
"auditCompliant" : true,
"auth" : {
"explicitlyOpen" : false,
"guarded" : true,
"source" : "service"
},
"baseUri" : "/api/cached",
...
Cut short here: 646 more lines. The whole recorded call.