[Workday][Sign-on] Add Sign-on data stream#20039
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
Elastic Docs Style Checker (Vale)Summary: 2 suggestions found 💡 Suggestions (2): Optional style improvements. Apply when helpful.
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>
🚀 Benchmarks reportTo see the full report comment with |
Co-authored-by: Cursor <cursoragent@cursor.com>
TL;DR
Remediation
Investigation detailsRoot CauseThe PR moves Activity-specific required variables into the Activity data stream manifest:
That layout matched the old manifest, but after this PR the required Activity variables must be supplied through Evidence
Verification
What is this? | From workflow: PR Buildkite Detective Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not. |
|
Pinging @elastic/security-service-integrations (Team:Security-Service Integrations) |
| ) | ||
| : | ||
| { | ||
| "events": [{ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Yes, can you explain why you've done this this way?
There was a problem hiding this comment.
You're right. The non-200 branch was wrapping the error object inside message, so the CEL input never populated ctx.error and the terminate/pipeline_error handling never fired. Reworked it to the single-object {"events": {"error": {"code", "id", "message"}}} form, matching the activity stream, so ctx.error is set and collection errors surface as degraded status instead of being indexed as sign-on events.
| 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: |
There was a problem hiding this comment.
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": "{}"}], |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Done, the empty-report branch now emits []. The old [{"message": "{}"}] placeholder was decoded into an empty workday.sign_on object but still ran through the rest of the pipeline, so every empty poll produced a junk user-signon event with no user/IP and @timestamp defaulted to ingest time. Since this stream has no cursor to advance, there's nothing to keep alive with a placeholder returning an empty array simply publishes no events.
| @@ -0,0 +1 @@ | |||
| data_retention: "30d" | |||
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Can't perform activity datatsream changes in sign-on datatsream PR.
| tag: rename_signon_ip_address_to_source_ip | ||
| target_field: workday.sign_on.signon_ip_address_string | ||
| ignore_missing: true | ||
| - set: |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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.
| ) | ||
| : | ||
| { | ||
| "events": [{ |
There was a problem hiding this comment.
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": "{}"}], |
| dependencies: | ||
| ecs: | ||
| reference: git@v9.3.0 | ||
| reference: git@v9.4.0 |
There was a problem hiding this comment.
Severity: 🟠 High confidence: high path: packages/workday/_dev/build/build.yml:3
This PR bumps the ECS pin in build.yml to v9.4.0 but the existing activity pipeline still emits ecs.version 9.3.0; align the activity pipeline to 9.4.0 so the pin and the emitted version match.
Details
build.yml now pins ECS to git@v9.4.0, and the new sign_on pipeline correctly sets ecs.version: 9.4.0. However, the pre-existing activity pipeline (packages/workday/data_stream/activity/elasticsearch/ingest_pipeline/default.yml) still hardcodes value: 9.3.0 in its set_ecs_version processor. Before this PR both were 9.3.0 and consistent; the build.yml bump introduces a mismatch between the package-wide ECS pin (9.4.0) and the version stamped into activity documents (9.3.0). The two data streams in the same package will report different ecs.version values, and the pin no longer matches the activity pipeline.
Recommendation:
Update the activity pipeline's set_ecs_version value to match the new build.yml pin (9.4.0):
# packages/workday/data_stream/activity/elasticsearch/ingest_pipeline/default.yml
- 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.
| } | ||
| }, | ||
| "delete": { | ||
| "min_age": "30d", |
There was a problem hiding this comment.
Severity: 🟡 Medium confidence: medium path: packages/workday/data_stream/sign_on/elasticsearch/ilm/default_policy.json:16
The new sign_on data stream ships a custom ILM policy that deletes data after 30 days, silently discarding authentication/audit telemetry; drop the delete phase (or the custom policy) and let the stack-managed logs lifecycle govern retention.
Details
The sign_on data stream introduces a package-shipped ILM policy with a delete phase at min_age: 30d. This hard-deletes sign-on records after 30 days, which is short for security/authentication audit data that teams typically retain for investigations and compliance. The pre-existing activity data stream ships no custom ILM policy and relies on the stack-managed logs lifecycle, so this also makes retention inconsistent within the same package and overrides the retention strategy the user would otherwise control.
Recommendation:
Prefer not shipping a custom lifecycle and letting the stack-managed logs policy handle retention (remove the ilm_policy line in manifest.yml and the ilm/default_policy.json file). If a custom rollover is genuinely required, at minimum drop the auto-delete so audit data is not silently removed:
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_age": "2d",
"max_size": "50gb"
},
"set_priority": {
"priority": 100
}
}
}
}
}
}🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills
⚠️ Automated review — verify suggestions before applying.
| title: Sign-on logs | ||
| description: Collect Sign-on logs from Workday. | ||
| template_path: cel.yml.hbs | ||
| vars: |
There was a problem hiding this comment.
Severity: 🔵 Low confidence: medium path: packages/workday/data_stream/sign_on/manifest.yml:9
The sign_on cel.yml.hbs references proxy_url and ssl but the sign_on manifest defines neither var, so those template branches are dead and users cannot configure a proxy or custom CA for the HTTPS Workday endpoint; add the vars (as the activity stream already does).
Details
The shared sign_on template (agent/stream/cel.yml.hbs) contains {{#if proxy_url}}resource.proxy_url: {{proxy_url}}{{/if}} and {{#if ssl}}resource.ssl: {{ssl}}{{/if}}, but the sign_on manifest's stream vars list does not declare proxy_url or ssl. As a result those branches never render and operators have no way to route the Workday Custom Report (RaaS) HTTPS request through a proxy or trust a custom/internal CA — capabilities the activity policy template does expose. This is a configuration-completeness gap for enterprise Workday deployments.
Recommendation:
Declare the proxy_url and ssl vars in the sign_on stream, mirroring the activity input:
- name: proxy_url
type: text
title: Proxy URL
description: proxy configuration in the form of https://<user>:<password>@<server name/ip>:<port>.
multi: false
required: false
show_user: false
- name: ssl
type: yaml
title: SSL Configuration
description: SSL configuration options. See [documentation](https://www.elastic.co/guide/en/beats/filebeat/current/configuration-ssl.html#ssl-common-config) for details.
multi: false
required: false
show_user: false🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills
⚠️ Automated review — verify suggestions before applying.
| "Failed_Signon": false, | ||
| "Forgotten_Password_Reset_Request": false, | ||
| "Invalid_Credentials": false, | ||
| "Is_Device_Managed": false, |
There was a problem hiding this comment.
| "authentication", | ||
| "session" | ||
| ], | ||
| "end": "2026-06-19T06:25:22.000Z", |
There was a problem hiding this comment.
@uri-weisman do you think it makes sense that this session_end timestamp is mapped to host.entity.lifecycle.last_activity?
Would you map it to the session_start field instead?
https://www.elastic.co/docs/reference/ecs/ecs-entity#field-entity-lifecycle-last-activity
There was a problem hiding this comment.
That's a good point, but we just need to verify that for activity logs, besides sign-on we populate this field.
| "original": "{\"Account_Locked__Disabled_or_Expired\":\"0\",\"Active_Session\":\"0\",\"Authentication_Failure_Message\":\"Mobile PIN has expired. To reset your PIN, first sign in using your user name and password.\",\"Authentication_Type_for_Signon\":\"Biometric\",\"Browser_Type\":\"Workday Phone App\",\"Device_Type\":\"Phone\",\"Device_is_Trusted\":\"0\",\"Failed_Signon\":\"1\",\"Forgotten_Password_Reset_Request\":\"0\",\"Invalid_Credentials\":\"0\",\"Is_Device_Managed\":\"0\",\"Operating_System\":\"iOS\",\"Password_Changed\":\"0\",\"Request_Originator\":\"UI\",\"Session_Start\":\"2026-06-18T16:52:43-07:00\",\"System_Account\":\"user179.acme / User 179\",\"UI_Client_Type\":\"iPhone Native\"}", | ||
| "outcome": "failure", | ||
| "reason": "Mobile PIN has expired. To reset your PIN, first sign in using your user name and password.", | ||
| "start": "2026-06-18T23:52:43.000Z", |
There was a problem hiding this comment.
In this case as it is a single action (sign-on failure), I would map event.start with https://www.elastic.co/docs/reference/ecs/ecs-entity#field-entity-lifecycle-last-activity.
There was a problem hiding this comment.
@chemamartinez Should we map both end and start with same ecs field,i.e, host.entity.lifecycle.last_activity?
There was a problem hiding this comment.
I would say in case there's only start, use start for the last_activity field. In case there are both start and end, map end as it is the last time known when the user/device was active.
| "layers": {} | ||
| } | ||
| }, | ||
| "filters": [], |
| "events": [] | ||
| } | ||
| }, | ||
| "filters": [], |
|
✅ All changelog entries have the correct PR link. |
| "0c598211-5777-402f-89ae-2f05488a5f0d": { | ||
| "explicitInput": { | ||
| "dataViewId": "logs-*", | ||
| "fieldName": "workday.sign_on.Authentication_Type", |
There was a problem hiding this comment.
Severity: 🟡 Medium confidence: medium path: packages/workday/kibana/dashboard/workday-36544d7d-809c-4306-a2b0-6276bad0a9b6.json:16
The Sign-on dashboard's authentication control and 3 visualizations key only on workday.sign_on.Authentication_Type, but the README-recommended report column maps to workday.sign_on.Authentication_Type_for_Signon; normalize the two report columns into one field in the pipeline so all documented report shapes populate the auth-type panels.
Details
The sample data contains two distinct report shapes: records 1-5 emit workday.sign_on.Authentication_Type_for_Signon (and no Authentication_Type), while records 6-10 emit workday.sign_on.Authentication_Type. The README's 'Build the Sign-on custom report' step recommends adding the column 'Authentication Type for Signon', which produces Authentication_Type_for_Signon. The pipeline keeps these as two separate keyword fields and never unifies them. The dashboard's Authentication Type options-list control and all three authentication visualizations (Sign-ons by Authentication Type over Time, Distribution of Authentication Types, Failure Breakdown) source only workday.sign_on.Authentication_Type. As a result, events from the report layout the README tells users to build (records 1-5 in the fixture) carry no Authentication_Type and are excluded from those panels, so the dashboard's core authentication views render empty for that report shape.
Recommendation:
Normalize the two report columns into a single field in the ingest pipeline (before enrichment) so every documented report shape feeds the dashboard. For example, copy Authentication_Type_for_Signon into Authentication_Type when the latter is absent:
- set:
field: workday.sign_on.Authentication_Type
tag: set_authentication_type_from_signon_variant
copy_from: workday.sign_on.Authentication_Type_for_Signon
ignore_empty_value: true
override: false
if: ctx.workday?.sign_on?.Authentication_Type == nullAlternatively, add matching panels/controls that also cover workday.sign_on.Authentication_Type_for_Signon.
🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills
⚠️ Automated review — verify suggestions before applying.
Review summaryIssues found across the latest commits 7d20ff6 — 1 medium
Issues found across earlier commits 94d8c84 — 1 high, 1 medium, 1 low
Issues found across earlier commits bd625d5 — 2 high, 5 medium, 2 low
🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills
|
💚 Build Succeeded
History
|
|
@muskan-agarwal26 - This PR has merge conflicts with the base branch. Please resolve them. |
Proposed commit message
Checklist
changelog.ymlfile.How to test this PR locally
To test the Workday package:
Related issues
Screenshots