Skip to content

[Workday][Sign-on] Add Sign-on data stream#20039

Open
muskan-agarwal26 wants to merge 3 commits into
elastic:mainfrom
muskan-agarwal26:workday-sign_on-0.1.1
Open

[Workday][Sign-on] Add Sign-on data stream#20039
muskan-agarwal26 wants to merge 3 commits into
elastic:mainfrom
muskan-agarwal26:workday-sign_on-0.1.1

Conversation

@muskan-agarwal26

@muskan-agarwal26 muskan-agarwal26 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Proposed commit message

This PR adds the `sign_on` data stream to the Workday integration, along
with its associated dashboard and visualizations.

Workday fields are mapped to their corresponding ECS fields where
possible.

Test samples were derived from live data samples, which were
subsequently sanitized.

Checklist

  • I have reviewed tips for building integrations and this pull request is aligned with them.
  • I have verified that all data streams collect metrics or logs.
  • I have added an entry to my package's changelog.yml file.
  • I have verified that Kibana version constraints are current according to guidelines.
  • I have verified that any added dashboard complies with Kibana's Dashboard good practices

How to test this PR locally

To test the Workday package:

  • Clone integrations repo.
  • Install elastic package locally.
  • Start elastic stack using elastic-package.
  • Move to integrations/packages/workday directory.
  • Run the following command to run tests.

elastic-package test

Note: pipeline/system tests were not run in this session. `elastic-package build` and `elastic-package check` pass on the package (the only warnings are the intentionally-excluded SVR00004 dashboard-reference checks). Run `elastic-package test` locally to execute the full pipeline/system test suite.

Related issues

Screenshots

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Elastic Docs Style Checker (Vale)

Summary: 2 suggestions found

💡 Suggestions (2): Optional style improvements. Apply when helpful.
File Line Rule Message
packages/workday/_dev/build/docs/README.md 12 Elastic.Ellipses In general, don't use an ellipsis.
packages/workday/data_stream/sign_on/fields/fields.yml 12 Elastic.WordChoice Consider using 'deactivated, deselected, hidden, turned off, unavailable' instead of 'disabled', unless the term is in the UI.

The Vale linter checks documentation changes against the Elastic Docs style guide. To use Vale locally or report issues, refer to Elastic style guide for Vale.

Co-authored-by: Cursor <cursoragent@cursor.com>
@elastic-vault-github-plugin-prod

Copy link
Copy Markdown

🚀 Benchmarks report

To see the full report comment with /test benchmark fullreport

@andrewkroh andrewkroh added Crest Contributions from Crest developement team. dashboard Relates to a Kibana dashboard bug, enhancement, or modification. documentation Improvements or additions to documentation. Applied to PRs that modify *.md files. Integration:workday Workday labels Jul 8, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
@muskan-agarwal26 muskan-agarwal26 marked this pull request as ready for review July 8, 2026 17:33
@muskan-agarwal26 muskan-agarwal26 requested a review from a team as a code owner July 8, 2026 17:33
@elastic-vault-github-plugin-prod

Copy link
Copy Markdown

✅ All changelog entries have the correct PR link.

@infra-vault-gh-plugin-prod

infra-vault-gh-plugin-prod Bot commented Jul 8, 2026

Copy link
Copy Markdown

💔 Build Failed

Failed CI Steps

History

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

TL;DR

Check integrations workday failed while running .buildkite/scripts/test_one_package.sh packages/workday .... The actionable issue in this PR is that Activity credentials were moved from package input vars to data-stream vars, but the Activity system-test config still supplies them as package-level vars, so the generated policy for the system test is missing required stream variables.

Remediation

  • Update packages/workday/data_stream/activity/_dev/test/system/test-common-config.yml so hostname, tenant, client_id, client_secret, and refresh_token are under data_stream.vars; keep shared input vars such as ssl under top-level vars.
  • Re-run the Workday package checks, especially elastic-package test system -v -p packages/workday and then the full package test command used by CI.
Investigation details

Root Cause

The PR moves Activity-specific required variables into the Activity data stream manifest:

  • packages/workday/data_stream/activity/manifest.yml:9-43 now declares hostname, tenant, client_id, client_secret, and refresh_token as required stream vars.
  • packages/workday/manifest.yml:44-52 no longer defines those variables at the package input level; only shared input vars such as proxy_url/ssl remain there.
  • packages/workday/data_stream/activity/_dev/test/system/test-common-config.yml:3-8 still sets those credentials under top-level vars, while only preserve_original_event and batch_size are under data_stream.vars at lines 31-34.

That layout matched the old manifest, but after this PR the required Activity variables must be supplied through data_stream.vars for system tests.

Evidence

  • Build: https://buildkite.com/elastic/integrations/builds/45748
  • Job/step: Check integrations workday
  • Command: .buildkite/scripts/test_one_package.sh packages/workday origin/main bd625d54dc03a3c02bac41dc1ae4d4170e3589dc
  • Captured log excerpt: --- [workday] failed followed by Error: The command exited with status 1. The prefetched Buildkite log only contains the job tail and artifact upload summary; the detailed test assertion output was not included in the local log file.

Verification

  • Reviewed the PR diff and file contents for the changed Workday package.
  • Local elastic-package verification was not run because elastic-package is not installed in this environment, and Docker-in-Docker is unavailable for system tests.

What is this? | From workflow: PR Buildkite Detective

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@andrewkroh andrewkroh added the Team:Security-Service Integrations Security Service Integrations team [elastic/security-service-integrations] label Jul 8, 2026
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

Pinging @elastic/security-service-integrations (Team:Security-Service Integrations)

)
:
{
"events": [{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🟠 High confidence: medium path: packages/workday/data_stream/sign_on/agent/stream/cel.yml.hbs:36

Sign-on CEL emits API errors wrapped inside message, so ctx.error is never set and the pipeline's error handling (terminate/pipeline_error) never fires — API errors are indexed as normal sign-on events. Emit the single-object {"events": {"error": {...}}} shape like the activity stream.

Details

On a non-200 response the program returns "events": [{"message": {"error": {...}}.encode_json()}]. Because the error object is embedded in the event's message string, the CEL input does not populate ctx.error. The ingest pipeline then renames message -> event.original and JSON-decodes it into workday.sign_on, so the error ends up at workday.sign_on.error.* (an undeclared field) and ctx.error.message stays null. As a result the pipeline's terminate (tag data_collection_error) never triggers, event.kind is never set to pipeline_error, degraded status is not reported, and every API failure is silently indexed as a normal user-signon event. The sibling activity stream uses the correct single-object form "events": {"error": {...}}, which is exactly what this pipeline's error machinery expects.

Recommendation:

Return the error in the single-object form so the framework sets ctx.error and the existing terminate/pipeline_error logic works:

      :
        {
          "events": {
            "error": {
              "code": string(resp.StatusCode),
              "id": resp.Status,
              "message": "GET " + state.url + ": " + (
                (size(resp.Body) != 0) ?
                  string(resp.Body)
                :
                  resp.Status + " (" + string(resp.StatusCode) + ")"
              ),
            },
          },
        }

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, can you explain why you've done this this way?

ignore_missing: true
description: The `message` field is no longer required if the document has an `event.original` field.
if: ctx.event?.original != null
- json:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🟠 High confidence: medium path: packages/workday/data_stream/sign_on/elasticsearch/ingest_pipeline/default.yml:35

Sign-on ingests the full custom report every interval with no _id fingerprint, so each poll re-indexes the same rows as new documents (unbounded duplication). Add a fingerprint processor that derives a stable _id, as the activity pipeline does.

Details

The sign-on CEL program fetches state.url (the RaaS report) on every interval with no time-window parameters and no cursor, emitting every Report_Entry row. The pipeline never sets a deterministic _id (unlike the activity pipeline, which fingerprints requestTime/sessionId/taskId into _id). Because a custom report returns a rolling window of sign-ons, each 24h poll re-emits rows already ingested on prior runs, and Elasticsearch auto-generates a fresh _id for each, producing duplicate documents on every cycle.

Recommendation:

Fingerprint each record into _id so re-collected rows overwrite instead of duplicating. Add after the json_event_original processor:

  - fingerprint:
      fields:
        - event.original
      tag: fingerprint_sign_on
      target_field: _id
      ignore_missing: true

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

"events": (has(body.Report_Entry) && size(body.Report_Entry) > 0) ?
body.Report_Entry.map(e, {"message": e.encode_json()})
:
[{"message": "{}"}],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🟡 Medium confidence: medium path: packages/workday/data_stream/sign_on/agent/stream/cel.yml.hbs:31

When the report is empty the CEL emits [{"message": "{}"}], which the pipeline turns into a spurious user-signon event (empty workday.sign_on, timestamp defaulted to ingest time) on every empty poll. Emit an empty events array instead.

Details

The empty-report branch returns [{"message": "{}"}]. The pipeline decodes this into an empty workday.sign_on map (later removed) but still unconditionally sets event.kind=event, event.category=[authentication,session], event.type=[start], and event.action=user-signon, and @​timestamp falls back to ingest time. So each polling cycle with no report rows produces a junk authentication event with no user, IP, or real data. There is no cursor to advance here, so no placeholder event is needed.

Recommendation:

Return an empty events array when there are no report entries:

            "events": (has(body.Report_Entry) && size(body.Report_Entry) > 0) ?
              body.Report_Entry.map(e, {"message": e.encode_json()})
            :
              [],

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also curious about this.

@@ -0,0 +1 @@
data_retention: "30d"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🟡 Medium confidence: medium path: packages/workday/data_stream/sign_on/lifecycle.yml:1

The sign_on data stream defines both a custom ILM policy (ilm_policy + elasticsearch/ilm/default_policy.json) and a Data Stream Lifecycle (lifecycle.yml with data_retention). Only one retention mechanism should be used; keep the ILM policy and remove lifecycle.yml.

Details

manifest.yml sets ilm_policy: logs-workday.sign_on-default_policy and ships elasticsearch/ilm/default_policy.json (hot rollover + 30d delete), while lifecycle.yml also declares a DSL data_retention: "30d". When both an ILM policy and a data stream lifecycle are attached, ILM takes precedence and the DSL retention is effectively ignored, making the two configs redundant and contradictory. The sibling activity data stream uses neither (Fleet default), so this is also inconsistent within the package.

Recommendation:

Pick one mechanism. Since the ILM policy provides rollover that DSL does not, keep the ILM policy and delete the DSL file:

# Remove packages/workday/data_stream/sign_on/lifecycle.yml.
# Retention/rollover is already managed by the ILM policy referenced in manifest.yml:
#   ilm_policy: logs-workday.sign_on-default_policy

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

dependencies:
ecs:
reference: git@v9.3.0
reference: git@v9.4.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🟡 Medium confidence: medium path: packages/workday/_dev/build/build.yml:3

build.yml bumps the ECS pin to v9.4.0, but the existing activity pipeline still sets ecs.version: 9.3.0, leaving the package build ECS version and the activity pipeline inconsistent. Bump the activity pipeline to 9.4.0 to match.

Details

This PR raises the ECS dependency pin from git@​v9.3.0 to git@​v9.4.0. The new sign_on pipeline correctly sets ecs.version: 9.4.0, but the pre-existing activity pipeline (data_stream/activity/elasticsearch/ingest_pipeline/default.yml) still hardcodes ecs.version: 9.3.0. After this change the two are inconsistent: activity documents report ECS 9.4.0 while the package is built against ECS 9.4.0 mappings. The bump should be applied consistently across all pipelines in the package.

Recommendation:

Update the activity pipeline's set_ecs_version processor to match the new build pin:

  - set:
      field: ecs.version
      tag: set_ecs_version
      value: 9.4.0

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

tag: rename_signon_ip_address_to_source_ip
target_field: workday.sign_on.signon_ip_address_string
ignore_missing: true
- set:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🟡 Medium confidence: medium path: packages/workday/data_stream/sign_on/elasticsearch/ingest_pipeline/default.yml:251

The sign_on pipeline sets source.ip but performs no geo/ASN enrichment, unlike the sibling activity pipeline. Add geoip (city + ASN) enrichment on source.ip so the Top Source IPs and location analytics work.

Details

source.ip is populated from Signon_IP_Address/Session_IP_Address, and the sign_on dashboard includes a Top Source IPs table, but the pipeline never enriches source.ip into source.geo or source.as. The activity pipeline in the same package does both geo and ASN enrichment. For a security/authentication data stream, geo+ASN enrichment on the originating IP is the current standard and is needed for investigation workflows.

Recommendation:

Add geo and ASN enrichment after source.ip is set (mirroring the activity pipeline):

  - geoip:
      field: source.ip
      tag: geoip_source_ip_to_source_geo
      target_field: source.geo
      ignore_missing: true
  - geoip:
      database_file: GeoLite2-ASN.mmdb
      field: source.ip
      tag: geoip_source_ip_to_source_as
      target_field: source.as
      properties:
        - asn
        - organization_name
      ignore_missing: true
  - rename:
      field: source.as.asn
      tag: rename_source_as_asn
      target_field: source.as.number
      ignore_missing: true
  - rename:
      field: source.as.organization_name
      tag: rename_source_as_organization_name
      target_field: source.as.organization.name
      ignore_missing: true

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

value: end
allow_duplicates: false
if: ctx.event?.end != null
- set:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🟡 Medium confidence: medium path: packages/workday/data_stream/sign_on/elasticsearch/ingest_pipeline/default.yml:333

Authentication events never set event.outcome, even though the report exposes Failed_Signon and Authentication_Failure_Message. Set event.outcome to success/failure so auth analytics and detections can distinguish failed sign-ons.

Details

The pipeline categorizes events as authentication/session and copies Authentication_Failure_Message into event.reason, but never sets event.outcome. For an authentication data stream, event.outcome (success/failure) is a core ECS field driving failed-sign-on dashboards and security detections. The source data supports it directly via the Failed_Signon boolean (kept in workday.sign_on).

Recommendation:

Derive event.outcome from Failed_Signon (add before the flags are otherwise consumed):

  - set:
      field: event.outcome
      tag: set_event_outcome_failure
      value: failure
      if: ctx.workday?.sign_on?.Failed_Signon == true || ctx.event?.reason != null
  - set:
      field: event.outcome
      tag: set_event_outcome_success
      value: success
      if: ctx.event?.outcome == null

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

type: keyword
description: The Workday account associated with the sign-on (alternate report column name for System_Account).
- name: signin_ip_address_string
type: keyword

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🔵 Low confidence: medium path: packages/workday/data_stream/sign_on/fields/fields.yml:89

fields.yml declares signon_ip_address_string typo variant signin_ip_address_string that the pipeline never produces. Remove the unused field definition.

Details

fields.yml defines workday.sign_on.signin_ip_address_string ("sign-in"), but the pipeline only ever produces signon_ip_address_string (the Signon_IP_Address fallback rename) and session_ip_address_string. No processor or report column maps to signin_ip_address_string, so it is dead and appears to be a typo of the already-declared signon_ip_address_string.

Recommendation:

Remove the unused field definition (keep signon_ip_address_string, which the pipeline actually sets):

# Delete this entry — the pipeline emits `signon_ip_address_string`, not `signin_ip_address_string`:
#        - name: signin_ip_address_string
#          type: keyword
#          description: The originating address of the sign-on when it is not a routable IP address (for example, Workday Internal).

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

"id": "",
"params": {
"fontSize": 12,
"markdown": "### Overview\n\nThe Workday Sign-On dashboard provides security and IT teams visibility into authentication activity from the Workday Sign-On custom report, covering sign-on volume, authentication methods, and failure patterns.\n\nThe Total Users tile shows authenticated account scope, while Sign-ons by Authentication Type and Distribution of Authentication Types break down usage across SAML, OAuth 2.0, Trusted, Username/Password, and ID Token.\n\nTop Source IPs surfaces active originating addresses for investigation, Top SAML Identity Providers highlights federated sign-in sources, and the Failure Breakdown table helps teams quickly triage authentication failures.\n\n[**Integration Page**](https://127.0.0.1:5601/app/integrations/detail/workday-0.1.0/overview)\n",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: 🔵 Low confidence: low path: packages/workday/kibana/dashboard/workday-36544d7d-809c-4306-a2b0-6276bad0a9b6.json:272

The sign_on dashboard's overview markdown links to a version-pinned integration page (workday-0.1.0), which is already stale (package is 0.1.1) and will drift on every release. Link to the unversioned integration page.

Details

The Overview markdown panel embeds https://127.0.0.1:5601/app/integrations/detail/workday-0.1.0/overview. The version segment 0.1.0 is already out of date for this PR (which ships 0.1.1) and will become stale again on each subsequent release, sending users to a non-current integration detail page.

Recommendation:

Drop the version from the integration link so it always resolves to the current package:

[**Integration Page**](https://127.0.0.1:5601/app/integrations/detail/workday/overview)

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

@vera-review-bot

Copy link
Copy Markdown

Review summary

Issues found across the latest commits bd625d5 — 2 high, 5 medium, 2 low
  • 🟠 Sign-on CEL emits API errors wrapped inside message, so ctx.error is never set and the pipeline's error handling (terminate/pipeline_error) never fires — API errors are indexed as normal sign-on events. Emit the single-object {"events": {"error": {...}}} shape like the activity stream. (link) (Unresolved)
  • 🟠 Sign-on ingests the full custom report every interval with no _id fingerprint, so each poll re-indexes the same rows as new documents (unbounded duplication). Add a fingerprint processor that derives a stable _id, as the activity pipeline does. (link) (Unresolved)
  • 🟡 When the report is empty the CEL emits [{"message": "{}"}], which the pipeline turns into a spurious user-signon event (empty workday.sign_on, timestamp defaulted to ingest time) on every empty poll. Emit an empty events array instead. (link) (Unresolved)
  • 🟡 The sign_on data stream defines both a custom ILM policy (ilm_policy + elasticsearch/ilm/default_policy.json) and a Data Stream Lifecycle (lifecycle.yml with data_retention). Only one retention mechanism should be used (link) (Unresolved)
  • 🟡 build.yml bumps the ECS pin to v9.4.0, but the existing activity pipeline still sets ecs.version: 9.3.0, leaving the package build ECS version and the activity pipeline inconsistent. Bump the activity pipeline to 9.4.0 to match. (link) (Unresolved)
  • 🟡 The sign_on pipeline sets source.ip but performs no geo/ASN enrichment, unlike the sibling activity pipeline. Add geoip (city + ASN) enrichment on source.ip so the Top Source IPs and location analytics work. (link) (Unresolved)
  • 🟡 Authentication events never set event.outcome, even though the report exposes Failed_Signon and Authentication_Failure_Message. Set event.outcome to success/failure so auth analytics and detections can distinguish failed sign-ons. (link) (Unresolved)
  • 🔵 fields.yml declares signon_ip_address_string typo variant signin_ip_address_string that the pipeline never produces. Remove the unused field definition. (link) (Unresolved)
  • 🔵 The sign_on dashboard's overview markdown links to a version-pinned integration page (workday-0.1.0), which is already stale (package is 0.1.1) and will drift on every release. Link to the unversioned integration page. (link) (Unresolved)

A new commit triggers another review — at most once every 15 minutes. I skip the PR while it's approved or has merge conflicts.

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

"message": {
"error": {
"code": string(resp.StatusCode),
"status": string(resp.Status),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"status": string(resp.Status),
"status": resp.Status,

"body": (size(resp.Body) != 0) ?
string(resp.Body)
:
string(resp.Status) + " (" + string(resp.StatusCode) + ")",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
string(resp.Status) + " (" + string(resp.StatusCode) + ")",
resp.Status + " (" + string(resp.StatusCode) + ")",

)
:
{
"events": [{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, can you explain why you've done this this way?

"events": (has(body.Report_Entry) && size(body.Report_Entry) > 0) ?
body.Report_Entry.map(e, {"message": e.encode_json()})
:
[{"message": "{}"}],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also curious about this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This program is non-idiomatic as raised by Vera. If this is necessary, it needs a comment explaining why.

title: Collect Workday logs via API
description: Collecting logs from Workday via CEL input.
vars:
- name: hostname

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this removed?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is using visualisations by reference. This is against guidance. Can you make sure the visualisations are saved by value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Crest Contributions from Crest developement team. dashboard Relates to a Kibana dashboard bug, enhancement, or modification. documentation Improvements or additions to documentation. Applied to PRs that modify *.md files. Integration:workday Workday Team:Security-Service Integrations Security Service Integrations team [elastic/security-service-integrations]

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants