Technical documentation
For developers and coding agents: what AssayLink is, what is already built, and how to change it without breaking the product rules.
Agent brief (read this first)
Goal: a POC that can mature into a product — the assay definition layer (intended TDP successor): AI-assisted template discovery, metadata authoring, vocabulary governance and template review. Not experimental execution data. Stewardship and controlled vocabulary are first-class, not an afterthought.
Two rules that override everything else:
- Build a metadata-driven, vocabulary-governed assay template product, not a JSON viewer.
- Design so every hard-coded demo behaviour can later become governed configuration.
Canonical project instructions also live in the repo root
CLAUDE.md. Prefer this HTML pack for humans and offline
export; keep CLAUDE.md as the short agent policy file.
What is implemented today
| Capability | Status |
|---|---|
Next.js 15 App Router app under src/web/ | Done |
| Prisma + PostgreSQL schema, migrations, seed from 4 JSON sources | Done |
| Three personas with capability-based auth (mock cookie) | Done |
| Grouped catalogue, template detail, lifecycle statuses | Done |
| Metadata-driven authoring wizard (by section) + draft edit | Done |
| Steward review queue + review decision form | Done |
| Vocabulary CRUD, suggestions gate, change log | Done |
| Metadata model: Assay Definition Knowledge Model (sections, field–vocabulary map, rules) | Done |
| Metadata Quality Score (completeness, vocabulary, rules) | Done |
| Free-text matcher with explained scoring and rule-derived gaps | Done |
| Hybrid extraction (rules + optional Claude / Azure OpenAI) | Done (mock default) |
| Project-first flow via MaRLay mock + ProjectAssayLink | Done |
Static HTML docs at /docs/ | Done |
| Real Entra/ALB SSO | Designed, not wired |
| Real MaRLay HTTP client | Mock client shaped for swap |
| Reusable assay subtypes as a primary object | Out of primary UX (ADR-0003) |
| Protocol / instruments / data-output blocks | FUTURE sections on the section map |
Non-negotiable engineering rules
-
Layering:
app/→server/services/→server/repositories/→server/db.ts. Components never call Prisma. -
Domain types live in
src/domain/, framework-free, with Zod. - Metadata model is data — sections, fields, rules and vocabulary terms; never hard-code controlled values in UI components.
-
AI only under
src/server/ai/, Zod-validated, cannot activate vocabulary terms or approve templates. -
Auth checks only via
src/server/auth/(guardCapability/requireCapability). -
Build context is
src/web/— nothing the Docker image needs may live above that folder. -
Before claiming work done:
npm run lint,npm run typecheck,npm testinsrc/web.
Repository map
ph-rnd-assaylink/
├── CLAUDE.md # Agent/project policy (short)
├── config.yml # ONLY infra file to edit
├── terraform/ # DO NOT MODIFY (upstream)
├── docs/ # Markdown ADRs & product notes (source material)
├── .github/workflows/ci.yml # Our CI
├── docker-compose.yml # Local Postgres
├── dev.sh # One-command local start
└── src/web/ # Entire application (Docker build context)
├── prisma/ # Schema, migrations, seed
├── public/docs/ # THIS documentation (static HTML)
├── src/app/ # Routes, server actions
├── src/components/ # UI
├── src/domain/ # Types + Zod
├── src/server/ # services, repositories, ai, auth, integrations
└── tests/ # unit, integration, e2e
Markdown under repo docs/ (ADRs, meeting notes) remains the
historical design record. Prefer linking to those for deep decisions;
this HTML site is the navigable export for users and agents.
Architecture → · Implementation detail → · How to continue development →