Forms — Code Map
All paths absolute from the repo root.
API (NestJS)
| File | Role |
|---|---|
apps/api/src/forms/forms.module.ts | DI wiring. Imports MembershipsModule + R2Module; exports FormsService. The reverse hook (auto-issue) flows over EventEmitter, not DI — no forwardRef needed. |
apps/api/src/forms/forms.controller.ts | Two controllers: FormsController mounted at /organizations/:orgId/forms (auth), FormsPublicController mounted at /forms/sign/:token (public, @Public()). |
apps/api/src/forms/forms.service.ts | Domain service. ~1070 lines. Template CRUD, instance issuance (single + bulk + auto-issue), token mint, both signing paths, signed-PDF presign, member + staff reads. Constants: SIGNING_TOKEN_BYTES=32, SIGNING_TOKEN_TTL_MS=7d. |
apps/api/src/forms/pdf.service.ts | Puppeteer-based Hebrew RTL PDF renderer. Singleton browser (browserPromise), closed on onModuleDestroy. Uses @sparticuz/chromium in prod; honors PUPPETEER_EXECUTABLE_PATH for macOS dev. |
apps/api/src/forms/forms.service.driver.ts | Test driver. Used by forms.service.unit.spec.ts. |
apps/api/src/forms/forms.service.unit.spec.ts | Unit tests. |
apps/api/src/forms/dto/create-form.dto.ts | Template create DTO. Compliance shape (no recurrence); check-in shape (no validityPeriodDays) enforced at the service layer in assertKindShape. |
apps/api/src/forms/dto/update-form.dto.ts | Patch + bump-version DTO. All fields optional. |
apps/api/src/forms/dto/assign-compliance-form.dto.ts | { formId, assigneeUserId }. |
apps/api/src/forms/dto/submit-form-answers.dto.ts | { answers: FormAnswers }. Detailed shape validated by Zod inside the service. |
API — adjacent
| File | Role |
|---|---|
apps/api/src/r2/r2.service.ts | S3 client wrapping Cloudflare R2. getComplianceBucket(), upload(key, bytes, mime, {bucket}), getPresignedUrlCached, getPresignedUploadUrl, getObjectBytes. The compliance bucket key (R2_COMPLIANCE_BUCKET_NAME) falls back to the default bucket when unset. |
apps/api/src/r2/r2.module.ts | Global. Exposes R2Service. |
apps/api/src/memberships/membership-events.ts | MEMBERSHIP_ACTIVATED event token. Emitted by MembershipsService and OrganizationLeadsService. Consumed by FormsService.handleMembershipActivated. |
apps/api/src/auth/public.decorator.ts | @Public() marker used on the /forms/sign/:token routes. |
apps/api/src/uploads/uploads.service.ts | Authenticated staged-PUT presigns. Used by the in-app signing flow (signature PNG upload) — NOT by the tokenized flow (which has its own bespoke presign). |
apps/api/src/ai/agent/tools/leaves/forms.tools.ts | Spotter-agent tool surface for compliance — out of scope here. |
Shared (@fitkit/shared)
| File | Role |
|---|---|
libs/shared/src/lib/schemas/forms.ts | Source of truth for: formKindEnum, complianceStatusEnum, checkInStatusEnum, complianceTypeKeyEnum (the six FIT-158 slugs), formFieldSchema (discriminated union: text, free_text, checkbox, date, number, scale, photo, multi_choice, signature), formAnswersSchema, recurrenceSchema, createFormSchema, submitFormAnswersSchema, formResponseSchema, formInstanceResponseSchema, state machine maps complianceTransitions + checkInTransitions, helpers canTransitionCompliance / canTransitionCheckIn. |
libs/shared/src/lib/schemas/forms-presets.ts | Pre-built FormField[] skeletons for the six compliance type-keys, labelled in Hebrew, aligned with Israeli regulatory minima (PAR-Q for health declaration, gym contract conventions for the rest). |
libs/shared/src/lib/agent-schemas/forms.ts | Spotter-agent tool descriptors — out of scope. |
libs/shared/src/lib/utils/roles.ts | isStaffRole(role). |
Database (@fitkit/db)
| File | Role |
|---|---|
libs/db/src/lib/schema/forms.ts | Drizzle definitions for forms, form_instances, form_signatures + relations + types. CHECK constraints + partial-unique indexes encoded here. |
libs/db/src/lib/schema/enums.ts | formKind (compliance, check_in), formStatus (8-value superset; CHECK constraint narrows per kind). |
libs/db/drizzle/ | Migration journal. New forms-touching migrations land here. |
Web (apps/web — Next.js)
| File | Role |
|---|---|
apps/web/src/app/[lang]/(protected)/dashboard/forms/page.tsx | Staff forms list page. |
apps/web/src/app/[lang]/(protected)/dashboard/forms/new/page.tsx | New template builder route. |
apps/web/src/app/[lang]/(protected)/dashboard/forms/[formId]/page.tsx | Template detail (edit, publish, bump version, assign, coverage). |
apps/web/src/components/overview/forms/forms-list-page.tsx | List table component. |
apps/web/src/components/overview/forms/template-editor.tsx | Form builder UI. |
apps/web/src/components/overview/forms/template-detail-page.tsx | Detail / actions panel. |
apps/web/src/components/overview/forms/form-field-builder.tsx | Field editor (add/remove/reorder). |
apps/web/src/components/overview/forms/assign-compliance-dialog.tsx | Single-member assignment + bulk-missing tab. |
apps/web/src/components/overview/forms/generate-signing-link-dialog.tsx | Token mint + copy-to-clipboard UI. URL: ${origin}/${lang}/forms/sign/${token}. |
apps/web/src/components/overview/members/member-forms-tab.tsx | Per-member audit tab on the member detail page. |
apps/web/src/components/overview/members/member-forms-tab.driver.tsx | Driver for member-forms-tab.int.spec.tsx. |
apps/web/src/components/overview/members/member-compliance-tab.tsx | Member’s own pending-forms tab (in-app authenticated signing — pending FIT-178). |
apps/web/src/app/[lang]/forms/sign/[token]/page.tsx | Pending (FIT-178) — public signing page. Not yet present. Referenced by generate-signing-link-dialog.tsx. |
i18n
| File | Keys |
|---|---|
apps/web/src/i18n/dictionaries/en.json | forms.* block: title, subtitle, newTemplate, kind.{compliance,checkIn}, status.*, instanceStatus.*, columns.*, complianceTypeKey.*, builder.*, fieldTypes.*, detail.*, memberTab.*, assign.*, signingLink.*, publishWarning.*, autoIssue.*. |
apps/web/src/i18n/dictionaries/he.json | Hebrew labels. Source of truth for the signed PDF body text fallbacks. |
apps/web/src/i18n/dictionaries/ru.json | Russian labels. |
Test inventory
| File | Type |
|---|---|
apps/api/src/forms/forms.service.unit.spec.ts | API unit. |
apps/web/src/components/overview/forms/template-detail-page.int.spec.tsx | Web integration. |
apps/web/src/components/overview/forms/template-editor.int.spec.tsx | Web integration. |
apps/web/src/components/overview/forms/assign-compliance-dialog.int.spec.tsx | Web integration. |
apps/web/src/components/overview/members/member-forms-tab.int.spec.tsx | Web integration. |
| Playwright e2e | None yet for the signing flow — to add as part of FIT-178 QA. |
Configuration
| Env | Purpose |
|---|---|
R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET_NAME | Cloudflare R2 credentials. |
R2_COMPLIANCE_BUCKET_NAME | Dedicated bucket for signed PDFs. Falls back to R2_BUCKET_NAME in dev. |
PUPPETEER_EXECUTABLE_PATH | Override Chromium binary path on macOS dev. Prod uses @sparticuz/chromium. |
FRONTEND_URL | Used in the WebSocket gateway, not forms — but generate-signing-link-dialog.tsx derives the public URL from window.location.origin on the web client. |