@adobe-commerce/aio-toolkit 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/CHANGELOG.md +250 -0
  2. package/README.md +450 -1
  3. package/dist/aio-toolkit-cli-workflow/bin/cli.js +2048 -0
  4. package/dist/aio-toolkit-cli-workflow/bin/cli.js.map +1 -0
  5. package/dist/aio-toolkit-cursor-context/bin/cli.js +16 -0
  6. package/dist/aio-toolkit-cursor-context/bin/cli.js.map +1 -1
  7. package/dist/index.d.mts +61 -6
  8. package/dist/index.d.ts +61 -6
  9. package/dist/index.js +600 -42
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +610 -38
  12. package/dist/index.mjs.map +1 -1
  13. package/files/cursor-context/commands/aio-toolkit-analyze-adobe-commerce-module.md +612 -0
  14. package/files/cursor-context/commands/aio-toolkit-create-amazon-sqs-consumer.md +445 -0
  15. package/files/cursor-context/commands/aio-toolkit-create-event-consumer-action.md +6 -0
  16. package/files/cursor-context/commands/aio-toolkit-create-graphql-action.md +21 -7
  17. package/files/cursor-context/commands/aio-toolkit-create-openwhisk-action.md +326 -0
  18. package/files/cursor-context/commands/aio-toolkit-create-runtime-action.md +15 -5
  19. package/files/cursor-context/commands/aio-toolkit-create-shipping-carrier.md +681 -0
  20. package/files/cursor-context/commands/aio-toolkit-create-webhook-action.md +22 -9
  21. package/files/cursor-context/rules/aio-toolkit-create-adobe-commerce-client.mdc +252 -116
  22. package/files/cursor-context/rules/aio-toolkit-oop-best-practices.mdc +10 -4
  23. package/files/cursor-context/rules/aio-toolkit-setup-new-relic-telemetry.mdc +167 -2
  24. package/files/cursor-context/rules/aio-toolkit-use-abdb-collection.mdc +610 -0
  25. package/files/cursor-context/rules/aio-toolkit-use-abdb-repository.mdc +705 -0
  26. package/files/cursor-context/rules/aio-toolkit-use-adobe-auth.mdc +442 -0
  27. package/files/cursor-context/rules/aio-toolkit-use-amazon-sqs-publish.mdc +397 -0
  28. package/files/cursor-context/rules/aio-toolkit-use-file-repository.mdc +502 -0
  29. package/files/cursor-context/rules/aio-toolkit-use-publish-event.mdc +510 -0
  30. package/files/cursor-context/rules/aio-toolkit-use-runtime-api-gateway-service.mdc +542 -0
  31. package/package.json +4 -2
package/README.md CHANGED
@@ -312,7 +312,7 @@ OpenTelemetry integration for enterprise-grade observability with distributed tr
312
312
  - Access to current OpenTelemetry span via `ctx.telemetry` for custom instrumentation
313
313
  - `telemetry.instrument()` method for wrapping functions with automatic span creation
314
314
  - Conditional span access based on `ENABLE_TELEMETRY` flag
315
- - Multi-provider support (New Relic implemented, Grafana ready)
315
+ - Multi-provider support (New Relic and Grafana LGTM implemented)
316
316
  - Graceful fallback when telemetry is not configured
317
317
  - Zero performance impact when disabled (opt-in via feature flags)
318
318
 
@@ -420,6 +420,195 @@ SELECT * FROM Log WHERE `x-adobe-commerce-request-id` = 'request-123' AND level
420
420
  SELECT count(*) FROM Log FACET `action.type` SINCE 1 hour ago
421
421
  ```
422
422
 
423
+ ---
424
+
425
+ #### Grafana LGTM Telemetry
426
+
427
+ The Grafana provider forwards traces, metrics, and logs to an OTLP/HTTP collector backed by the [Grafana LGTM](https://github.com/grafana/docker-otel-lgtm) all-in-one stack (**L**oki · **G**rafana · **T**empo · **M**imir). It works in two modes:
428
+
429
+ | Mode | When | Collector URL |
430
+ |---|---|---|
431
+ | **Dev** | `GRAFANA_DEV=true` | `http://localhost:4318` (Docker image) |
432
+ | **Deployed** | `GRAFANA_DEV` not set | `GRAFANA_ENDPOINT` (e.g. Cloudflare tunnel) |
433
+
434
+ ##### Dev mode — local Docker stack
435
+
436
+ Start the LGTM stack with a single command:
437
+
438
+ ```bash
439
+ docker run --rm -p 3000:3000 -p 4317:4317 -p 4318:4318 \
440
+ --name otel-lgtm \
441
+ grafana/otel-lgtm:latest
442
+ ```
443
+
444
+ This exposes:
445
+
446
+ | Port | Service |
447
+ |---|---|
448
+ | `3000` | Grafana UI — open `http://localhost:3000` (default credentials: `admin` / `admin`) |
449
+ | `4317` | OTLP gRPC endpoint |
450
+ | `4318` | OTLP HTTP endpoint (used by the toolkit) |
451
+
452
+ Configure `app.config.yaml`:
453
+
454
+ ```yaml
455
+ runtime-action:
456
+ function: actions/runtime-action/index.js
457
+ web: 'yes'
458
+ runtime: nodejs:22
459
+ inputs:
460
+ LOG_LEVEL: debug
461
+ ENABLE_TELEMETRY: true
462
+ GRAFANA_TELEMETRY: true
463
+ GRAFANA_DEV: true
464
+ GRAFANA_SERVICE_NAME: $GRAFANA_SERVICE_NAME
465
+ annotations:
466
+ require-adobe-auth: true
467
+ final: true
468
+ ```
469
+
470
+ `.env`:
471
+
472
+ ```bash
473
+ GRAFANA_SERVICE_NAME=my-app-builder-app
474
+ ```
475
+
476
+ ##### Deployed mode — Cloudflare tunnel
477
+
478
+ Adobe I/O Runtime actions run in the cloud and cannot reach `localhost`. Expose your local LGTM stack via a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/):
479
+
480
+ ```bash
481
+ npx cloudflared tunnel --url http://localhost:4318
482
+ # Outputs a URL like: https://abc123-def456.trycloudflare.com
483
+ ```
484
+
485
+ Configure `app.config.yaml`:
486
+
487
+ ```yaml
488
+ runtime-action:
489
+ function: actions/runtime-action/index.js
490
+ web: 'yes'
491
+ runtime: nodejs:22
492
+ inputs:
493
+ LOG_LEVEL: debug
494
+ ENABLE_TELEMETRY: true
495
+ GRAFANA_TELEMETRY: true
496
+ GRAFANA_ENDPOINT: $GRAFANA_ENDPOINT
497
+ GRAFANA_SERVICE_NAME: $GRAFANA_SERVICE_NAME
498
+ annotations:
499
+ require-adobe-auth: true
500
+ final: true
501
+ ```
502
+
503
+ `.env`:
504
+
505
+ ```bash
506
+ GRAFANA_ENDPOINT=https://abc123-def456.trycloudflare.com
507
+ GRAFANA_SERVICE_NAME=my-app-builder-app
508
+ ```
509
+
510
+ ##### Usage example
511
+
512
+ Telemetry is automatically initialized when you use framework action classes:
513
+
514
+ ```javascript
515
+ /*
516
+ * <license header>
517
+ */
518
+
519
+ const { RuntimeAction, RuntimeActionResponse, HttpMethod } = require('@adobe-commerce/aio-toolkit');
520
+ const name = 'runtime-action';
521
+
522
+ exports.main = RuntimeAction.execute(
523
+ name,
524
+ [HttpMethod.POST],
525
+ [],
526
+ ['Authorization'],
527
+ async (params, ctx) => {
528
+ const { logger, telemetry } = ctx;
529
+
530
+ logger.info({
531
+ message: `${name}-log`,
532
+ params: JSON.stringify(params),
533
+ });
534
+
535
+ const sampleInstrumental = telemetry.instrument(
536
+ `runtime.action.${name}.sampleInstrumental`,
537
+ async () => {
538
+ const span = telemetry.getCurrentSpan();
539
+
540
+ if (span) {
541
+ span.setAttribute('test', 'ABC');
542
+ }
543
+
544
+ logger.info({
545
+ message: `${name}-sampleInstrumental`,
546
+ test: 'ABC',
547
+ });
548
+
549
+ return 'Hello World';
550
+ }
551
+ );
552
+
553
+ const result = await sampleInstrumental();
554
+
555
+ return RuntimeActionResponse.success(result);
556
+ }
557
+ );
558
+ ```
559
+
560
+ ##### Grafana Cloud
561
+
562
+ Grafana Cloud provides a managed LGTM backend. It uses the same OTLP/HTTP protocol but requires
563
+ HTTP Basic authentication with your stack's **Instance ID** and an **API key**.
564
+
565
+ Find your OTLP endpoint and instance ID in **Grafana Cloud → Stack → OpenTelemetry**.
566
+
567
+ Configure `app.config.yaml`:
568
+
569
+ ```yaml
570
+ runtime-action:
571
+ inputs:
572
+ ENABLE_TELEMETRY: true
573
+ GRAFANA_TELEMETRY: true
574
+ GRAFANA_CLOUD: true
575
+ GRAFANA_ENDPOINT: $GRAFANA_ENDPOINT
576
+ GRAFANA_SERVICE_NAME: $GRAFANA_SERVICE_NAME
577
+ GRAFANA_INSTANCE_ID: $GRAFANA_INSTANCE_ID
578
+ GRAFANA_API_KEY: $GRAFANA_API_KEY
579
+ ```
580
+
581
+ `.env`:
582
+
583
+ ```bash
584
+ GRAFANA_ENDPOINT=https://otlp-gateway-prod-us-east-0.grafana.net/otlp
585
+ GRAFANA_SERVICE_NAME=my-app-builder-app
586
+ GRAFANA_INSTANCE_ID=123456
587
+ GRAFANA_API_KEY=glc_xxx
588
+ ```
589
+
590
+ ##### Environment variable reference
591
+
592
+ | Variable | Mode | Required | Default | Description |
593
+ |---|---|---|---|---|
594
+ | `ENABLE_TELEMETRY` | all | ✅ | — | Must be `true` to enable any telemetry |
595
+ | `GRAFANA_TELEMETRY` | all | ✅ | — | Must be `true` to select the Grafana provider |
596
+ | `GRAFANA_DEV` | dev | — | `false` | Set `true` to use `http://localhost:4318` |
597
+ | `GRAFANA_CLOUD` | cloud | — | `false` | Set `true` to enable Grafana Cloud Basic auth |
598
+ | `GRAFANA_ENDPOINT` | tunnel / cloud | ✅ | — | Collector base URL (not needed in dev mode) |
599
+ | `GRAFANA_SERVICE_NAME` | tunnel / cloud | ✅ | `app-builder-app` | Service name tag (not needed in dev mode) |
600
+ | `GRAFANA_INSTANCE_ID` | cloud | ✅ | — | Grafana Cloud stack instance ID |
601
+ | `GRAFANA_API_KEY` | cloud | ✅ | — | Grafana Cloud API key / token |
602
+
603
+ **Multi-provider fallback chain:**
604
+
605
+ The toolkit tries providers in this order:
606
+ 1. **New Relic** — when `NEW_RELIC_TELEMETRY=true`
607
+ 2. **Grafana LGTM** — when `GRAFANA_TELEMETRY=true`
608
+ 3. **No telemetry** — original action runs uninstrumented
609
+
610
+ ---
611
+
423
612
  **Supported Action Classes:**
424
613
 
425
614
  Telemetry is automatically integrated with all framework action classes:
@@ -430,6 +619,97 @@ Telemetry is automatically integrated with all framework action classes:
430
619
 
431
620
  All action classes provide structured logging with automatic request ID and action type tracking.
432
621
 
622
+ #### `LogSanitizer`
623
+
624
+ Utility class that deep-clones a value and replaces sensitive field values with `"[REDACTED]"` before writing to logs. Used internally by all action classes and available for direct use.
625
+
626
+ **Sensitive key detection (case-insensitive):**
627
+
628
+ | Match type | Keys / patterns |
629
+ |---|---|
630
+ | Exact | `authorization`, `x-api-key`, `cookie`, `set-cookie` |
631
+ | Suffix | `*_api_key`, `*_secret`, `*_token`, `*_password`, `*_key`, `*-token`, `*-secret`, `*-key` |
632
+
633
+ **Constructor:**
634
+
635
+ ```typescript
636
+ new LogSanitizer(
637
+ additionalSensitiveKeys?: ReadonlySet<string>, // extra keys to redact (lowercase)
638
+ maxDepth?: number // recursion limit, default 10
639
+ )
640
+ ```
641
+
642
+ **`LogSanitizer.parseSensitiveKeys(raw: unknown): ReadonlySet<string>`**
643
+
644
+ Static helper that parses the `SENSITIVE_KEYS` runtime param into a `ReadonlySet<string>` suitable for the constructor. Accepts three input forms:
645
+
646
+ | Input type | Example value | Result |
647
+ |---|---|---|
648
+ | Comma-separated string | `"x-merchant-token,internal_id"` | `Set { "x-merchant-token", "internal_id" }` |
649
+ | Array | `["x-merchant-token", "INTERNAL_ID"]` | `Set { "x-merchant-token", "internal_id" }` |
650
+ | Single string | `"x-merchant-token"` | `Set { "x-merchant-token" }` |
651
+ | Anything else (incl. `undefined`) | — | `Set {}` (no-op) |
652
+
653
+ All keys are lowercased; whitespace around commas and in array elements is trimmed; non-string array elements are silently dropped.
654
+
655
+ **Automatic `SENSITIVE_KEYS` param support:**
656
+
657
+ All action classes (`RuntimeAction`, `EventConsumerAction`, `OpenwhiskAction`) and `Telemetry.createLogger()` automatically call `parseSensitiveKeys(params.SENSITIVE_KEYS)` when initializing `LogSanitizer`. To extend sanitization with project-specific keys, add them to `app.config.yaml`:
658
+
659
+ ```yaml
660
+ application:
661
+ actions:
662
+ my-action:
663
+ function: actions/my-action/index.js
664
+ inputs:
665
+ SENSITIVE_KEYS: "x-merchant-token,internal_order_id"
666
+ ```
667
+
668
+ Or pass an array when testing:
669
+
670
+ ```typescript
671
+ await myAction({ ...params, SENSITIVE_KEYS: ['x-merchant-token', 'internal_order_id'] });
672
+ ```
673
+
674
+ **Usage:**
675
+
676
+ ```typescript
677
+ const { LogSanitizer } = require('@adobe-commerce/aio-toolkit');
678
+
679
+ const sanitizer = new LogSanitizer();
680
+
681
+ // Sanitize HTTP headers before logging
682
+ logger.debug({
683
+ message: 'Headers received',
684
+ headers: sanitizer.execute(params.__ow_headers || {}),
685
+ });
686
+ // authorization, x-api-key, cookie → "[REDACTED]"
687
+
688
+ // Sanitize full action parameters (includes env-bound secrets)
689
+ logger.debug({
690
+ message: 'Parameters received',
691
+ parameters: sanitizer.execute(params),
692
+ });
693
+ // MY_API_KEY, NEW_RELIC_LICENSE_KEY, GRAFANA_API_KEY → "[REDACTED]"
694
+
695
+ // Extend with project-specific keys using parseSensitiveKeys
696
+ const customSanitizer = new LogSanitizer(
697
+ LogSanitizer.parseSensitiveKeys(params.SENSITIVE_KEYS)
698
+ );
699
+ customSanitizer.execute(data);
700
+
701
+ // Or construct a Set directly
702
+ const fixedSanitizer = new LogSanitizer(new Set(['x-merchant-token', 'my_internal_secret']));
703
+ fixedSanitizer.execute(data);
704
+ ```
705
+
706
+ **Behaviour:**
707
+ - Returns a deep copy — never mutates the input
708
+ - Handles nested objects and arrays recursively (configurable depth limit)
709
+ - Primitives (`string`, `number`, `boolean`, `null`, `undefined`) are returned as-is
710
+
711
+ ---
712
+
433
713
  #### `RuntimeApiGatewayService`
434
714
  Flexible Adobe I/O Runtime API Gateway client that accepts bearer tokens for authenticated requests.
435
715
 
@@ -1650,6 +1930,73 @@ if (stats.errors.length) {
1650
1930
 
1651
1931
  ---
1652
1932
 
1933
+ #### `AmazonSQSClient`
1934
+ Batched publisher and long-polling consumer for Amazon SQS standard and FIFO queues.
1935
+
1936
+ **Installation**
1937
+ ```bash
1938
+ npm install @aws-sdk/client-sqs
1939
+ ```
1940
+
1941
+ **Basic Usage**
1942
+ ```typescript
1943
+ const { AmazonSQSClient } = require('@adobe-commerce/aio-toolkit');
1944
+
1945
+ const client = new AmazonSQSClient({
1946
+ region: 'us-east-1',
1947
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
1948
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
1949
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/my-queue',
1950
+ });
1951
+ ```
1952
+
1953
+ **Publishing messages**
1954
+ ```typescript
1955
+ const payloads = orders.map(o => JSON.stringify(o));
1956
+ const stats = await client.publish(payloads);
1957
+
1958
+ console.log(`published=${stats.published} failed=${stats.failed}`);
1959
+ if (stats.errors.length) {
1960
+ console.error('Failed payloads:', stats.errors);
1961
+ }
1962
+ ```
1963
+
1964
+ **Publishing to a FIFO queue**
1965
+ ```typescript
1966
+ const fifoClient = new AmazonSQSClient({
1967
+ region: 'us-east-1',
1968
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
1969
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
1970
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/my-queue.fifo',
1971
+ messageGroupId: 'order-processing', // required for FIFO
1972
+ messageDeduplicationId: 'unique-batch-id', // optional — omit to use content-based dedup
1973
+ });
1974
+
1975
+ const stats = await fifoClient.publish(payloads);
1976
+ ```
1977
+
1978
+ **Consuming messages**
1979
+ ```typescript
1980
+ const stats = await client.consume(
1981
+ { batchSize: 10, waitTimeSeconds: 20 }, // long polling
1982
+ async (message) => {
1983
+ const order = JSON.parse(message.body);
1984
+ await processOrder(order);
1985
+ }
1986
+ );
1987
+
1988
+ console.log(`consumed=${stats.consumed} acked=${stats.acked} failed=${stats.failed}`);
1989
+ ```
1990
+
1991
+ **API Reference**
1992
+
1993
+ | Method | Description | Returns |
1994
+ |---|---|---|
1995
+ | `publish(payloads)` | Sends each payload as an SQS message; FIFO queues include group/dedup IDs | `Promise<PublishStats>` |
1996
+ | `consume(options, handler)` | Long-polls the queue, invokes `handler` for each message, auto-deletes on success | `Promise<ConsumeStats>` |
1997
+
1998
+ ---
1999
+
1653
2000
  #### `InfiniteLoopBreaker`
1654
2001
  Detect and prevent infinite loops in event-driven applications.
1655
2002
 
@@ -2118,6 +2465,108 @@ deployment:
2118
2465
  3. **CI/CD Integration**: Automate event configuration in deployment pipelines
2119
2466
  4. **Multi-Environment Setup**: Use different config files for dev/staging/production environments
2120
2467
 
2468
+ #### `aio-toolkit-cli-workflow`
2469
+
2470
+ Command-line tool for orchestrating Adobe I/O CLI workflows in your App Builder projects. This CLI acts as a wrapper around the `aio` CLI to streamline environment setup, resets, and cron rule management via interactive prompts.
2471
+
2472
+ > **Prerequisite:** The `aio` CLI must be installed. If it is missing, the command will detect this at startup and print installation instructions pointing to the [Adobe App Builder CLI install guide](https://developer.adobe.com/app-builder/docs/guides/runtime_guides/tools/cli-install).
2473
+
2474
+ ##### Commands
2475
+
2476
+ ###### `env:setup`
2477
+ Interactively configure the AIO Console environment (org → project → workspace).
2478
+
2479
+ ```bash
2480
+ npx aio-toolkit-cli-workflow env:setup
2481
+
2482
+ # Skip the interactive prompt and use a specific workspace config file
2483
+ npx aio-toolkit-cli-workflow env:setup --config-file ./path/to/.aio
2484
+ ```
2485
+
2486
+ **Flow without `--config-file`:**
2487
+ 1. Prompts "Do you have a workspace config file?" (yes/no).
2488
+ 2. If **yes** — prompts for the file path and runs `aio app use <file>`.
2489
+ 3. If **no** — runs `aio console org select` → `aio console project select` → `aio console workspace select` interactively.
2490
+
2491
+ ###### `env:reset`
2492
+ Fully reset the AIO CLI environment and re-authenticate.
2493
+
2494
+ ```bash
2495
+ # Reset for production (default)
2496
+ npx aio-toolkit-cli-workflow env:reset
2497
+
2498
+ # Reset for staging
2499
+ npx aio-toolkit-cli-workflow env:reset --env stage
2500
+ ```
2501
+
2502
+ **Steps performed:**
2503
+ 1. `aio auth logout`
2504
+ 2. `aio config clear -f` (local) + `aio config clear -g -f` (global)
2505
+ 3. `aio telemetry off`
2506
+ 4. `aio config set cli.env <stage|prod>`
2507
+ 5. `aio auth login`
2508
+ 6. `aio telemetry on`
2509
+
2510
+ After reset, verify with `aio config get cli.env` and `aio console where`.
2511
+
2512
+ ###### `cron:status`
2513
+ Display the status of all AIO Runtime cron rules in the current workspace.
2514
+
2515
+ ```bash
2516
+ # List all cron rules
2517
+ npx aio-toolkit-cli-workflow cron:status
2518
+
2519
+ # Inspect a single rule by name
2520
+ npx aio-toolkit-cli-workflow cron:status --name myRuleName
2521
+ ```
2522
+
2523
+ **Output per rule:** rule name, status (active/inactive), action name, action path, publish status, trigger name, cron schedule, version.
2524
+
2525
+ ###### `cron:enable`
2526
+ Enable AIO Runtime cron rules interactively.
2527
+
2528
+ ```bash
2529
+ # Interactive rule selection
2530
+ npx aio-toolkit-cli-workflow cron:enable
2531
+
2532
+ # Enable all rules without prompting
2533
+ npx aio-toolkit-cli-workflow cron:enable --all
2534
+ ```
2535
+
2536
+ ###### `cron:disable`
2537
+ Disable AIO Runtime cron rules interactively.
2538
+
2539
+ ```bash
2540
+ # Interactive rule selection
2541
+ npx aio-toolkit-cli-workflow cron:disable
2542
+
2543
+ # Disable all rules without prompting
2544
+ npx aio-toolkit-cli-workflow cron:disable --all
2545
+ ```
2546
+
2547
+ ###### `cron:delete`
2548
+ Delete AIO Runtime cron rules and their associated triggers.
2549
+
2550
+ ```bash
2551
+ npx aio-toolkit-cli-workflow cron:delete
2552
+ ```
2553
+
2554
+ Confirms the workspace, lists all rules (with trigger names), and prompts for one or more rule numbers to delete. For each selected rule the associated trigger is deleted first (`aio rt trigger delete`) and then the rule (`aio rt rule delete`).
2555
+
2556
+ ###### `help`
2557
+ Displays help information for the CLI.
2558
+
2559
+ ```bash
2560
+ npx aio-toolkit-cli-workflow help
2561
+ ```
2562
+
2563
+ ##### Use Cases
2564
+
2565
+ 1. **First-time setup**: Run `env:setup` to select org, project, and workspace in one step.
2566
+ 2. **Environment switching**: Run `env:reset --env stage` or `env:reset --env prod` to cleanly switch AIO CLI environments.
2567
+ 3. **Cron management**: Use `cron:status` to audit schedules, then `cron:enable` / `cron:disable` to control them without memorising `aio rt` commands.
2568
+ 4. **Rule cleanup**: Use `cron:delete` to remove stale rules and their triggers together.
2569
+
2121
2570
  ## Environment Variables
2122
2571
 
2123
2572
  Common environment variables used across components: