Skip to content

Database Table Reference ​

Complete reference of all database tables in the SDASIS Student Information System, organized by domain.

For lookup tables (lookup_*), see Lookup Codes Reference.


Core ​

TablePurposeKey Relationships
countriesCountry reference data (ISO codes, names, visa requirements)Referenced by people, person_addresses, campuses
sys_currenciesCurrency codes, symbols, and decimal precisionReferenced by billing tables
sys_institution_settingsInstitution-wide configuration key-value pairsStandalone settings store
ui_translationsMulti-language UI translation stringsStandalone
email_templatesEmail message templates (code, subject, HTML body)Used by notification services

Academic ​

Calendar & Terms ​

TablePurposeKey Relationships
academic_yearsAcademic calendar years with start/end datesParent of academic_terms
academic_termsTerms (Fall, Spring, etc.) within academic yearsFK: academic_year_id -> academic_years, term_type_id -> lookup_term_type
sub_termsMini-terms or sub-sessions within a termFK: term_id -> academic_terms
term_campus_offeringsWhich campuses offer which termsFK: term_id, campus_id

Courses & Sections ​

TablePurposeKey Relationships
coursesCourse master catalog (code, title, credits, level)FK: status_id -> lookup_course_status, course_level_id -> lookup_course_level
course_attributesAttribute flags on courses (e.g., writing-intensive)FK: course_id, attribute_type_id -> lookup_course_attribute
course_requisitesPrerequisites, corequisites, antirequisites entered by hand. The importer never writes it; Colleague's rules are in course_requisite_linksFK: course_id, requisite_course_id, requisite_type_id -> lookup_requisite_type
course_requisite_linksEvery Colleague requisite rule a course carries (migration 285): timing P = earlier term (prerequisite), C = same term (corequisite), E = either; enforcement RQ = required, RM = recommended (not enforced). block_id is the rule's requirement-block tree. Rebuilt by migrate-requirements --steps=course-prereqs from CRS_REQS, falling back to the legacy CRS_PREREQS only where a course has no newer prior ruleFK: course_id -> courses, block_id -> requirement_blocks (both ON DELETE CASCADE)
course_equivalentsEquivalency mappings between coursesFK: course_id, equivalent_course_id, equivalence_type_id -> lookup_equivalence_type
course_sectionsSection instances of courses per termFK: course_id, term_id, campus_id, class_id, status_id, instruction_mode_id -> lookup_instruction_mode (derived modality), instructional_method_id -> lookup_instructional_method (declared pedagogy, migration 263). colleague_section_id is Colleague's COURSE_SECTIONS_ID (migration 293): the import matches on it, follows renames in place and deletes stamped sections Colleague no longer has; NULL for sections planned in the SIS
classesGrouping of sections (cross-listed, combined)FK: term_id, status_id -> lookup_class_status
class_sectionsJunction: classes to sectionsFK: class_id, section_id
section_schedulesDead. Meeting times live on the section's schedule container -- course_sections.class_id -> class_schedules. Nothing reads this table; migrate-daily --redo=classes truncates itFK: section_id, room_id
section_instructorsInstructors assigned to teach sectionsFK: section_id, teacher_id, instructor_role_id -> lookup_instructor_role. source is SIS (the default, screen-entered) or ODS (imported); the import deletes only ODS rows Colleague stopped listing (migration 293)
course_substitutionsCatalog/program-level course substitutionsFK: original_course_id, substitute_course_id, bulletin_id, major_id
student_course_substitutionsPer-student course substitutions for degree auditFK: student_id, original_course_id, substitute_course_id, block_id

Schedule Templates ​

TablePurposeKey Relationships
schedule_templatesReusable schedule patterns (MWF 50min, TR 75min)Parent of schedule_template_entries
schedule_template_entriesTime slots within a schedule templateFK: template_id -> schedule_templates
class_schedulesClass meeting schedule (template-based or custom); the live source of meeting times for a section, via its container. One row per (class, day, start) -- uq_class_schedules_class_day_start, migration 213FK: class_id, template_id, room_id, schedule_type_id -> lookup_schedule_type

Bulletins & Catalogs ​

TablePurposeKey Relationships
bulletinsAcademic bulletins/catalogs with effective datesFK: bulletin_type_id, status_id
bulletin_academic_yearsJunction: bulletins to academic yearsFK: bulletin_id, academic_year_id
course_bulletinsCourses listed in a bulletinFK: course_id, bulletin_id, teaching_frequency_id
course_bulletin_periodsTerm periods when bulletin courses are offeredFK: course_bulletin_id

Degrees, Majors & Minors ​

TablePurposeKey Relationships
degreesDegree programs (BA, BS, MA, etc.)FK: degree_level_id, department_id, college_id, bulletin_id, status_id
degree_blocksJunction: degrees to requirement blocksFK: degree_id, block_id
degree_approved_minorsMinors approved for a degreeFK: degree_id, minor_id
degree_default_advisorsDefault advisors assigned to degreesFK: degree_id, advisor_id
majorsMajor programs within degreesFK: degree_id, department_id, bulletin_id, status_id
major_blocksJunction: majors to requirement blocksFK: major_id, block_id
major_campus_offeringsCampuses where a major is offeredFK: major_id, campus_id
major_default_advisorsDefault advisors for majorsFK: major_id, advisor_id
minorsMinor programsFK: department_id, bulletin_id, status_id
minor_blocksJunction: minors to requirement blocksFK: minor_id, block_id
minor_campus_offeringsCampuses where a minor is offeredFK: minor_id, campus_id
minor_default_advisorsDefault advisors for minorsFK: minor_id, advisor_id

Requirements ​

TablePurposeKey Relationships
requirement_blocksRequirement block definitions (GenEd, Major Core, etc.)FK: block_type_id -> lookup_block_type, bulletin_id, parent_block_id, min_grade_id
requirement_groupsGroups of requirements within a blockFK: block_id
requirement_group_rulesLogic rules for requirement groupsFK: block_id
requirement_itemsIndividual course/non-course requirementsFK: block_id, group_id, requirement_type_id, course_id, course_pattern_id, min_grade_id
requirement_item_coursesJunction: requirement items to specific coursesFK: item_id, course_id
course_patternsPattern-based course matching (e.g., "all MATH 300+")FK: bulletin_id, department_id
course_pattern_exclusionsCourses excluded from a patternFK: pattern_id, course_id

Course Materials ​

TablePurposeKey Relationships
materialsTextbook/material master records (ISBN, title, author)FK: material_type_id, oer_license_id
material_formatsAvailable formats for a material (print, digital)FK: material_id, format_type_id
materialsMaterials assigned to coursesFK: course_id, material_id, requirement_id, adoption_status_id
section_material_assignmentsMaterials assigned to specific sections (overrides)FK: section_id, material_id, requirement_id, adoption_status_id

Organization ​

TablePurposeKey Relationships
campusesPhysical and online campus locationsFK: country_id -> countries
buildingsCampus buildingsFK: campus_id -> campuses
roomsClassrooms and meeting spaces with capacityFK: building_id -> buildings, room_type_id -> lookup_room_type
room_featuresFeatures available in rooms (projector, whiteboard)FK: room_id, feature_id -> lookup_room_feature
colleges_schoolsCollege/School organizational unitsStandalone
departmentsAcademic and administrative departmentsFK: parent_department_id (self-referential hierarchy)
department_college_mappingJunction: departments to collegesFK: department_id, college_id
unit_course_codesMaps course code prefixes to departments/collegesFK: department_id, college_id

People ​

TablePurposeKey Relationships
peopleMaster person record (DOB, demographics, FERPA)FK: gender_id, ethnicity_id, religion_id, country_of_birth_id, citizenship_country_id, marital_status_id, veteran_status_id, primary_language_id
person_namesName variants (legal, preferred, maiden, etc.)FK: person_id, name_type_id -> lookup_name_type. source is SIS or ODS (migration 298); a person can hold a current PREFERRED row beside the current LEGAL_PRIMARY, so join on a name type or use core.person_display_name()
person_addressesMailing, permanent, campus addressesFK: person_id, address_type_id -> lookup_address_type
person_phonesPhone numbers by typeFK: person_id, phone_type_id -> lookup_phone_type
person_emailsEmail addresses by typeFK: person_id, email_type_id -> lookup_email_type
person_identifiersGovernment IDs, SSN, passport numbersFK: person_id, identifier_type_id -> lookup_identifier_type
person_racesMulti-race tracking per personFK: person_id, race_id -> lookup_race
person_visa_statusImmigration/visa status tracking: status, program and entry dates, sponsor and financial support, work authorization, and the US-only sevis_status / form_type (migration 281)FK: person_id, visa_type_id -> lookup_visa_type
person_citizenshipsCitizenships beyond the primary people.citizenship_country_id, one row per country (migration 281). Any citizenship of the HOME_COUNTRY setting makes a person domesticFK: person_id, country_id -> countries
person_name_display_configName display preferences per document typeFK: person_id, document_type_id, name_type_to_use_id
person_name_audit_logAudit trail for name changesFK: person_name_id, person_id
person_test_scoresStandardized test scores (SAT, ACT, etc.)FK: person_id, test_type_id
person_activitiesExtracurricular activities and organizationsFK: person_id, activity_type_id -> lookup_activity_type
person_essaysApplication essaysFK: person_id, application_id, essay_type_id
person_recommendationsLetters of recommendationFK: person_id, application_id, relationship_id -> lookup_recommender_relationship
person_honorsAwards and honors receivedFK: person_id, recognition_level_id -> lookup_recognition_level
person_family_membersFamily member informationFK: person_id, relationship_id -> lookup_family_relationship, education_level_id
person_photosUploaded person photos with approval workflowFK: person_id, approval_status_id -> lookup_photo_status
person_merge_logAudit log when two person records are mergedFK: primary_person_id, secondary_person_id, merged_by_user_id

Roles ​

Student Role ​

TablePurposeKey Relationships
studentsStudent role records (enrollment status, campus, IPEDS)FK: person_id, student_status_id, initial_term_id, primary_campus_id, ipeds_residency_id, ipeds_student_type_id. Cohort membership moved to student_cohorts in migration 181
student_admission_status_historyAdmission status change historyFK: student_id, status_id -> lookup_admission_status
student_academic_status_historyAcademic status change history (good standing, probation)FK: student_id, status_id -> lookup_academic_status, major_id
student_campus_assignmentsCampuses a student is allowed to register atFK: student_id, campus_id
student_majorsJunction: students to declared majorsFK: student_id, major_id, status_id
student_minorsJunction: students to declared minorsFK: student_id, minor_id
probation_alert_logTracks probation alerts sent to studentsFK: student_id, major_id

Other Roles ​

TablePurposeKey Relationships
teachersTeacher role records. display_first_name / display_last_name hold Colleague's faculty listing name (migration 298), which records.instructor_display_name() shows before the person's own nameFK: person_id, status_id -> lookup_teacher_status
advisorsAdvisor role recordsFK: person_id, advisor_type_id, advisor_role_id
applicantsApplicant role records (linked to applications)FK: person_id, application_term_id, program_id, status_id -> lookup_applicant_status
cohortsStudent groups of an institution-defined type. Colleague-sourced rows carry source = 'ODS' and are refreshed nightly; the importer inserts but never reclassifies themFK: cohort_type_id, academic_year_id, major_id, start_term_id, expected_graduation_term_id. start_date/end_date apply only when the type has uses_dates
lookup_cohort_typeCohort kinds, with per-type rules (uses_dates, allow_multiple, requires_major, unique_per_level, requires_campus, requires_start_term, supports_auto_sync, allows_bulk_assign)Extended lookup, owned by the roles domain
student_cohortsDated cohort membership, replacing students.cohort_idFK: student_id, cohort_id, academic_level_id. An open membership has end_date IS NULL. Membership is concurrent -- a student holds several at once. source = 'ODS' marks the importer's rows, which is what scopes its delete pass; created_by IS NULL does not mean migration-owned here
student_listsCustom student lists (advising, reporting)Standalone with student membership
class_standing_thresholdsCredit thresholds for class standing (FR, SO, JR, SR)FK: standing_lookup_id -> lookup_class_standing

Registration ​

TablePurposeKey Relationships
student_term_enrollmentsStudent enrollment record per termFK: student_id, term_id, enrollment_status_id
student_section_enrollmentsStudent enrollment in specific course sections. midterm_grade_source (SIS/ODS, migration 292) says who wrote the midterm; the import never overwrites SIS. incomplete_deadline / incomplete_default_grade_id / incomplete_workflow_instance_id (migration 295) hold an approved Incomplete request's termsFK: student_id, section_id, enrollment_status_id, grade_id, midterm_grade_id
enrollment_status_historyAudit trail for enrollment status changesFK: enrollment_id, old_status_id, new_status_id
registration_transactionsMulti-step registration workflow instancesFK: student_id, term_id, campus_id, transaction_type_id, current_step_id, status_id, initiator_role_id
transaction_enrollment_itemsSections being added/dropped in a transactionFK: transaction_id, section_id, action_type_id, item_status_id
transaction_step_historyStep transition audit for transactionsFK: transaction_id, from_step_id, to_step_id
hold_typesRegistration hold type definitionsStandalone
student_holdsActive holds placed on studentsFK: student_id, hold_type_id, term_id, created_by_person_id
hold_evaluation_logAudit log for automated hold evaluationsFK: hold_type_id
planned_coursesCourses planned for future registration (advising)FK: student_id, section_id, requirement_item_id, planned_by_person_id, status_id
section_waitlistsWaitlist entries for full sectionsFK: section_id, student_id, status_id -> lookup_waitlist_status

Degree Audit ​

TablePurposeKey Relationships
student_degree_progressOverall degree completion tracking per studentFK: student_id, degree_id, catalog_year_id
student_requirement_fulfillmentPer-block fulfillment status within degree progressFK: progress_id, block_id
requirement_waiversWaivers or substitutions for requirementsFK: student_id, block_id, item_id, waiver_type_id -> lookup_waiver_type, approved_by_id
transfer_creditsTransfer credit evaluations from other institutions. Status PRE_APPROVED (migration 295) is a course approved before it is taken: it counts nowhere and is left off the transcriptFK: student_id, equivalent_course_id, status_id -> lookup_transfer_credit_status, credit_type_id
graduation_applicationsStudent applications to graduateFK: student_id, degree_id, graduation_date_id, expected_graduation_term_id
graduation_datesCeremony dates with application deadlinesFK: term_id
graduation_recordsConferred degree recordsFK: student_id, degree_id, graduation_date_id, graduation_type_id, honors_id
graduation_record_honorsExtra honors on a conferred degree (language, music, leadership), one row per honor; entered manually, never importedFK: graduation_record_id, graduation_honor_id -> lookup_graduation_honor
graduation_application_status_historyStatus change audit for graduation applicationsFK: application_id

Grading ​

TablePurposeKey Relationships
grading_systemsGrading scale definitions (e.g., Standard 4.0)Parent of grading_system_grades
grading_system_gradesIndividual grade definitions within a systemFK: grading_system_id

Billing ​

TablePurposeKey Relationships
billing_settingsBilling system configurationStandalone
billing_methodsBilling calculation methods (per-credit, flat, banded)Parent of billing_method_configs
billing_method_configsConfiguration per billing methodFK: method_id
credit_rate_schedulesPer-credit billing rates by term/residency/levelFK: term_id, method_id, residency_id, degree_level_id
billing_bandsBanded billing tiers (min/max credits -> flat amount)FK: method_id, term_id, residency_id
fee_typesFee classifications (technology, lab, activity)Standalone
term_feesFees charged for a specific termFK: term_id, fee_type_id, residency_id, degree_level_id
term_fee_bandsBanded term fee tiersFK: term_fee_id
term_fee_categoriesCustom fee groupings per termFK: term_id
term_fee_category_bandsBanded custom fee tiersFK: category_id
payment_plansPayment plan templates (installment count, down payment %)Standalone template
payment_plan_termsTerms applicable to each payment planFK: plan_id, term_id
payment_plan_eligibilityEligibility criteria (residency, credits)FK: plan_id, residency_id, student_type_id
payment_plan_feesFees within payment plansFK: plan_id, fee_type_id
payment_plan_schedulesInstallment due datesFK: plan_id
student_billing_transactionsStudent billing records (charges, payments)FK: student_id, term_id, status_id
student_payment_plan_enrollmentsStudent enrollment in payment plansFK: student_id, term_id, plan_id, status_id

Admissions ​

TablePurposeKey Relationships
admission_applicationsApplication records with status trackingFK: applicant_id, form_template_id, status_id, decision_id
application_checklist_itemsRequired documents and tasks per applicationFK: application_id, status_id -> lookup_checklist_status
application_documentsUploaded application documentsFK: application_id, document_type_id
application_reviewsFaculty/staff reviews of applicationsFK: application_id, reviewed_by_person_id, recommendation_id
recruiter_assignmentsRecruiter-to-applicant assignmentsFK: applicant_id, recruiter_id, term_id
student_inquiriesProspect inquiries and interest trackingFK: prospect_person_id, program_id, source_id

Financial Aid ​

TablePurposeKey Relationships
award_typesFinancial aid award definitions (scholarships, grants, loans)Standalone template
awardsIndividual student awards with lifecycle statusFK: person_id, term_id, award_type_id
fafsa_dataFAFSA submission data (EFC/SAI, Pell eligibility)FK: person_id, application_id
financial_estimatesCost of attendance estimates with aid projectionsFK: person_id, term_id, degree_id, fafsa_data_id
estimate_cost_itemsItemized cost components in an estimateFK: estimate_id
estimate_awardsAwards included in a financial estimateFK: estimate_id, award_id

Form Builder ​

TablePurposeKey Relationships
form_templatesDynamic form definitions (application forms)FK: status_id -> lookup_form_template_status
form_sectionsLogical sections within formsFK: template_id, condition_field_id
form_fieldsIndividual form fields with type and validationFK: section_id, field_type_id -> lookup_form_field_type
program_form_templatesLinks forms to academic programsFK: template_id, program_id
form_responsesSubmitted form dataFK: template_id, person_id, application_id

Authorization ​

TablePurposeKey Relationships
rolesSystem role definitions (admin, registrar, faculty)Standalone
permission_nodesPermission tree hierarchy (menu items + actions)FK: parent_node_id (self-referential)
role_permissionsPermissions assigned to rolesFK: role_id, node_id
user_rolesRoles assigned to usersFK: user_id, role_id
role_permissionsDirect permissions assigned to users (overrides)FK: user_id, node_id
institution_domainsAllowed email domains for authenticationStandalone
dashboard_tilesDashboard widget configuration per roleFK: role_id
user_impersonation_sessionsLog of admin impersonation sessionsFK: admin_user_id, impersonated_user_id
audit_logGeneral audit log (table/record/action/changes)Standalone

Authentication ​

TablePurposeKey Relationships
auth_usersUser accounts with credentialsFK: person_id -> people
application_access_tokensAPI access tokens (integrations)FK: user_id, token_type_id -> lookup_access_token_type

Workflow ​

TablePurposeKey Relationships
registration_workflowsRegistration workflow definitionsStandalone
registration_workflow_stepsSteps within a workflow (search, cart, pay, confirm)FK: workflow_id, step_type_id -> lookup_workflow_step_type
workflow_step_transitionsValid transitions between stepsFK: from_step_id, to_step_id
workflow_automation_rulesRules for automatic step advancementFK: rule_type_id -> lookup_automation_rule_type

Proxy Access ​

TablePurposeKey Relationships
student_proxy_accessParent/guardian proxy access grantsFK: student_id, proxy_person_id, relationship_id -> lookup_proxy_relationship_type
proxy_invitationsPending proxy access invitationsFK: student_id, relationship_id
proxy_access_permissionsSpecific permissions granted to proxy usersFK: proxy_access_id

Test Scores ​

TablePurposeKey Relationships
standardized_test_typesTest type definitions (SAT, ACT, GRE, etc.)Standalone
institution_test_score_policiesInstitution test score policiesStandalone

LMS Integration ​

The lms schema (migration 199). An LMS type is data, not code: a connector type plus versioned operation definitions describes how to call a given LMS.

Connector definitions ​

TablePurposeKey Relationships
connector_typesOne kind of LMS: auth strategy, pagination style, default rate limits. Seeded with CANVAS, MOODLE, BRIGHTSPACEParent of connector_operations; referenced by instances
connector_operationsOne named operation on a type (verify, create_course, enroll_user, post_grade, ...)FK: connector_type_id
operation_versionsVersioned JSONB definition of an operation - URL, headers, body template, response and error mapping. A change adds a version rather than overwritingFK: operation_id

Instances, credentials and mappings ​

TablePurposeKey Relationships
instancesOne LMS tenant. Carries dry_run, match_strategy, drop_behavior, create_missing_users, grade_passback_enabled, and shell name/code templatesFK: connector_type_id
instance_credentialsWrite-only secrets, AES-sealed with a rotating keyring. is_active is partial-unique; activating one retires the incumbent in the same transactionFK: instance_id, rotated_from_credential_id
instance_access_tokensCached OAuth tokens, encrypted at restFK: instance_id
instance_term_mappingsSIS term to the LMS's term or session id. An unmapped term never provisionsFK: instance_id, term_id
instance_role_mappingsSIS role to LMS enrollment roleFK: instance_id
instance_org_unit_mappingsSIS org unit to the LMS account or org unit a shell is created underFK: instance_id, org_unit_id
assignment_rulesWhich sections route to which instance, by org unit and/or campus, by priority (lowest wins)FK: instance_id, org_unit_id, campus_id
sync_policyGlobal, not per instance: provisioning and enrollment triggers and lead times, conclude policy, and what each kind of drift should doSingle row

Shells, enrollments and sync ​

TablePurposeKey Relationships
course_shellsThe LMS course created for one or more sections. sis_course_id (migration 251) records the id actually sentFK: instance_id
shell_sectionsJunction: shells to sections. Several sections share one shell when cross-listedFK: shell_id, section_id
section_overridesPins one section to one instance regardless of the assignment rulesFK: section_id, instance_id
enrollment_linksAn SIS enrollment as reflected in the LMSFK: shell_id
user_mappingsAn SIS person to their LMS userFK: instance_id, person_id
sync_jobsThe work queue. Worked with SKIP LOCKED; the dead letter is a status, not a separate tableFK: instance_id
sync_runsOne pass of a scanner or worker, with stats JSONBFK: instance_id
drift_findingsDifferences between what the SIS believes and what the LMS reports: missing enrollment, extra enrollment, missing shellFK: instance_id
integration_logEvery rendered request and its outcomeFK: instance_id
export_runsOne SIS CSV export. One active run per instance, enforced by the databaseFK: instance_id
export_filesThe files a run producedFK: export_run_id
export_watermarksPer-instance delta position for exportsFK: instance_id
passback_watermarksPer-instance position in records.grade_change_log. The first scan only initialises it, so enabling passback never replays historyFK: instance_id

The legacy LMS tables are gone

Migration 202 dropped records.lms_platforms, lms_platform_urls, lms_platform_campuses, lms_credentials, lms_user_tokens, lms_sync_log and lms_enrollment_mapping, plus four lookup_lms_* tables. The old subsystem stored API secrets in plaintext despite a migration comment claiming otherwise. The names are listed here so nobody who remembers them reintroduces them.


Payments (ACI portal) ​

The payments schema (migration 153). Storage for the ACI TRANSACT CoBrand+ hosted card-payment portal, which has no database of its own. It gets its own schema rather than joining studentfinance because a different service owns its lifecycle.

TablePurposeKey Relationships
payment_typeWhat can be paid for. Carries aci_product_id and requires_student_verificationReferenced by sessions and transactions
payment_sessionOne visitor's payment attempt: token, matched person, client IP, status, expiryFK: payment_type_id
payment_transactionThe result ACI posts back server to server: amount, result code, confirmation, card last four, fees, mismatch flag, raw postback, and Colleague posting statusFK: payment_session_id, payment_type_id
verification_attemptRate limiting and audit for student-identity verification attempts, by client IPStandalone
payment_type_lineThe lines a payment type is split into, each with its own posting code and kindFK: payment_type_id
payment_transaction_lineHow a completed payment's amount was split across those lines, for postingFK: payment_transaction_id, payment_type_line_id
aci_channelACI channels (code, display name, aci_product_id)Standalone
schema_migrationsThe portal's own migration ledger; these four tables come from the portal's migrations, not database/migrations/Standalone

payments is deliberately outside the audit trigger

core.apply_audit_config() only onboards tables in a fixed schema list, and payments is not on it - so no trg_audit_row is attached and the portal's writes need no actor context. If payments is ever added to that list, the portal must start setting app.actor_source = 'PUBLIC_FORM' on its connections or every insert will be rejected by the strict actor check in core.audit_row_change().


Cafeteria (point of sale) ​

The cafeteria schema (migrations 309-313). Storage for the cafeteria point-of-sale service, which replaced a SQL Server database the registers wrote to directly. Like payments, a separate service owns it and nothing in SIS+ reads it; people stay in core.

TablePurposeKey Relationships
accountsOne row per ID card, keyed by the 9-digit card number (type prefix + 7-digit Colleague id). Imported nightly from Colleague; carries a display name of its own for department and vendor cardsFK: person_id (when the card resolves to a person)
account_type_rulesWhat a card type may do: PLAN (charges count against a limit), DIRECT or NONE, and whether its balance window is the charge period or the card's own dates (balance_window, 313)Standalone
charge_periodsThe current charging period for student cards, proposed nightly from records.academic_terms by cafeteria.sync_charge_periods() and editable in the cafeteria admin (313)FK: term_id
cashiersWhich cards may log a register inFK: account_id
registersThe physical terminals; each authenticates with a device token (only its SHA-256 is stored)Referenced by sales and events
product_categories, products, register_buttonsThe catalog and the item buttons on each registerFK: category_id, register_id
settingsService settingsStandalone
sales, sale_lines, sale_paymentsAppend-only sales. A void is a new negative sale pointing at the original (voids_sale_id); created_by marks back-office voids (311). Each payment names the card charged and, once exported, its charge_exports rowFK: register_id, cashier_id; sale_payments: account_id, charge_export_id
charge_exportsThe nightly charge file sent on to billingReferenced by sale_payments
register_events, report_subscriptions, import_runsRegister log, report recipients (seeded by 312), and import historyFK: register_id

The account_balances view computes each card's balance over its window.

Only the configuration tables are row-audited

cafeteria is enrolled in core.audit_schema_defaults disabled, and only the configuration tables are switched on. Sales are append-only, accounts are rewritten nightly, and events are already a log, so auditing them would double every row for no information. Any writer of an audited table must set app.actor_id / app.actor_source, or core.audit_row_change() rejects the write.


Summary ​

Counted from the live database rather than from this page, so these are the real numbers - including the two schemas this page did not cover until now.

SchemaNon-lookup tableslookup_* tables
records14371
core8641
studentfinance386
lms240
admissions (retired)1912
financialaid (retired)61
payments80
cafeteria160
public10
Total341131

Counted at migration 313. core here excludes the two tmp_ts_snap* scratch tables noted below; counting them gives 343 non-lookup tables and 474 in all.

The complete, always-current picture

This page is curated prose, so it lags the schema. The ER Diagram is generated from the live database and covers all 315 drawn entities across core, records, studentfinance, lms, payments and cafeteria, with every column, type, key and foreign key. Read it as one page. Where the two disagree, the ER diagram is right.


Tables that are documented above but do not exist ​

Each of these appeared in earlier versions of this page. They are listed so the names are not reintroduced by someone who remembers them.

NameReality
auth_magic_linksMagic links are rows in application_access_tokens.
auth_password_resetsPassword-reset links are also application_access_tokens, distinguished by token_type.
auth_user_sessionsSessions live in Valkey, not in Postgres.
form_field_dependenciesNo such table. Conditional display is held on the field itself.
form_field_mappingsNo such table. A field maps to an entity via maps_to_entity / maps_to_field columns.
form_field_optionsNo such table. Option lists come from lookup_* tables via the field type.
grade_rostersNo such table. A roster is assembled from student_section_enrollments.
programsNo such table, and no /programs endpoint either. Degrees, majors and minors are the programme model.
student_programsNo such table. A student's programme is recorded in student_majors and student_minors.
student_term_gpaNo such table. Term GPA is computed; the cached cumulative figure sits on students.cumulative_gpa.
student_transcriptsNo such table. Transcripts are generated on request from enrolments and grades.
test_score_requirementsReferenced by code but absent from the database — see the warning below.

program_test_requirements — resolved

The test-scores repository used to issue SELECT, INSERT and DELETE against program_test_requirements, which exists in no schema (confirmed against pg_class, so not a view either). All five /api/v1/testscores/requirements endpoints failed at runtime, and nothing in the interface called them.

Those endpoints and their Go layer were removed in August 2026. The rest of the test-scores domain was always sound — applicant_test_scores, institution_test_score_policies, standardized_test_types, person_superscore_records and lookup_verification_status all exist — and test scores continue to appear on the student record.

This was the same failure mode as term fees, formbuilder and admissions: a Go layer written against a schema that was never committed. go build cannot catch it, because a table name is a string. internal/router/sql_conformance_live_test.go now does: it reads every SQL literal in internal/domain and asserts each relation it names actually exists.


Not yet documented ​

This page describes 194 of the 305 non-lookup tables in prose. The remaining 111 are listed here so the gap is visible rather than implied. Every one of them is in the ER Diagram with its full column list - this list is about narrative coverage, not about what is known.

Several are whole subsystems that deserve a section here: the generic workflow engine, the org-unit hierarchy, the audit trail, and most of billing.

academic_level_grading_systems  academic_policy_rules  academic_term_slots
applicant_test_score_sections  applicant_test_scores  application_decisions
application_status_history  application_test_scores  ar_code_mappings  audit_schema_defaults
audit_system_config  audit_table_config  audit_trail_deletion_log  billing_student_type_rules
billing_transaction_items  clubs_organizations  cohort_advisors  cohort_majors
colleague_ar_charges  course_fees  course_material_assignments  course_offering_terms
credit_system_conversions  data_change_history  degree_level_grading_systems
email_message_recipients  email_messages  emphasis_areas  emphasis_blocks  fee_schedules
ferpa_change_log  form_composite_responses  form_field_programs  form_field_responses
grade_change_log  grade_releases  hold_type_roles  housing_plans  identifier_access_log
inquiry_sources  institutions  legacy_academic_credits  material_platforms  meal_plans
migration_ods_waivers  migration_watermarks  network_cidrs  networks  org_units
payment_allocations  permission_audit_log  person_relationships  person_superscore_records
photo_sync_runs  program_fees  prospect_communications  proxy_access_audit_log
proxy_invitation_permissions  refund_schedule_entries  refund_schedules
registration_transaction_notes  requirement_item_activities  role_default_tiles
role_email_policies  role_menu_shortcuts  role_network_rules  schema_migrations
section_fee_overrides  sender_address_grants  sender_addresses  sequence_policies
sso_identity_providers  standardized_test_sections  state_provinces  student_academic_levels
student_account_balance  student_activities  student_advisors  student_awards  student_charges
student_class_waivers  student_emphases  student_housing_assignments  student_leaves
student_list_members  student_list_shares  student_meal_plan_elections
student_noncredit_completions  student_organization_membership  student_payment_plan_schedule
student_payments  student_types  teacher_credentials  term_registration_windows
transaction_payment_history  transfer_course_equivalencies  unit_administrators
upfront_payment_discounts  user_active_role  user_dashboard_preferences  user_filter_presets
user_shortcuts  workflow_definitions  workflow_initiator_roles
workflow_instance_parallel_tracking  workflow_instance_step_assignees  workflow_instance_steps
workflow_instances  workflow_step_permissions  workflow_steps  workflow_transitions

tmp_ts_snap and tmp_ts_snap2

These are leftover scratch tables from a data investigation, not part of the schema. Nothing reads them and they can be dropped. The ER diagram excludes them.

Student Information System Documentation