University of Peradeniya crestSCS Documentation
University of Peradeniya crestSCS Documentation
Department website

Start here

Repository handbookRepository overviewDevelopment

System design

ArchitectureAuthentication and authorizationPublic dataAPI contractsSchemas
UI system

Applications

Department Web applicationPeople applicationProjects applicationPortal application

Services

API serviceGitHub App serviceMailer service
Service internals
API internalsAPI request lifecycleAPI identity and stateAPI public-data mutations

Shared packages

Schemas packageUI packageTypeScript configuration packageESLint configuration package

Development workflow

Testing and verificationDependency managementDocumentation authoringUI quality assurance

Operations

Continuous integrationEnvironment variablesOperationsSecurityTroubleshooting

Reference

Route referenceGlossary
Service internalsAPI service

How profile, project, course, and offering reads and Git-backed changes are authorized and orchestrated.

API public-data mutations

Public data is repository-owned. The API reads published JSON for display and validation, but sends all Git mutations to GitHub App. This keeps browser sessions, GitHub App credentials, and repository writes in separate trust zones.

Common mutation flow

The asynchronous path is selected by Prefer: respond-async. The API uses an explicit caller idempotency key when supplied, otherwise creates one. It hashes the normalized actor email into an opaque subject ID and sends a fresh correlation ID. Raw email is not used as the durable operation actor identity.

Concurrency controls

Mutation bodies may include an expectedRevision. The API passes it through to GitHub App, where it is compared with the current authoritative file revision. A mismatch becomes a conflict that tells the editor to refresh; the service must not silently overwrite a newer repository version.

An idempotency key identifies one actor's logical request. Reusing it with the same input returns the existing operation; reusing it for different input is a conflict. These controls solve different problems and should be preserved together.

Domain rules

DomainRead and selection behaviorMutation authorization
profilesresolves published profile plus placement metadata and derives fields the editor may not chooseusers edit their allowed profile kind; admins may target other users; kind-specific identity and placement fields remain locked
student placementinterprets programme, stream, department, batch, alumni, and postgraduate registriesadministrative placement workflows own registry metadata rather than trusting a profile form
projectslists bounded records and checks published or draft membershipa non-super-admin must be a recognized project person; only super-admins delete registry projects
courses and offeringsreads individual files and bounded registriesacademic users and super-admins may edit; the record id is locked to the route identity

The schema-description endpoints return capabilities, identity context, locked fields, and explanatory notes so Portal can build a truthful editor. They do not replace server authorization.

Published reads

Published JSON URLs are constructed from DATA_PUBLIC_BASE_URL and fixed path families. Services parse fetched data before using it for authorization or metadata interpretation. A public endpoint returning malformed data is an upstream failure, not permission to accept an unvalidated edit.

Operation status and cancellation

/api/operations/{id} proxies GitHub App status and cancellation. The API derives the actor subject from the current session and forwards it in a trusted internal header. GitHub App uses that subject to prevent one user from reading or cancelling another user's operation. Terminal status and outcome shapes are defined in @scs/schemas and described in API contracts.

Adding a new mutable domain

Define the shared transport and domain schema first, then add API authorization and validation, a GitHub App resource/action and repository implementation, operation compatibility tests, and Portal handling for queued, running, succeeded, conflicted, failed, and cancelled outcomes. A browser route must never bypass the API to reach GitHub App.

API identity and state

Better Auth policy, D1 tables, permission resolution, proxy state, and administrative safety invariants.

GitHub App internals

Source map, trust boundary, domain ownership, and verification guide for Git-backed automation.

On this page

API public-data mutationsCommon mutation flowConcurrency controlsDomain rulesPublished readsOperation status and cancellationAdding a new mutable domain