feat(core,schemas,phrases,test): add submitStepUp with its audit key - #9582
Open
wangsijie wants to merge 6 commits into
Conversation
COMPARE TO
|
| Name | Diff |
|---|---|
| packages/console/src/consts/logs.ts | 📈 +71 Bytes |
| packages/core/src/routes/experience/classes/experience-interaction.test.ts | 📈 +9.05 KB |
| packages/core/src/routes/experience/classes/experience-interaction.ts | 📈 +5.93 KB |
| packages/core/src/routes/experience/experience.step-up.openapi.json | 📈 +1.03 KB |
| packages/core/src/routes/experience/index.test.ts | 📈 +5.88 KB |
| packages/core/src/routes/experience/index.ts | 📈 +490 Bytes |
| packages/core/src/routes/experience/middleware/koa-step-up-route-guard.test.ts | 📈 +9 KB |
| packages/core/src/routes/experience/middleware/koa-step-up-route-guard.ts | 📈 +2.37 KB |
| packages/core/src/routes/experience/verification-routes/password-verification.test.ts | 📈 +814 Bytes |
| packages/core/src/routes/experience/verification-routes/password-verification.ts | 📈 +227 Bytes |
| packages/core/src/routes/experience/verification-routes/verification-code.ts | 📈 +616 Bytes |
| packages/integration-tests/src/client/index.ts | 📈 +1.22 KB |
| packages/integration-tests/src/helpers/experience/authorization.ts | 📈 +163 Bytes |
| packages/integration-tests/src/tests/api/experience-api/step-up-interaction/routes.test.ts | 📈 +4.5 KB |
| packages/integration-tests/src/tests/api/experience-api/step-up-interaction/subject-verification.test.ts | 📈 +240 Bytes |
| packages/integration-tests/src/tests/api/experience-api/step-up-interaction/submission.test.ts | |
| packages/integration-tests/src/tests/api/oidc/acr-interaction-policy.test.ts | 📈 +118 Bytes |
| packages/phrases/src/locales/ar/errors/session.ts | 📈 +266 Bytes |
| packages/phrases/src/locales/de/errors/session.ts | 📈 +260 Bytes |
| packages/phrases/src/locales/en/errors/session.ts | 📈 +225 Bytes |
| packages/phrases/src/locales/es/errors/session.ts | 📈 +229 Bytes |
| packages/phrases/src/locales/fa-ir/errors/session.ts | 📈 +307 Bytes |
| packages/phrases/src/locales/fr/errors/session.ts | 📈 +253 Bytes |
| packages/phrases/src/locales/it/errors/session.ts | 📈 +224 Bytes |
| packages/phrases/src/locales/ja/errors/session.ts | 📈 +271 Bytes |
| packages/phrases/src/locales/ko/errors/session.ts | 📈 +242 Bytes |
| packages/phrases/src/locales/pl-pl/errors/session.ts | 📈 +219 Bytes |
| packages/phrases/src/locales/pt-br/errors/session.ts | 📈 +224 Bytes |
| packages/phrases/src/locales/pt-pt/errors/session.ts | 📈 +225 Bytes |
| packages/phrases/src/locales/ru/errors/session.ts | 📈 +371 Bytes |
| packages/phrases/src/locales/th/errors/session.ts | 📈 +485 Bytes |
| packages/phrases/src/locales/tr-tr/errors/session.ts | 📈 +245 Bytes |
| packages/phrases/src/locales/zh-cn/errors/session.ts | 📈 +175 Bytes |
| packages/phrases/src/locales/zh-hk/errors/session.ts | 📈 +172 Bytes |
| packages/phrases/src/locales/zh-tw/errors/session.ts | 📈 +172 Bytes |
| packages/schemas/src/types/log/interaction.ts | 📈 +663 Bytes |
wangsijie
marked this pull request as ready for review
September 11, 2026 03:12
wangsijie
requested review from
charIeszhao,
gao-sun,
simeng-li and
xiaoyijun
as code owners
September 11, 2026 03:12
wangsijie
force-pushed
the
wangsijie-log-14106-pure-step-up-route-allow-list
branch
from
September 11, 2026 03:30
af42e8b to
e2f75b7
Compare
wangsijie
force-pushed
the
wangsijie-log-14109-add-submitstepup-with-its-audit-log-key-and-pure-step-up
branch
from
September 11, 2026 03:34
d267c37 to
ea8c25b
Compare
3 tasks
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The audit-key type permits invalid non-sign-in keys, and the audit integration assertion can pass using logs from earlier tests.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds the pure step-up completion flow, dedicated audit logging, localized errors, API documentation, and end-to-end coverage.
Changes:
- Implements
submitStepUp()with ACR validation and limited account persistence. - Adds the step-up audit key and console label.
- Adds localized errors and integration/unit coverage.
File summaries
| File | Description |
|---|---|
packages/schemas/src/types/log/interaction.ts |
Adds the step-up audit key grammar. |
packages/phrases/src/locales/zh-tw/errors/session.ts |
Adds the Traditional Chinese error. |
packages/phrases/src/locales/zh-hk/errors/session.ts |
Adds the Hong Kong Chinese error. |
packages/phrases/src/locales/zh-cn/errors/session.ts |
Adds the Simplified Chinese error. |
packages/phrases/src/locales/tr-tr/errors/session.ts |
Adds the Turkish error. |
packages/phrases/src/locales/th/errors/session.ts |
Adds the Thai error. |
packages/phrases/src/locales/ru/errors/session.ts |
Adds the Russian error. |
packages/phrases/src/locales/pt-pt/errors/session.ts |
Adds the Portuguese error. |
packages/phrases/src/locales/pt-br/errors/session.ts |
Adds the Brazilian Portuguese error. |
packages/phrases/src/locales/pl-pl/errors/session.ts |
Adds the Polish error. |
packages/phrases/src/locales/ko/errors/session.ts |
Adds the Korean error. |
packages/phrases/src/locales/ja/errors/session.ts |
Adds the Japanese error. |
packages/phrases/src/locales/it/errors/session.ts |
Adds the Italian error. |
packages/phrases/src/locales/fr/errors/session.ts |
Adds the French error. |
packages/phrases/src/locales/fa-ir/errors/session.ts |
Adds the Persian error. |
packages/phrases/src/locales/es/errors/session.ts |
Adds the Spanish error. |
packages/phrases/src/locales/en/errors/session.ts |
Adds the English error. |
packages/phrases/src/locales/de/errors/session.ts |
Adds the German error. |
packages/phrases/src/locales/ar/errors/session.ts |
Adds the Arabic error. |
packages/integration-tests/src/tests/api/experience-api/step-up-interaction/submission.test.ts |
Covers step-up submission end to end. |
packages/integration-tests/src/helpers/experience/authorization.ts |
Supports custom authorization redirect URIs. |
packages/integration-tests/src/client/index.ts |
Adds resumed authorization handling. |
packages/core/src/routes/experience/index.ts |
Dispatches step-up submissions and audit keys. |
packages/core/src/routes/experience/index.test.ts |
Tests route dispatch and audit selection. |
packages/core/src/routes/experience/experience.step-up.openapi.json |
Documents the dev-feature response. |
packages/core/src/routes/experience/classes/experience-interaction.ts |
Implements pure step-up completion. |
packages/core/src/routes/experience/classes/experience-interaction.test.ts |
Tests step-up completion behavior. |
packages/console/src/consts/logs.ts |
Adds the audit-log display title. |
Review details
- Files reviewed: 28/28 changed files
- Comments generated: 2
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
- Dispatch `POST /experience/submit` on the stored step-up mode: a pure step-up completes through `submitStepUp()`, an allow-list path that asserts the achieved context satisfies `selectedAcr`, writes only the methods the interaction established, and runs no sign-in guard or side effect (`lastSignInAt`, tenant MFA policy, hooks, identity and token-set sync, JIT provisioning are all skipped). - Add `Interaction.SignIn.StepUp.Submit` to the log-key grammar, recording the requested and achieved classes and the proved factor families, and document the operation through a dev-feature OpenAPI supplement. - Add unit coverage for the completion path, the persistence scope and the audit payload, plus pure step-up integration coverage driven through a real Authorization Code Flow on a developer-created application.
- `manualConsent()` follows the resumed authorization directly; probing the interaction URL first consumed the authorization code, so the follow-up request had nothing left to complete. - Give the TOTP user `skipMfaOnSignIn`, so the password sign-in that establishes the session is not challenged for MFA; the step-up still verifies the factor because the requested ACR is what asks for it.
- Add `MockClient.resumeAuthorization()`: a resumed authorization either asks for consent once more or goes straight back to the callback, and both are completed from a single request. Re-requesting a URL that already handed back a callback consumes the authorization a second time, which is what broke the previous fix. - Enroll a separate TOTP user per test: a TOTP code is single-use within its time step, so tests sharing one secret failed the second verification. - Restore the user-controlled MFA settings after the policy test, so the tests that follow still have TOTP enabled.
…heck The submit route appends the interaction snapshot to its audit entry, exactly as it does for a sign-in, so the entry names the verification records the interaction holds. Those are identifiers, not credentials; the credentials check stays.
`persistEstablishedMethods()` writes the identifier or factor the interaction established without the revalidation `submit()` performs, so a duplicate primary email / phone would reach the `(tenant_id, primary_email)` unique constraint as a raw error instead of the 422 the API promises, and a factor disabled in between would be bound anyway. Both guards only run when there is something to write, which the step-up route allow-list keeps unreachable until the establishment and enrollment routes open.
The ACR assertion runs before the subject is read, so a submission that counted no verification is a 403, not the 404 the JSDoc promised. Keep the 404 documented for the shape that does reach it — a counted `bind` proof, which identifies nobody and which the allow-list blocks until establishment opens — and pin that shape with a test instead of deleting the guard.
wangsijie
force-pushed
the
wangsijie-log-14109-add-submitstepup-with-its-audit-log-key-and-pure-step-up
branch
from
September 11, 2026 09:20
ea8c25b to
c097cc6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #9580, which is stacked on #9575. Implements LOG-14109: the pure step-up completion path, the audit log key it writes, and the integration coverage that proves the flow end to end.
submitStepUp()POST /experience/submitdispatches on the stored step-up mode. A pure step-up completes throughsubmitStepUp()instead of asubmit()with exemptions, so a guard or side effect added tosubmit()later never reaches step-up by default.selectedAcr, otherwise 403session.step_up.acr_not_satisfiedwith no interaction result written. The achieved context is aggregated from the interaction's proofs on top of the context the session carried, so a submission that counted no verification derives nothing and fails there.toUserMfaVerifications(), and a newly established password or primary identifier fromprofile.data. Establishing is wired in a later milestone, so a step-up that only verifies existing methods runs no user write at all.submit()runs: no captcha, no tenant MFA or profile policy, no passkey suggestion, nolastSignInAt, no SSO identity sync, no social / SSO token-set upserts, no JIT organization provisioning, no post-sign-in action, no data-hook context.acr/amr;achievedAcrmay be stronger thanselectedAcr.Audit log
Interaction.SignIn.StepUp.Submitkey in the log-key grammar (packages/schemas/src/types/log/interaction.ts). Its payload recordsrequestedAcrValues,selectedAcr, the achieved ACR and the proved factor families, plus the client id the experience middleware already prepends. A successful and a rejected submission each write one entry, with the outcome on the entry'sresult/error.Interaction.SignIn.Verification.{type}.{action}keys are unchanged.Dev featureOpenAPI supplement.Integration coverage
New
step-up-interaction/submission.test.tsdrives a developer-created OIDC application through a real Authorization Code Flow:1favia the pinned password and via the pinned primary email code,mfavia the enrolled factor alone on a1fasession, a1fa-only submission rejected whenmfawas selected and then completed by the missing factor,max_age=0forcing an active verification without forcing the password, the session context being replaced rather than merged, nolastSignInAtwrite and no tenant MFA policy, a mid-flow refetch, and the audit entries for both outcomes.Testing
Unit tests
The new integration suite needs a running Logto and Postgres, so CI is its first execution.