Skip to main content

Implementation Portal Module

Technical module reference for apps/backend/src/implementation-portal/.

This page is focused on architecture and backend behavior. For operations and incident handling, use:

  • dev/runbooks/implementation-portal-troubleshooting

Module purpose

Implementation Portal models delivery work as tenant-scoped boards with:

  • reusable templates (phases/steps)
  • execution workflows for team and client participants
  • billable tracking and invoice drafting
  • portal-facing collaboration (attachments/comments) with OTP-secured write access

Hexagonal architecture mapping

Domain layer

Key entities:

  • ImplementationBoard
  • BoardPhase
  • BoardStep
  • TimeEntry
  • StepAttachment
  • StepComment
  • InvoiceDraft
  • GuideTemplate + guide phase/step/resource entities

Key services:

  • BoardFactoryService (template -> board tree)
  • InvoiceCalculatorService (billable line-item rules)
  • OverdueCheckerService (board health scoring)

Ports:

  • repositories for templates/boards/steps/invoices/client sessions
  • STORAGE_PORT, PAYMENT_PORT, NOTIFICATION_PORT

Application layer

Use-case orchestration under application/use-cases/*, including:

  • template CRUD/clone/resource use cases
  • board create/update/status lifecycle
  • step completion/assignment/time/attachment/comment operations
  • client OTP/session and portal step actions
  • invoice draft generation and send flow

Infrastructure layer

  • Kysely repositories (infrastructure/persistence/kysely/*)
  • storage adapter: gcs-storage.adapter.ts
  • payment adapter: stripe-invoice.adapter.ts
  • notification adapter: sendgrid-notification.adapter.ts
  • overdue queue processor: overdue-notification.processor.ts

Interfaces layer

  • staff-facing controllers:
    • guide-template.controller.ts
    • implementation-board.controller.ts
    • board-step.controller.ts
    • invoice-draft.controller.ts
  • client-facing controller:
    • client-portal.controller.ts
  • guard:
    • portal-session.guard.ts

Infrastructure concerns (HTTP/DB/GCS/Stripe/SendGrid) remain outside domain behavior.


Primary workflows

1) Guide template -> implementation board

  1. Team creates guide template.
  2. Team creates board with optional templateId.
  3. BoardFactoryService clones template phases/steps and applies due offsets from board start date.

2) Team step execution

Team endpoints allow:

  • step status transitions
  • assignment and due-date updates
  • time-entry logging on hourly steps
  • step attachments and comments

3) Client portal flow

  1. Client reads board via GET /portal/:shareToken.
  2. Client requests OTP.
  3. Client verifies OTP and receives session token.
  4. Client uses guarded write endpoints (complete/approve step, upload, comment).

4) Invoicing

  1. GenerateInvoiceDraftUseCase computes line items from eligible unbilled steps.
  2. Team can edit line-item descriptions.
  3. SendInvoiceDraftUseCase pushes invoice and items through payment adapter, finalizes, marks sent, then emits best-effort notification.

Step and billing rules

Step transitions

From BoardStep domain behavior and completion use cases:

  • pending -> in_progress
  • in_progress -> completed (non-approval steps)
  • in_progress -> approved|rejected (approval steps)
  • rejected -> in_progress (rework)
  • completed|approved -> client_approved

Completion constraints

  • document steps require at least one attachment before completion (team + client paths)
  • client completion is limited to client-assigned steps
  • client approval requires current status completed or approved

Time-entry constraints

From LogTimeEntryUseCase and TimeEntry:

  • allowed only when billableType=hourly
  • minimum entry: 0.25 hours

From step controller write guards:

  • time entries cannot be edited/deleted once step is linked to an invoice draft

Invoice calculator rules

From InvoiceCalculatorService:

  • non_billable: excluded
  • fixed: bill when completed|approved|client_approved
  • milestone: only approval steps in approved|client_approved
  • hourly: sum(hours) * hourlyRate only when completed|approved|client_approved

File and comment behavior

Step attachments

From StepAttachment + upload use case:

  • max size: 50 MB (STEP_ATTACHMENT_MAX_BYTES)
  • MIME type must be in allowlist
  • key pattern: portal/{boardId}/steps/{stepId}/{timestamp}-{sanitizedFilename}

Storage adapter behavior:

  • requires GCS_PUBLIC_BUCKET
  • signed URLs generated for read actions in listing endpoints

Comments

From PostStepCommentUseCase:

  • client-authored comments are always persisted as client_visible
  • team comments can use internal/client visibility via team endpoints

Health and notification model

Health scoring

OverdueCheckerService:

  • green: 0 overdue
  • yellow: 1-2 overdue
  • red: 3+ overdue OR stale board (>7 days without step updates)

Notification events

Notification port events currently include:

  • BOARD_ACTIVATED
  • CLIENT_STEP_READY
  • IMPLEMENTER_STEP_DONE
  • STEP_OVERDUE
  • PHASE_COMPLETED
  • BOARD_COMPLETED
  • INVOICE_SENT
  • FILE_SHARED

Emission points are use-case driven and mostly best-effort (non-blocking for main workflow).


Client session model

From OTP/session use cases and guard:

  • OTP TTL: 15 minutes
  • portal session TTL: 24 hours
  • guard token sources:
    • x-portal-session-token header
    • flowpos-portal-session cookie

Client portal read payload intentionally excludes billing-sensitive fields.


High-level endpoint groups

Team APIs

  • /businesses/:businessId/guide-templates/*
  • /businesses/:businessId/implementation-boards/*
  • /businesses/:businessId/board-steps/*
  • /businesses/:businessId/invoice-drafts/*

Client portal APIs

  • /portal/:shareToken
  • /portal/:shareToken/auth/request-otp
  • /portal/:shareToken/auth/verify-otp
  • guarded portal write routes under /portal/:shareToken/steps/*