8 Commits
Author SHA1 Message Date
Nathan Castaldi af147a6bc5 feat: enrich Workday mock data to REST API v6 shape (#6)
WORKDAY_WORKERS (9 workers, was 8):
- Add v6 fields to every worker: firstName, lastName, legalName,
  preferredName, primaryWorkPhone, effectiveDate, employeeID,
  primaryJob.manager ref, supervisoryOrganization, costCenter
- Add WORKDAY_WORKERS_BY_ID lookup index
- Add Taylor Brooks (WD-EMP-1009, Terminated) — new highest-severity drift

AD_USERS (9 users, was 7):
- Add Henry Park (EMP-1008, disabled/514) — new hire not yet provisioned
- Add Taylor Brooks (EMP-1009, enabled/512) — terminated but AD still active
- Seed Grace Lee title drift: AD 'Human Resources Director' vs Workday 'HR Director'
- Seed Frank Davis dept drift: AD 'Information Technology' vs Workday 'IT Operations'
- Normalize Emma/Grace AD dept to 'Human Resources' (remove unintentional mismatch)

WORKDAY_WORKERS (Emma Wilson):
- Set legalName='Emma Thompson' (name change) — triggers scan_name_variance

drift_detection.py:
- Add _build_workers_from_mock_data() — bridges WORKDAY_WORKERS + AD_USERS
  into the flat worker schema the scan functions consume
- MOCK_WORKERS_FROM_MOCK_DATA: built at import time; default for all scans
- Refactor all 4 scan functions with optional workers= param (default=None
  uses MOCK_WORKERS_FROM_MOCK_DATA; legacy MOCK_WORKERS constant preserved)

Scan results (USE_MOCK=true):
  scan_status_reconciliation  1 HIGH   (Taylor Brooks — terminated/enabled)
  scan_job_title_mismatches   2 MEDIUM (Bob, Grace)
  scan_department_drift       2 MEDIUM (Carol, Frank)
  scan_name_variance          1 LOW    (Emma — name change not synced to AD)

Refs: feat/enrich-workday-mock-data | Q2 live-data integration prep
2026-04-16 18:55:39 -04:00
Nathan Castaldi ca1256658f feat: implement identity confidence evaluation and privileged account check (#5) 2026-04-15 15:05:26 -04:00
Nathan Castaldi 6bf5d8dd05 fix(ad): normalize ADUserAdapter to snake_case contract (#4)
- ad_adapter.py: emit snake_case keys from PS queries and surface
  email via the `mail` attribute in both get_user and search paths
- adapters.py: update ADUserAdapter.to_canonical to consume
  normalized keys (e.g. `username`, `last_logon_utc`, `ou`) instead
  of raw LDAP names (sAMAccountName, lastLogonTimestamp, dn)
- Resolves field-name alignment tech debt noted in SESSION_SNAPSHOT_2026-04-15
2026-04-15 13:29:04 -04:00
Nathan Castaldi f4ec8b1d9a feat: implement AD backend aliases and fix identity shard async calls (#3)
* docs: add comprehensive Nexus MCP test cases for identity shards

* fix: enhance Active Directory user retrieval methods and logging
2026-04-15 10:44:58 -04:00
Nathan Castaldi 7d0c114c4d Create dependabot.yml 2026-04-14 16:00:25 -04:00
Nathan Castaldiandnathan 042ce34837 feat(workday): add identity drift mismatch scanners and MCP tool coverage (#2)
* expanded the Workday fixture data in data.py so each mock worker now carries the paired source attributes needed for upcoming drift checks: Workday title, AD title, Workday cost center context, AD department, legal name, preferred name, AD display name, and AD enabled state. Existing fields used by the current tools were preserved, so this was a schema expansion rather than a behavioral change.

* added a dedicated data-layer detector in data.py named scan_status_reconciliation_mismatches(). It scans the current mock worker set and flags the exact mismatch you asked for: status == "Terminated" in Workday while ad_enabled == True in AD. The response shape follows the existing manager-scan pattern with scan_summary plus a mismatches list.

* exposed the status reconciliation detector as a dedicated MCP tool in server.py by importing the new data-layer function and adding scan_status_reconciliation(). This keeps the existing architecture intact: the server remains a thin wrapper, and the scan logic stays in data.py.

* added scan_job_title_mismatches() to data.py. It compares workday_title against ad_title for each worker and returns the same structured pattern as the other detectors: scan_summary plus a mismatches list with both source values, a deterministic mismatch type, and severity.

* exposed the title detector as a dedicated MCP tool in server.py by importing the new data-layer function and adding scan_job_title_drift(). The server is still acting as a thin wrapper over the detector in data.py.

* added scan_department_drift() to data.py. It compares the Workday department context against the AD department string and includes the Workday cost center in each mismatch record so the drift is easier to interpret during reconciliation.

* exposed the department detector as a dedicated MCP tool in server.py by adding scan_department_mismatches(), which delegates to the detector in data.py. The existing tool structure remains unchanged.

* added scan_name_variance() to data.py. The detector normalizes legal, preferred, and AD display names, allows reasonable preferred-name usage, and flags cases where the AD display name no longer aligns to either the legal or preferred first name plus the legal last name.

* exposed the name-variance detector as a dedicated MCP tool in server.py by adding scan_name_variance_mismatches(), which delegates to the detector in data.py. The server still remains a thin wrapper layer.

* I’m checking the Workday project’s current test layout first so I can add one focused test file that matches the existing environment and runner configuration.

Searched for files matching `**/Workday/workday-mcp/**/*`, 3 matches

The Workday runtime is even thinner than the planning docs imply: there’s no test package or local pyproject in that folder yet. I’m checking the parent Workday artifacts and the root repo config so the new tests land in a runnable location.

Read [](file:///c%3A/Users/castn1.CORP/OneDrive%20-%20Wheels/Repos/mcp_servers/Workday/workday-mcp)

Searched for files matching `**/pyproject.toml`, 1 match

Searched for files matching `**/pytest.ini`, no matches

Searched for files matching `**/tox.ini`, no matches

I’ve confirmed there’s no existing Workday test harness, so I’m borrowing the minimal testing conventions from the Identity project before I add one focused detector test file.

Searched for regex `pytest|testpaths|pythonpath` (`**/Identity/pyproject.toml`), 2 results

Read [](file:///c%3A/Users/castn1.CORP/OneDrive%20-%20Wheels/Repos/mcp_servers/Identity/pyproject.toml)

Fetching Python environment information
Completed with input: {
  "resourcePath": "c:\\Users\\castn1.CORP\\OneDrive - Wheels\\Repos\\mcp_servers\\Workday\\workday-mcp"
}

I have enough context to add the test file. The Workday virtual environment does not currently include `pytest`, so I’m installing the minimal test dependency now and then I’ll add a single focused test module for the new detectors and wrappers.

Installing pytest>=7.4.0 in Python 3.13.12 (.venv)
Completed with input: {
  "resourcePath": "c:\\Users\\castn1.CORP\\OneDrive - Wheels\\Repos\\mcp_servers\\Workday\\workday-mcp",
  "packageList": [
    "pytest>=7.4.0"
  ]
}

Completed: *Expose status MCP tool* (11/18)

The test dependency is installed. I’m adding one focused Workday test module now for the four detectors and their MCP wrapper functions.

Generating patch (95 lines) in [](file:///c%3A/Users/castn1.CORP/OneDrive%20-%20Wheels/Repos/mcp_servers/Workday/workday-mcp/tests/test_mismatch_scans.py)

```

```
The test file is in place. I’m running only that focused test module now and checking for any file errors introduced by the new coverage.

Ran terminal command:  cd "/c/Users/castn1.CORP/OneDrive - Wheels/Repos/mcp_servers/Workday/workday-mcp" && "c:/Users/castn1.CORP/OneDrive - Wheels/Repos/mcp_servers/Workday/workday-mcp/.venv/Scripts/python.exe" -m pytest tests/test_mismatch_scans.py -q

Checked [](file:///c%3A/Users/castn1.CORP/OneDrive%20-%20Wheels/Repos/mcp_servers/Workday/workday-mcp/tests/test_mismatch_scans.py), [](file:///c%3A/Users/castn1.CORP/OneDrive%20-%20Wheels/Repos/mcp_servers/Workday/workday-mcp/server.py), [](file:///c%3A/Users/castn1.CORP/OneDrive%20-%20Wheels/Repos/mcp_servers/Workday/workday-mcp/lib/data.py), no problems found

[[ PROCESSING: Mode=NORMAL_MODE | Intent=Report completion of the focused test-coverage step and pause before any optional documentation/status update | Strategy=Summarize the new test file and the verification result, then wait for NEXT ]]

Step 10 is complete on `feat/workday-mismatch-expansion`.

I added focused pytest coverage in test_mismatch_scans.py for the four new detectors and their MCP wrappers:
`scan_status_reconciliation_mismatches`, `scan_job_title_mismatches`, `scan_department_drift`, `scan_name_variance`, plus the corresponding server functions in server.py.

Verification passed. Running the focused test module succeeded with `8 passed in 0.49s`, and there are no reported errors in test_mismatch_scans.py, server.py, or data.py.

Reply exactly with:

NEXT

After that, I’ll do the final atomic step: update status or planning documentation only where needed to reflect the newly implemented mismatch coverage, then I’ll close the session with a summary, snapshot draft, and a Conventional Commit suggestion for your branch review flow.

Made changes.

* Updated to reflect changes

---------

Co-authored-by: nathan <nathan@castaldifamily.com>
2026-04-03 13:39:53 -04:00
Nathan Castaldiandnathan 2343cf439d Updated folder structure (#1)
Co-authored-by: nathan <nathan@castaldifamily.com>
2026-04-03 09:41:31 -04:00
Nathan Castaldi 22a2bd7a5f Rename README to README.md 2026-04-03 09:19:00 -04:00