Files
claudetools/.claude/skills/alis/SKILL.md
Mike Swanson c3aeef60fb sync: auto-sync from GURU-5070 at 2026-07-01 15:06:42
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-07-01 15:06:42
2026-07-01 15:07:39 -07:00

5.9 KiB

name, description
name description
alis Build the ALIS (Medtelligent) staff bulk-import .xls (13-column template) for Cascades of Tucson (communityId 622) and read the live staff roster via the read-only API. Triggers: alis, alisonline, medtelligent, alis staff import, add staff to alis, alis security roles.

ALIS Skill (Medtelligent) — staff import builder + roster reference

ALIS is Medtelligent's assisted-living EHR. This skill exists to create/change staff (and their logins) in bulk, which in ALIS is done by uploading an .xls in the web UI (Staff -> Import) — there is no staff-write API. The skill:

  1. Reads the live staff roster via the ALIS API (read-only) to learn how staff are set up — the security-role and job-role vocabulary, and a job-role → security-role map.
  2. Builds a correctly-formatted import workbook from your CSV/JSON of new hires, inferring each person's Security Roles from that reference so new staff match existing ones. You upload it in ALIS and fine-tune there.

Running the CLI

PY="bash $CLAUDETOOLS_ROOT/.claude/scripts/py.sh"
ALIS="$PY C:/claudetools/.claude/skills/alis/scripts/alis.py"

# --- read (reference) ---
$ALIS auth-test                       # mint token, confirm scope
$ALIS communities                     # communityId(s) in scope (Cascades = 622)
$ALIS staff --status Hired --limit 20 # roster
$ALIS roles                           # live security + job role vocabulary
$ALIS role-map [--refresh]            # jobRole -> securityRole(s), learned from Hired staff

# --- build (the deliverable) ---
$ALIS template --out new_staff.xls    # blank, exactly-formatted template to hand-fill
$ALIS build-import --input hires.csv --out import.xls   # NEW staff (create format)
$ALIS build-import --input hires.csv --out import.xls --gen-passwords  # also mint logins
$ALIS build-import --input edits.csv --out upd.xls --format update     # edit existing (ALIS ID)
$ALIS inspect import.xls              # dump a workbook to verify before upload

Transport auto-selects httpx if installed, else stdlib urllib. Workbook I/O needs xlwt (write .xls) + xlrd (read .xls); openpyxl for .xlsx.

Credentials

Never hardcoded. The user login (used to mint a JWT) loads from the SOPS vault:

bash "$CLAUDETOOLS_ROOT/.claude/scripts/vault.sh" \
     get-field clients/cascades-tucson/alis-api-howard-user.sops.yaml credentials.username

Auth model (critical, verified live 2026-06-29): POST /user/tokens with {username, password} returns a JWT (accessToken, ~1h) + refreshToken; send Authorization: Bearer <accessToken>. The username must be tenant-qualifiedhoward.enos@cascadestucson, not bare howard.enos (bare returns HTTP 400). Env overrides for testing: ALIS_USERNAME, ALIS_PASSWORD, ALIS_BASE_URL, ALIS_COMMUNITY_ID.

The import template (what ALIS expects)

13 columns, exact order — Sheet1 header, then one row per staff. Sheet2 carries the dropdown lists. The builder reproduces both exactly.

Column Notes
First Name, Last Name required
Staff Record Number your HR id / match key
Security Roles inferred from Job Role if blank (see role-map)
Staff Status Applicant / Hired / Discharged / Rejected (default Hired)
Hire Date date — format unconfirmed, builder passes your string through
Login Enabled Yes / No (auto: Yes if Email+Password present, else No)
Email required if Login Enabled = Yes
Password credential — see below
Date of Birth, Gender Gender: Female / Male
Job Role free text; drives Security Role inference
Cell Phone

Input headers are matched flexibly (Job Title→Job Role, Cell/Mobile→Cell Phone, DOB→Date of Birth, Login→Login Enabled, etc.).

Passwords (handle with care)

  • By default the builder does not invent passwords — supply them, or set Login Enabled = No.
  • --gen-passwords mints a strong password for each Login-enabled row missing one and writes them to a plaintext sidecar *_passwords.csv next to the .xls. That file is a credential set: distribute to staff, then delete it or vault it. Never commit it. The terminal output never prints passwords.

Two import formats — create vs update (confirmed from the real export)

ALIS has two layouts; the builder writes either via --format:

  • create (default, new staff): columns include Password, no ALIS ID. Rows without an ALIS ID are created as new staff.
  • update (existing staff): leads with ALIS ID (the staffId), no Password. Rows with an ALIS ID update the matching staff member. (This is the format ALIS exports as ALIS_Staff_Update_Import.xls.)

So the create-vs-update match key is ALIS ID — present = update, absent = create. Dates are MM/DD/YYYY (confirmed). Security Roles are comma-separated and the builder infers the full typical combination for a job role (e.g. Med TechCaregiver (Cascades), Medication Tech), learned from current staff in role-map.json.

Still smart to test with ONE row first before a bulk run. Scope: this credential only sees Cascades of Tucson (communityId 622).

Scope reality

The ALIS API has only GET endpoints for staff — no create/update/delete. Do not try to "PUT a staff record"; it does not exist. The .xls upload is the supported write path. (The API does have writes for residents/prospects/billing, out of scope for this skill.)

Files

  • scripts/alis_client.py — API client (JWT auth via vault, staff/community reads, role-map).
  • scripts/import_builder.py — template spec, input parsing, validation, role inference, password gen, .xls read/write.
  • scripts/alis.py — CLI.
  • references/api-reference.md — endpoints, auth, template, role vocabulary.
  • references/role-map.json — cached job-role → security-role reference (refresh with role-map --refresh).