$ctx — Context Directive
Reads environment variables, tenant metadata, application properties, platform info, the authenticated user, and the current date/time.
| Property | Value |
|---|---|
| Directive name (DI key) | ctx |
| Required isolation level | Safe |
| Project | Context.Services |
| Class | ContextDirectiveService |
| Sub-keys | env · tenant · app · platform · user · now · today |
Syntax
AtBrace (default)
{@ $ctx.sub-key.property @option }DoubleBrace
{{ $ctx.sub-key.property }}Complete Path Reference
env — Environment Variables
| Path | Returns | Example |
|---|---|---|
$ctx.env.KEY_NAME | Value of the named environment variable / config key | {@ $ctx.env.DATABASE_URL } → Server=sql1;... |
$ctx.env.SMTP_HOST | Mail server host | smtp.sendgrid.net |
$ctx.env.API_BASE_URL | Base URL for API calls | https://api.acme.com/v3 |
Config hierarchy Environment variables are read via
IConfiguration, which respects the full .NET config hierarchy: appsettings.json → appsettings.{env}.json → environment variables → secrets.tenant — Tenant Metadata
| Path | Type | Example value |
|---|---|---|
$ctx.tenant.id | Number | 5 |
$ctx.tenant.name | String | Acme Corp |
$ctx.tenant.timezone | String (IANA) | Europe/Dublin |
$ctx.tenant.currency | String (ISO 4217) | EUR |
$ctx.tenant.locale | String (BCP 47) | en-IE |
$ctx.tenant.billingEmail | String | billing@acme.com |
$ctx.tenant.hrManagerEmail | String | hr@acme.com |
$ctx.tenant.plan | String | Enterprise |
app — Application Metadata
| Path | Type | Example value |
|---|---|---|
$ctx.app.id | Number | 12 |
$ctx.app.name | String | Payroll UK |
$ctx.app.code | String | payroll-uk |
$ctx.app.environment | String | Production |
platform — Platform Metadata
| Path | Type | Example |
|---|---|---|
$ctx.platform.region | String | eu-west-1 |
$ctx.platform.version | String | 4.2.1 |
$ctx.platform.supportEmail | String | support@bizfirst.ai |
user — Authenticated User
| Path | Type | Example |
|---|---|---|
$ctx.user.id | Number | 42 |
$ctx.user.name | String | Alice Smith |
$ctx.user.email | String | alice@acme.com |
$ctx.user.firstName | String | Alice |
$ctx.user.lastName | String | Smith |
$ctx.user.roles | Array | ["Admin","Manager"] |
$ctx.user.department | String | Finance |
now / today — Date and Time
| Path | Type | Example |
|---|---|---|
$ctx.now | String (ISO 8601 UTC) | 2024-03-15T10:22:01Z |
$ctx.today | String (YYYY-MM-DD) | 2024-03-15 |
Options Compatibility
| Option | Works with |
|---|---|
@uppercase @lowercase @trim | All string paths |
@json | Object/array paths (tenant, user, roles) |
@date:format | $ctx.now, $ctx.today |
@default:val | Any path that may be null |
@cache @cache-thread @cache-process | All — highly recommended since context values are stable within an execution |
Complex Scenarios
Scenario 1 — Locale-Aware Email Greeting
Build a greeting that addresses the user by first name, formatted for their tenant locale, with the current date in their timezone:
Email subject
{@ $ctx.user.firstName }, your {@ $ctx.tenant.name } payslip for {@ $ctx.now @date:MMMM yyyy } is ready
"Alice, your Acme Corp payslip for March 2024 is ready"
Scenario 2 — Dynamic API Base URL from Environment
HTTP Request node URL assembled from environment config + input data:
URL field (template)
{@ $ctx.env.CRM_BASE_URL @cache-process }/contacts/{@ $input.current.crmId }/notes
"https://crm.acme.com/v2/contacts/8821/notes"
Scenario 3 — Audit Log with Full Context
Structured audit log message capturing who did what, when, on which tenant:
Log message field
[{@ $ctx.now }] User {@ $ctx.user.email } (ID:{@ $ctx.user.id }) submitted {@ $var.documentType } on behalf of tenant {@ $ctx.tenant.id } via app {@ $ctx.app.name }
[2024-03-15T10:22:01Z] User alice@acme.com (ID:42) submitted Invoice on behalf of tenant 5 via app Payroll UK
Scenario 4 — Multi-Tenant Tax Rate Configuration
Instead of hardcoding rates, read them from tenant-specific environment config keys:
Tax calculation — reads per-region tax rate from config
{@ $js`
const taxRateKey = "TAX_RATE_" + context.ctx.tenant.currency;
const rate = context.ctx.env[taxRateKey] || "0.20";
return (context.vars.subtotal * parseFloat(rate)).toFixed(2);
` }
Reads TAX_RATE_EUR, TAX_RATE_GBP, etc. from config per tenant currency
Scenario 5 — Role-Based Conditional Routing
Use the user's roles to decide which approval tier to route to:
// IfCondition node field — checks if user has Manager role
{@ $js`
const roles = context.ctx.user.roles;
return Array.isArray(roles) && roles.includes('Manager');
` @required }
// Result: true/false → routes to Manager lane or Standard lane
Scenario 6 — Multi-Locale Date Formatting
Format the date according to the tenant locale for user-facing messages:
// UK tenant: "15 March 2024"
{@ $ctx.now @date:dd MMMM yyyy }
// US tenant: "March 15, 2024"
{@ $ctx.now @date:MMMM dd, yyyy }
// ISO for machine-readable fields
{@ $ctx.now @date:yyyy-MM-ddTHH:mm:ssZ }
Common Errors
| Error | Cause | Fix |
|---|---|---|
PathNotFound: env.MY_VAR | Environment variable not set | Add to appsettings or environment; use @default:fallback |
PathNotFound: user.department | Claim not included in user token | Add the claim in the auth configuration |
PathNotFound: tenant.billingEmail | Tenant metadata provider not returning this field | Check ITenantMetadataProvider implementation |