# ARC knowledge graph

**ARC (Assessment Resource Connector)** is Pearson's LTI 1.3 tool that sits between school LMSs and the
AD (Authoring & Delivery) test engine. Teachers and students launch it from their LMS; ARC syncs the class
roster, auto-assigns tests (mainly the PRoPL interim product), launches students into the AD player inside a
lockdown browser, pulls scores back from AD and posts grades to the LMS gradebook. Pearson staff configure
it in an admin portal. Go (Echo + GORM + dig) backend, Vue 3/PrimeVue SPA, Aurora Postgres, two SQS queues, ECS Fargate.

## Start here
1. [[arc-server]] — bootstrap, DI, routes, middleware, sessions; how the backend is wired.
2. [[lti-launch]] — how every user gets in; creates [[context]] / [[member]] / [[context-member]].
3. [[take-assessment]] and [[saveoff-and-passback]] — the core student-to-gradebook path.
4. [[attempt]] — the central entity (its id is the AD session id).
5. [[resource]], [[offering]], [[platform]], [[platform-offering]] — what admins configure.
6. [[app-api]], [[admin-api]], [[proctor-api]], [[lti-api]] — every HTTP route with its auth.
7. [[ad-client]] / [[ad-api]] — everything ARC asks of AD.
8. [[postgres]] — table -> node index and the migration baseline.
9. `permissions.md` — who can call what (short version: one cookie per audience, almost no role checks).

## Main flows
[[lti-launch]], [[sync-class-roster]], [[auto-assign-assessments]], [[take-assessment]], [[testnav-handoff]],
[[lockdown-breach-handling]], [[saveoff-and-passback]], [[teacher-proctoring]], [[external-proctor-small-group]],
[[view-score-reports]], [[admin-content-setup]], [[upload-offering-document]], [[admin-rescore-attempts]],
[[refresh-dashboard-stats]], [[deploy-release]].

## Layout
`main.go` boots everything. `server/` is layered by kind, not domain: `routes/` -> `controllers/` (thin) ->
`services/` (business logic, interfaces in `services/interfaces/`) -> `repositories/` (GORM). The graph regroups
these into domain modules: [[lti]] + [[names-and-roles]] (LTI and roster), [[admin]] (portal backend),
[[app-backend]] (teacher/student API), [[delivery]] (launch/player/tokens), [[proctoring]] (proctoring, small groups),
[[async-workers]] (SQS saveoff/passback), [[stats-cron]], [[ad-client]] (`server/proxy_clients/ad`).
`client/` is the SPA ([[arc-client]]: [[admin-ui]], [[teacher-ui]], [[learner-ui]], [[external-proctor-ui]]).
`lockdown/` is the Chrome extension ([[lockdown-extension]]); `emulator/` a local LMS ([[lms-emulator]]);
`infra/` Terraform + CI ([[infra]]); `load-testing/` k6 ([[load-testing]]); `internal/propl_data` reporting-config tooling ([[propl-data]]).

## Conventions
- **Run locally:** `mise install`; copy `.env.example` to `.env`; `podman compose up -d` (Postgres + LocalStack queues/bucket);
  `make run` (Vite on https://secure.localhost:40444 + `air` server) or `npm run dev` + `go run main.go`.
  Admin portal at `/#/admin/login`. Use [[lms-emulator]] (`make emulator`) to launch as a teacher/student.
- **New service:** file in `server/services/` with an interface, constructor `NewXxx`, register in
  `server/di/container.go`, inject through constructor params. Controllers stay thin.
- **Routes:** `server/routes/*_routes.go`; pick the middleware for the audience (`RequireAdminSession`,
  `UnauthorizedOnMissingLTISession`, `RequireSGSession`) and add a role check yourself if needed — none is implied.
- **Migrations:** golang-migrate up/down pair in `server/database/migrations/` (`migrate create -ext sql -dir ./migrations name`),
  wrapped in `BEGIN; … COMMIT;`, timestamp newer than anything on the base branch (CI `check_migration_order`).
  Embedded and applied at startup by `MigrateUp`. Never edit the `20261005120000_initial` baseline.
- **Tests:** `make test` (Go; service tests in `server/services/tests/`, controller tests in `server/controllers/tests/`),
  `npm run test:unit` in `client/` (Vitest). Mocks: `make mocks` (mockery v2.53.6 into `server/tests/mocks`).
- **Deploy:** merge to `dev` -> smk/dev/perf; `release/*` or `hotfix/*` -> uat/prd ([[deploy-release]]). Don't use `internal/deploy/*.sh`.
- **Never** send `Resource.Connection` (AD client secret) to the browser (STARCPE-552).

## Known gaps worth knowing before you build
- Cookie store key is the literal `"secret"`; sessions are forgeable ([[arc-session]]).
- LTI launch doesn't validate state/nonce/deployment ([[lti]]); `/api/ad/event` is unauthenticated ([[ad-event-webhook]]).
- Almost no role checks on teacher endpoints; several IDORs ([[app-api]]).
- LTI private key is committed and baked into the image ([[lti-signing-key]]).
- Dead tables: [[credential]], [[legacy-session]], [[legacy-session-outcome]], [[user]].
