course-service 0.2.0

Course Service — a course-administration microservice modelled on schema.org/Course; interoperates with the course-matcher crate
docs.rs failed to build course-service-0.2.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

Course Service

A registry of course identities based on schema.org/Course. The Course Service is the abstract template (CS101 — Introduction to Computer Science); its CourseInstance sub-resource is the specific offering (CS101, Fall 2026, Prof. Smith, in-person). One course → many instances.

Sits between the Thing Service (anything with an identity) and the Event Service (occurrences with locations and parties).

Status. Production-ready MVP. FR-1..FR-9 (CRUD / search / match / merge / dedup) + FR-10..FR-13 (instance sub-resource) + FR-14..FR-18 (audit / streaming / privacy) are all wired. Only JWT auth (T-15) remains, blocked on the family-wide auth rollout. See spec.md §13 for the per-task ledger.

Quick start

Option 1: Podman compose (recommended)

# From the repo root because the Dockerfile pulls in the sibling
# course-matcher crate via the path dependency.
cd course-service-rust-crate
cp .env.example .env

# Brings up postgres + course-service.
podman compose up -d

# Wait for healthy:
podman compose logs -f course-service

# Service on host port 8084 (avoids clashing with person-service on 8080).
curl http://localhost:8084/api/health

Option 2: native build

# Prerequisites: Rust 1.93+, PostgreSQL 17+, podman (optional).
cp .env.example .env

# Set up the database.
podman run -d --name course-postgres -p 5434:5432 \
  -e POSTGRES_DB=course \
  -e POSTGRES_USER=course_user \
  -e POSTGRES_PASSWORD=course_password \
  postgres:17-alpine

# Apply migrations (manual — auto-migrate is out of scope for MVP).
for m in migrations/*/up.sql; do
  podman exec -i course-postgres psql -U course_user -d course < "$m"
done

# Build and run.
cargo run --release

API

REST routes mount under /api/courses/* and /api/courses/{id}/instances/*. See AGENTS/restful.md for the full list. All endpoints return the standard {success, data, error} envelope.

Interactive OpenAPI 3 documentation ships with the binary:

  • Swagger UI: http://localhost:8084/swagger-ui
  • Raw spec: http://localhost:8084/api-docs/openapi.json

The Event Service uses /api/v1/; Course does NOT — direct /api.

Configuration

Variable Description Default
DATABASE_URL Postgres connection string
DATABASE_MAX_CONNECTIONS Pool max 10
DATABASE_MIN_CONNECTIONS Pool min 2
SERVER_HOST REST bind address 0.0.0.0
SERVER_PORT REST port 8080
SEARCH_INDEX_PATH Tantivy index directory ./data/search_index
MATCHING_THRESHOLD Probabilistic match cutoff 0.85
RUST_LOG tracing-subscriber filter info
OTLP_ENDPOINT OpenTelemetry collector http://localhost:4317

Testing

# 35 unit tests (matcher facade, search index, validation, db
# helpers, streaming, privacy, repository conversions).
cargo test --lib

# 14 bridge tests pinning the service ↔ canonical course-matcher
# contract (identical clones, deterministic short-circuits, per-enum
# routing, config presets).
cargo test --test duplicate_detection

# 12 DB-backed integration tests. Skipped by default — opt in with
# `--ignored` after the Postgres bring-up below.
DATABASE_URL=postgres://course_user:course_password@localhost:5434/course \
  cargo test --test api_integration_test -- --ignored

# Three criterion benches (matching, search, validation).
cargo bench

See AGENTS/testing.md for the layout and docker-compose.yml for the dev Postgres bring-up the integration suite expects to be migrated against.

Compliance

  • GDPR: right of access via GET /api/courses/{id}/export; right to erasure via soft-delete + /masked view.
  • FERPA: masked view conceals instructor / student identifiers on CourseInstance records; audit log preserves access trail.

Status

  • Persistence: SeaORM entities + transactional repository CRUD (T-2 / T-3); CourseInstance sub-resource (T-8); merge bookkeeping.
  • Search: Tantivy SearchEngine with exact / fuzzy / blocking queries; reader reload after every commit (T-4).
  • Matching: canonical course-matcher driven through the service-side adapter (T-6); 14 bridge tests pin the contract (T-11).
  • Validation: FR-21..FR-28 with nested-instance path prefixes (T-5).
  • REST: FR-1..FR-9 + FR-14..FR-18 wired (T-7 / T-8 / T-9 / T-10); OpenAPI via utoipa (T-14).
  • Audit + streaming: AuditLogRepository + in-memory EventPublisher MVP (T-9). Fluvio adapter under feature flag pending.
  • Privacy: mask_course + GDPR Article-15 export (T-10).
  • Tests: 35 unit + 14 bridge + 12 #[ignore]-tagged integration (T-12) + 3 criterion benches (T-13).
  • Auth: JWT (T-15) blocked on the family-wide rollout.

License

Dual-licensed under MIT OR Apache-2.0 OR BSD-3-Clause OR GPL-2.0-only OR GPL-3.0-only.