Saltar al contenido principal

Implementation Portal Troubleshooting Runbook

Operational runbook for diagnosing backend issues in apps/backend/src/implementation-portal/.

Use this when team users or portal clients report OTP failures, blocked step actions, invoice issues, or attachment problems.


Scope

Primary codepaths:

  • interfaces/http/*.controller.ts
  • interfaces/guards/portal-session.guard.ts
  • application/use-cases/*
  • domain/entities/*
  • domain/services/*

1) Symptom triage

SymptomLikely layer
Client cannot request OTPRequestPortalOtpUseCase + email adapter
OTP verification failsVerifyPortalOtpUseCase + portal session repository
401 Portal session token is requiredPortalSessionGuard header/cookie mismatch
Client cannot complete a document stepCompleteClientStepUseCase attachment precondition
Team cannot log timeLogTimeEntryUseCase + TimeEntry minimum-hours rule
Time entry edit/delete blockedBoardStepController invoice guard (invoiceDraftId)
Invoice send failsSendInvoiceDraftUseCase + payment adapter
Attachments fail uploadUploadStepAttachmentUseCase + storage adapter + MIME/size constraints
Board health unexpectedly redOverdueCheckerService stale/overdue thresholds

2) OTP and portal session flow checks

Expected flow:

  1. POST /portal/:shareToken/auth/request-otp
  2. POST /portal/:shareToken/auth/verify-otp
  3. guarded portal write endpoint with session token

Validated rules from code:

  • OTP request is intentionally non-enumerating from controller perspective (204 response path).
  • OTP TTL is 15 minutes.
  • session TTL is 24 hours.
  • session token can be provided by:
    • x-portal-session-token header
    • flowpos-portal-session cookie

If clients still fail after OTP verify:

  1. confirm token is sent on write request
  2. confirm token is not stale (>24h)
  3. confirm shareToken points to expected board

3) Step-status failures

Team-side completion (board-steps endpoints)

Common blockers:

  • document step has zero attachments (Document steps require at least one attachment...)
  • invalid state transition (for example completing from pending instead of in_progress)
  • approval flow misuse (approve/reject required for approval step types)

Client-side completion (portal endpoints)

Common blockers:

  • step is not client-assigned
  • document step has no attachments
  • client approval called before step reached completed|approved

4) Time-entry failures

From LogTimeEntryUseCase and TimeEntry entity:

  • step must be hourly billed (billableType=hourly)
  • minimum entry is 0.25 hours

From BoardStepController:

  • edit/delete of time entries is blocked once step has invoiceDraftId set

When users report "time log won't save":

  1. verify step billing type
  2. verify hours >= 0.25
  3. verify step has not already been linked to an invoice draft

5) Attachment failures

From UploadStepAttachmentUseCase and StepAttachment entity:

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

From GcsStorageAdapter:

  • requires GCS_PUBLIC_BUCKET
  • signed URLs are generated on read endpoints

Failure patterns:

  • Unsupported file type -> MIME not allowed
  • File size exceeds the 50 MB limit -> too large
  • storage configuration errors -> bucket missing or GCS credentials issue

6) Invoice failures

Draft generation

GenerateInvoiceDraftUseCase only includes unbilled steps and uses InvoiceCalculatorService.

Frequent causes of empty/low totals:

  • steps are non_billable
  • step statuses are not in billable completion states
  • hourly steps have no time entries
  • steps were already linked to another invoice draft (invoiceDraftId)

Send flow

SendInvoiceDraftUseCase sequence:

  1. load draft + board
  2. create invoice in payment adapter
  3. add line items
  4. finalize
  5. mark sent
  6. send notification (best-effort)

If send fails:

  1. verify draft exists and belongs to business
  2. verify draft is still in draft status
  3. inspect payment adapter integration logs

7) Board health anomalies

OverdueCheckerService rules:

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

Terminal statuses excluded from overdue counting:

  • completed
  • approved
  • client_approved
  • rejected

If board health appears too severe, confirm stale condition before changing overdue logic.


8) Safe recovery actions

  1. Re-issue OTP and retry portal session flow.
  2. Re-upload required document attachment before step completion.
  3. Regenerate invoice draft after resolving step/time-entry eligibility.
  4. Re-run send action once payment adapter dependency is healthy.
  5. Regenerate board share token for compromised or misrouted links.