ek9_query_env_vars
Answers first: names[] (every env-var read), then envVars[] per call site (site, name, accessMethod, sanitization, inConstruct), dynamicAccesses[] and summary counts - type-resolved EnvVars calls, never text matches.
When to use it
Which environment variables does this app read, where, and how safely - one call, no arguments. Pass envVarNames for an existence check, accessMethodFilter:['unsanitizedGet'] for a security audit.
When not to use it
- Raw text matches of a literal name anywhere (comments, docstrings, JSON, extern files) — use
ek9_search_text; this returns only RESOLVED EnvVars calls. - Auditing the broader sensitive-data surface beyond env vars (Sensitive construction / reveal points) — use
ek9_query_sensitive_reveals. - You already know the variable holding a name and want its call sites — use
ek9_query_references(feed a dynamic access's nameExpression there). - System properties (System.getProperty), .env files or config loaders — out of scope; this covers org.ek9.lang::EnvVars only.
Details
Each entry carries a derived sanitization (get→sanitized, unsanitizedGet→unsanitized, sensitiveGet→sensitive-wrapped, contains→n/a) plus site ('file.ek9:LINE'), file/line/column and inConstruct/inConstructFqn — feed the FQN straight into ek9_query_call_graph to trace who reaches a secret read or where its value flows. One entry per CALL SITE, so staticAccessCount ≥ uniqueNameCount; runtime-computed names land in dynamicAccesses[]. Unmatched envVarNames/moduleFilter values are reported in meta.unmatchedFilters[] with status ok/empty, NOT errors — error only on an accessMethodFilter value outside the enum or no compiled program.
Arguments
| Argument | Type | Required | What it is |
|---|---|---|---|
accessMethodFilter | array of string: get | unsanitizedGet | sensitiveGet | contains | Restrict to these access methods. Example: ["unsanitizedGet"] for a security audit. Default: all four. | |
envVarNames | array of string | Restrict to specific env-var names (case-sensitive EXACT match per name, e.g. ["DATABASE_URL", "AUTH_SECRET"]). Not a substring pattern — env-var names are a set of distinct identifiers. Default: all discovered. | |
includeDynamic | boolean | Include the dynamicAccesses[] array flagging accesses where the env-var name is a runtime expression rather than a literal. Set false to suppress when only the statically-resolvable surface matters. | |
moduleFilter | array of string | Restrict to these exact module names. Default: workspace-wide. |
Recorded calls
Real calls, recorded against small projects and checked on every build - a changed answer fails it.
List all
Request
{ }
Response
{
"dynamicAccesses" : [ {
"accessMethod" : "get",
"column" : 17,
"file" : "config.ek9",
"inConstruct" : "readConfig",
"inConstructFqn" : "com.example.config::readConfig",
"line" : 15,
"module" : "com.example.config",
"nameExpression" : "key",
"nameExpressionType" : "String",
"note" : "Name supplied as runtime expression — resolve via ek9_query_references on 'key' to trace the source value(s).",
"site" : "config.ek9:15"
} ],
"envVars" : [ {
"accessMethod" : "sensitiveGet",
"column" : 20,
"file" : "auth.ek9",
"inConstruct" : "readSecret",
"inConstructFqn" : "com.example.auth::readSecret",
"line" : 8,
"module" : "com.example.auth",
"name" : "AUTH_SECRET",
"sanitization" : "sensitive-wrapped",
...
Cut short here: 53 more lines. The whole recorded call.