Skip to main content

OTP Verification Settings

Overview

OTP Config is a LINE OA level setting that determines whether phone number verification by OTP is enabled and, if so, how it behaves. It applies to forms that need confidence the phone number entered genuinely belongs to the person filling them in.

What makes this module unusual is that it is a per-OA singleton: the otp_config table has a unique constraint on line_oa_id, so instead of multi-row CRUD there are only GET and PUT, where PUT performs an upsert. If no configuration exists yet, GET returns an empty or default config rather than a 404, because "not configured yet" is a normal and common state.

This module was written fresh for the Go implementation and has no NestJS predecessor.

Business Flow

  1. The user opens the OTP settings screen in cms-web, which calls GET /api/otp-config. The service reads the otp_config row matching the lineOaId in CLS. When no row exists it returns a default or empty config representing the "not configured" state, without throwing.
  2. The user fills in the settings — whether OTP is enabled, the delivery provider, code length, code lifetime, and message text — then saves.
  3. PUT /api/otp-config performs an upsert keyed on line_oa_id, updating the existing row or creating one if none exists.
  4. Forms with OTP enabled read this configuration at runtime. client-api sends the OTP to the respondent and only accepts the form submission once verification succeeds.
  5. With OTP disabled, forms accept submissions immediately with no verification step.

Key Files & Functions

Core code lives in internal/modules/otpconfig/, comprising controller.go, service.go, and dto.go.

MethodRouteHandlerPolicy (metadata)
GET/api/otp-configct.getread otp-config
PUT/api/otp-configct.upsertupdate otp-config

Both routes are registered on the authed group, which applies global JWT authentication; no ModuleGate wraps them. The code follows the structure of the quickreply module, adapted to a singleton as described in the doc comment in service.go.

Connections to Other Services

  • Access control — requests must pass global JwtAuth and the token must carry a lineOaId. The PolicyModuleOtpConfig = "otp-config" enum is aligned with cms-web's MODULE_URL.OTP_CONFIG.
  • Tablesotp_config, with a unique constraint on line_oa_id.
  • Context — reads lineOaId from CLS to scope the record.
  • Design specdocs/superpowers/specs/2026-07-26-form-otp-verification-design.md, section "1. OTP config store".
  • Consumers — Form Builder and line-management-client-api-go, which actually sends and verifies the OTP.