-
Notifications
You must be signed in to change notification settings - Fork 1
Home
S9TerpSync keeps Slate CRM and your Ellucian ERP in sync as a single, file-state Node.js service — no Docker, no database, and no external ETL platform to license or run. It's built to drop onto a RHEL/systemd box and stay there. Version 1 moves data from Slate into Banner through Ethos APIs; Slate-to-Colleague support is planned.
This project is aimed at institutions that don't have an ETL platform in place, or can't justify buying one just for this. If your institution already has Ellucian Ethos Data Connect, use that instead — it's the better-supported path. Boomi, MuleSoft, and Jitterbit equivalents of this same sync are coming as separate open-source pipelines.
Every trigger — manual CLI run, scheduler tick, or service boot — converges on the same safety path.
flowchart TB
cli["CLI run<br/>manual, dry-run or live"]
cron["Scheduler tick<br/>cron, non-overlapping"]
boot["Service boot<br/>startup run assessment"]
preflight["Preflight gates<br/>config, reference data, crosswalks"]
coordinator["Run coordinator<br/>run lock, RUNNING manifest"]
discover["Discover and claim<br/>SFTP or Slate API source"]
acquire["Two-pass acquire<br/>checksum, duplicate skip"]
decode["Decode and map<br/>canonical applicant per row"]
match["Crosswalk and person match<br/>resolve codes, find person"]
plan["Plan target commands<br/>nine ordered stages"]
gateway["Target command gateway<br/>DRY_RUN plans, LIVE mutates"]
evidence["Institution evidence gate<br/>fixture-only evidence is non-live"]
ethos["Ellucian Ethos APIs"]
banner["Banner ERP<br/>implemented v1 target"]
colleague["Colleague ERP<br/>future target family"]
finish["Complete and finish<br/>report, archive, mark processed"]
state["File-based state<br/>locks, run audit, idempotency, reports"]
cli --> preflight
cron --> preflight
boot --> preflight
preflight --> coordinator
coordinator --> discover
discover --> acquire
acquire --> decode
decode --> match
match --> plan
plan --> gateway
gateway --> evidence
evidence -->|only when verified for school LIVE| ethos
ethos --> banner
ethos -. future .-> colleague
gateway --> finish
coordinator --> state
acquire --> state
gateway --> state
finish --> state
classDef pipeline fill:#EEEDFE,stroke:#534AB7,color:#26215C
classDef mutation fill:#FAECE7,stroke:#993C1D,color:#4A1B0C
classDef failure fill:#FAEEDA,stroke:#854F0B,color:#412402
classDef readonly fill:#E1F5EE,stroke:#0F6E56,color:#04342C
classDef neutral fill:#F1EFE8,stroke:#5F5E5A,color:#2C2C2A
class preflight,coordinator,discover,acquire,decode,match,plan,finish pipeline
class gateway,evidence,ethos,banner mutation
class state readonly
class cli,cron,boot,colleague neutral
Every applicant record starts as a Slate export and ends as a set of Banner writes made through Ethos. A Banner person record is always matched or created first; everything else depends on it (and admission decision, student attribute, and student cohort also depend on the admission application existing first). This is the real dependency order the stage engine enforces — src/stages/stage-registry.ts is the single source of truth for it.
flowchart TB
slate["Slate CRM export<br/>SFTP file or API"]
canonical["Decode, crosswalk,<br/>match to a Banner person"]
subgraph entities["Nine target entities, in dependency order"]
person["Person"]
permanentAddress["Permanent address"]
priorSchool["Prior school"]
familyAddress["Family address"]
familyRelationship["Family relationship"]
admissionApplication["Admission application"]
admissionDecision["Admission decision"]
studentAttribute["Student attribute"]
studentCohort["Student cohort"]
person --> permanentAddress
person --> priorSchool
person --> familyAddress
person --> familyRelationship
person --> admissionApplication
person --> admissionDecision
admissionApplication --> admissionDecision
person --> studentAttribute
admissionApplication --> studentAttribute
person --> studentCohort
admissionApplication --> studentCohort
end
ethos["Ellucian Ethos APIs"]
banner["Banner ERP"]
slate --> canonical --> person
entities --> ethos --> banner
classDef pipeline fill:#EEEDFE,stroke:#534AB7,color:#26215C
classDef mutation fill:#FAECE7,stroke:#993C1D,color:#4A1B0C
classDef failure fill:#FAEEDA,stroke:#854F0B,color:#412402
classDef readonly fill:#E1F5EE,stroke:#0F6E56,color:#04342C
classDef neutral fill:#F1EFE8,stroke:#5F5E5A,color:#2C2C2A
class canonical pipeline
class person,permanentAddress,priorSchool,familyAddress,familyRelationship,admissionApplication,admissionDecision,studentAttribute,studentCohort,ethos,banner mutation
class slate neutral
| Entity | What it carries | Ethos resource |
|---|---|---|
| Person | Match an existing Banner person (by Banner ID or Slate ID) or create one |
persons v12 |
| Permanent address | The applicant's Banner address |
persons v12 |
| Prior school | High school code, graduation date, GPA |
high-school-information-high-school-details v1 |
| Family address | Parent/guardian address |
general-person-identification-address v1 |
| Family relationship | Parent/guardian record and relationship type |
guardian-information v1 |
| Admission application | Application header, curricula, term/level/campus/program |
admissions-application-curricula v1 |
| Admission decision | Admit / deny / waitlist code and date |
admissions-decision-processing v1 |
| Student attribute | Attribute records tied to the application |
admissions-application-contacts-cohorts-attributes v1 |
| Student cohort | Cohort records tied to the application |
admissions-application-contacts-cohorts-attributes v1 |
See Ethos & Banner Prerequisites for exactly what to grant for each of these, and Configuration Reference for how source data maps into them.
- Installation & Requirements — for whoever installs the software: supported platforms, npm vs. source installs, and what the two shipped binaries do.
- Ethos & Banner Prerequisites — for whoever administers your Banner/Ethos environment, before you touch the CLI at all: the integration user, the Ethos application/proxy, and exactly which resources need to be granted.
-
Configuration Reference — for whoever writes
s9terpsync.yaml: every field, section by section, and how secrets are referenced without ever landing in plain YAML. -
Running S9TerpSync — for the operator doing a manual run:
run,run resume, andrun recover-lock, and how dry-run and live modes differ. - Service & Systemd Operation — for whoever stands this up as a long-lived service: the systemd install plan, the service-level lock, and where state, logs, and secrets live on disk.
- Retention, Replay & Recovery — for whoever cleans up after an interrupted or partially-failed run: retention policy, replaying incomplete records, and retry manifests.
- Diagnostics & Troubleshooting — for whoever gets paged when a run fails: local diagnostics, Ethos contract status, and what each exit code means.
- Architecture Overview — for contributors: the module boundaries and design constraints behind the codebase, not a how-to-contribute guide.