Skip to content

feat(kyc): expose submission completeness on personal and financial data - #195

Draft
joshuakrueger-dfx wants to merge 4 commits into
DFXswiss:developfrom
joshuakrueger-dfx:feat/kyc-step-submit-fields
Draft

feat(kyc): expose submission completeness on personal and financial data#195
joshuakrueger-dfx wants to merge 4 commits into
DFXswiss:developfrom
joshuakrueger-dfx:feat/kyc-step-submit-fields

Conversation

@joshuakrueger-dfx

@joshuakrueger-dfx joshuakrueger-dfx commented Jul 28, 2026

Copy link
Copy Markdown

Draft — blocked on the API side. The endpoints do not report submission completeness. See
"Status" below.

Status

This PR was written against DFXswiss/api#4426, which has since been closed without merging. The
API does not send complete or missingFields on either submit endpoint, and there is currently no
open API PR that would add them.

Both fields are optional, so merging this would not break anything at runtime — but it would ship an
SDK type promising fields that no deployment returns. complete would arrive as undefined from
every real response, and a consumer writing if (!result.complete) would treat every submit as
incomplete. That is why this stays a draft rather than being merged on the grounds of being additive.

What the API side did land instead:

What is in this PR

  • KycStepSubmit extending KycStepBase with optional complete and missingFields, and the
    matching return types on KycApi.setPersonalData / setFinancialData and the hook. Held until
    an API change actually emits the fields.
  • KycFinancialQuestion.conditions is a named KycFinancialCondition interface instead of an
    anonymous inline object. The field was already typed and readable; consumers can now import the
    type instead of restating the shape. This part is independent of the API and would be safe on its
    own, but it is cosmetic and does not carry a PR by itself.

Purely additive — existing consumers reading only KycStepBase fields are unaffected.

Tests

kyc-api.test.ts follows the pattern of bank-api.test.ts: it pins the exact call shape of each
endpoint (URL, method, body, token: false, x-kyc-code header) and asserts that the response
passes through the client unchanged. One case covers a response without the two fields, which only
compiles while they are optional.

@dfx.swiss/core: 7 suites, 74 tests, 5 of them new (69 on develop).

Counter-proofs, each run on this revision. In all three type cases the file's tests are not counted
at all, so the suite line is the signal, not the test line:

Mutation Result
return type back to KycStepBase Test Suites: 1 failed, 6 passed (TS2339 on result.complete)
complete? back to required Test Suites: 1 failed, 6 passed (TS2741 at the response literal)
missingFields? back to required Test Suites: 1 failed, 6 passed (TS2741 at the response literal)
client drops missingFields at runtime Tests: 1 failed, 73 passed

Gates: lerna run lint and lerna run format:check clean across all 4 projects; core and react
build. No version bump or changelog per CONTRIBUTING; versioning happens through the publish
workflow.

What has to happen before this can go ready

  1. The response body of a failing financial submit from the sandbox, so the reported symptom is
    attributed to a cause instead of a plausible one.
  2. If that confirms the fields are the right answer, an API PR that emits them — for the financial
    endpoint at least. On the personal endpoint the field would be constant: the global
    ValidationPipe rejects any incomplete body with 400, so after a successful call the only
    required field that can still be unset is mail, which is owned by the ContactData step.

The API returns whether a submission was complete and which required fields
are still missing. Type the two submit calls accordingly so consumers can
surface the information, and model the previously anonymous question
conditions as a named interface.
@joshuakrueger-dfx
joshuakrueger-dfx marked this pull request as ready for review July 28, 2026 10:26
Consumers pin this library independently and can run against an API
deployment that does not report submission completeness yet. With both
fields required, a consumer reading `result.complete` gets undefined and
treats a submission that in fact succeeded as incomplete - the inverse of
the symptom this contract is meant to remove. Both fields are now optional
with a documented absence case, following ApiException.switchToCode.

The test restated what the type system already enforces: three guard
helpers plus the same fact asserted up to six times per case. Reverting
the return type flags the plain field access before it reaches any of the
helpers, so they detected nothing. What remains follows bank-api.test.ts -
the exact call shape per endpoint, the response passing through unchanged,
and one case for a response without the two fields, which only compiles
while they are optional.
@joshuakrueger-dfx
joshuakrueger-dfx marked this pull request as draft July 31, 2026 14:10
@joshuakrueger-dfx

Copy link
Copy Markdown
Author

Converted to draft. The API counterpart (DFXswiss/api#4426) was closed without merging, so no deployment returns complete or missingFields.

Both fields are optional, so this is technically safe to merge — which is exactly the risk. complete would come back undefined from every real response, and if (!result.complete) then reads as "incomplete" on every submit, including successful ones. Better to hold the type than to ship a contract nothing serves.

Two things came out of reviewing the API side that are worth recording here:

conditions was never the gap. It has been sent at runtime since DFXswiss/api#2071 and was already typed in this package as an inline object — and DFXswiss/services evaluates it in two places (src/screens/kyc.screen.tsx:1981, src/app2/screens/kyc-steps.tsx:982) with the same expression the backend uses. The client could always compute which questions apply. DFXswiss/api#4541 only writes it into the Swagger contract; it unblocks nobody.

The reported symptom is still undiagnosed. Both frontends evaluate the submit response through isStepDone(result), which checks [IN_REVIEW, ON_HOLD, COMPLETED].includes(result.status). On an incomplete submit that is false, and neither screen has a branch for it — no message, no error, nothing moves. Whether missingFields is the right answer to that, or whether the form should not be able to submit an incomplete set in the first place, cannot be decided without the actual response body from the sandbox run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant