# Abigail knowledge graph

Abigail is Pearson's summative-assessment layer on top of the **Authoring & Delivery (AD)** platform ("AD" means Authoring & Delivery, not Active Directory). AD remains the system of record for items, forms, stimuli, media, standards and statistics. Abigail adds:

- multi-tenant accounts, banks and fine-grained role-based access control (RBAC);
- content reviews, with external reviewers who join by code;
- administrations and test profiles;
- AI generation, verification and translation through an external Content Agent;
- form extracts, Paper IDs, and the Toni style-guide authoring tool.

Stack: Go + Echo + GORM + PostgreSQL 17 (`server/`), Vue 3 + PrimeVue + Pinia (`client/`).

## Start here
1. [[server-bootstrap]]: `server/main.go` wiring, the middleware order, and how migrations run at startup.
2. [[web-client]]: the SPA shell. Covers the router guard, client-side permission checks, the generated API client and session expiry.
3. [[auth]] and [[auth-api]]: JWT cookie sessions, SSO, impersonation, and external-review tokens.
4. [[bank]], [[account]] and [[user]]: the tenancy model. A bank has one home account and can be shared with other accounts through [[account-bank]].
5. [[bank-role]], [[bank-role-permission]] and [[bank-role-status-permission]]: per-bank RBAC. See also `permissions.md`.
6. [[ad-content]], [[ad-content-api]] and [[ad-client]]: the proxy to AD. Most user-facing content screens go through it.
7. [[review-service]]: reviews and join codes.
8. [[bulk-request-service]], [[job-queue]] and [[content-agent-proxy]]: AI and bulk work running on the Postgres queue.
9. [[toni]]: style guides, which are fed to the Content Agent.
10. [[db-migrations]] and [[postgres-main]]: schema and seeds.

## Main flows
- **Sign-in and session:** [[password-login]], [[sso-login]], [[reset-password]], [[login-as-user]], [[redeem-join-code]].
- **Content authoring:** [[save-content]] (items, stimuli and forms all go through the same gates: status edit, required metadata, field restrictions, edit locks), [[import-export-item-metadata]], [[upload-historical-statistics]].
- **Reviews:** [[request-review]], then [[submit-review-feedback]], then [[export-review-history]].
- **Account and bank admin:** [[invite-user]], [[bulk-import-users]], [[bulk-export-users]], [[copy-bank-config]], [[copy-account-roles]], [[sync-and-share-banks]].
- **Administrations and test profiles:** [[create-administration]], [[validate-test-profile]], [[generate-paper-ids]].
- **AI:** [[run-bulk-ai-request]] then [[approve-ai-generated-content]].
- **Toni:** [[approve-toni-element]] (syncs the style guide to the Content Agent), [[import-toni-package]], [[duplicate-toni-project]].
- **Extracts and ops:** [[run-form-extract]], [[deploy-and-migrate]], [[handle-api-request]] (middleware chain, session expiry headers).

## Module layout
The server is layered, not split by package: each domain runs `server/api/<domain>_*.go` (Echo handlers registered through `api.Module`), then `server/service/` (domain logic), then `server/repository/` (GORM), with `server/models/` as the tables. Request and response contracts live in `server/dto/`.

The graph groups these layers into domain modules:
- [[auth]], [[account-admin]], [[bank-admin]], [[ad-content]], [[review-service]], [[administration-service]], [[test-profile-service]], [[paper-ids]], [[bulk-request-service]], [[extracts]], [[toni]] / [[toni-import]], [[helpdocs]].
- Infrastructure: [[ad-client]] (`server/ad`), [[job-queue]] (`server/queue`, a pgqueue on Postgres), [[content-agent-proxy]] (`server/agent`, `server/agentclient`), [[email]], [[logging]] (including the audit logger), [[server-bootstrap]], [[db-migrations]] and [[dev-tools]].

The client lives in `client/src`. `views/` is split into bank, account, toni, system and pages. Each `*-ui` interface node covers one screen area and declares which server API it `calls`. AD web components (`ad-item-editor`, `ad-test-player`, `ad-standards-picker`) are loaded from AD at runtime ([[ad-web-components]]).

## Conventions an implementer must follow
- **Migrations:**
  - Create them with `migrate create -ext sql -dir server/db/migrations <name>`. Both up and down files are required, each wrapped in `BEGIN; … COMMIT;`.
  - The version must be newer than everything on `origin/main`; `make migrate-check` enforces this.
  - Permission grants and renames go in `server/db/seed/`, which runs in every environment. `server/db/seed_fixtures/` holds local demo data only.
- **Routes:**
  - Add the handler in `server/api/` and register it in that domain's `Register(e, authorized)`.
  - Gate it with `RequireBankPermission` / `RequireAccountPermission` / `RequirePlatformPermission`.
  - A new bank key must also be added to `bankPermissionCatalog`; a new account key to `account_permission_registry.go`.
  - Add Swagger annotations, then run `make codegen` to regenerate `client/src/generated/Api.ts`.
- **AD access:** go through `ADClientFactory` / `ad.Client`. Credentials come from the bank's home [[account-settings]]. Never store AD-owned content locally.
- **Long-running work:** enqueue a [[bulk-request]] through `BulkEnqueueService`, then add a processor in `server/queue/`. Don't spawn goroutines: extract jobs do, and they get stuck when the server restarts.
- **Client:**
  - Pinia stores call the generated API client.
  - Any user-visible string must be an i18n key (`make check-i18n`).
  - Client permission checks are advisory only. The route guard does not scope to the `:bankId` in the URL; the server is the real gate.
- **Gate commands:**
  - `make ready-for-pr` runs codegen-check, i18n/vocab checks, migrate-check, Go and client tests, golangci-lint, Semgrep (it installs itself into `bin/semgrep-venv`), the client lint/format check (which also type-checks the e2e and tooling configs), and a11y.
  - Every `//nolint` must name its linter and give a reason (`nolintlint`).
  - A fixture shared by Go and Vitest must be added to the `client_unit_tests` sparse-checkout in `dev_pipeline.yml`.
  - `make ready-for-pr-full` adds e2e and BDD.
  - Single suites: `make test` (Go), `make test-client`.
  - Local setup: `make deps && make db-up && make migrate-with-seed && make run`. `PG_MAX_CONNECTIONS` in the repo-root `.env` sets local Postgres connections (default 100); raise it for parallel worktree test runs.
- **Release:** check the AD editor docs with `make ad-docs-check VERSION=x.y.z`, then close the check with `make ad-docs-close VERSION=x.y.z` ([[dev-tools]]).

## Known sharp edges (verified by the module pass)
- `POST /api/users/register` has no permission middleware.
- Account-level `/admin_plan` CRUD is not scoped by account (legacy, and the client never calls it).
- `reviews.complete` is never checked. `reviews.manage` is not in the catalog, so it cannot be granted.
- Paper IDs are API-only; no client screen exists.
- Dead code is kept as nodes with `status: dead` (for example [[token-usage-event]]). Filter on `status` in `INDEX.md`.
