Skip to content

feat: add Cognito login with the user pool in the app stack and an optional user admin UI - #6

Open
lavere wants to merge 28 commits into
mainfrom
feat/cognito-auth
Open

lavere wants to merge 28 commits into
mainfrom
feat/cognito-auth

Conversation

@lavere

@lavere lavere commented Oct 1, 2026 •

Copy link
Copy Markdown

Summary

Adds Cognito as a login option next to Auth0. The user pool is built in this app's own CDK stack, so there is no separate Cognito starter. This combines the earlier version of this PR with Brian's #7 and replaces both.

  • Prompt: one choice of None / Auth0 / Cognito. Cognito is offered only with an AWS env. It then asks for the optional user admin UI, the login domain prefix (validated against Cognito's reserved words and length limit) and MFA (required, optional or off).
  • Stack: a CognitoAuth construct creates the user pool, app client, managed login domain and branding, an admin group, and branded invitation and verification emails. Optional ses sender (with verifiedDomain).
  • Runtime config: the stack writes the pool IDs to /config.json at deploy time and the app loads it before rendering, so one build fits every environment. Local dev reads VITE_APP_COGNITO_* from .env.
  • Login: react-oidc-context, authorization code + PKCE against managed login. Tokens under 60 seconds from expiry are renewed first. A failed renewal is retried while the current token still works; invalid_grant sends the user to sign in again. The renewal changes made after the review have not been run against a real pool.
  • Logout: revokes the refresh token, then calls Cognito's /logout. Handles the back button after signing out.
  • Admin UI (optional): /admin routes to list, invite, edit, disable and delete users, reset passwords and MFA, and manage role membership. There is no backend: an identity pool gives members of the admin group temporary AWS credentials scoped to this pool.
  • Outputs for the API: CognitoIssuer, CognitoUserPoolArn and CognitoClientId (used by create-taxum-api#5).

Includes the TanStack Router / auth0-react build fix from #5. Merge that first; this branch will need a rebase after.

Testing

  • Generator: pnpm test, tsc and biome ci . pass.
  • All six renders (none, auth0, cognito, cognito-admin, and cognito-admin with MFA optional and off) pass their ci-check.sh and pnpm build.
  • Both Cognito renders passed cdk synth with ses set. That run predates the review fixes.
  • End-to-end against real pools, once with only the Cognito part of the stack and the app on localhost, and once with the full stack behind CloudFront on a real domain:
    • /config.json is served uncached with the real pool IDs, and the deployed build logs in with it. Deep links load.
    • Login through managed login, with authenticator setup forced when MFA is required.
    • Access token carries the admin group.
    • Admin UI: list, invite and disable a user, add and remove a role, checked against Cognito's own records.
    • Token renewal with refresh-token rotation, without a trip to the login page.
    • Sign-out ends the session and lands on the login form.

Notes

  • MFA cannot be reset when the pool requires it. Cognito does not list an authenticator that a user enrolls at sign-in, and it accepts AdminSetUserMFAPreference with Enabled=false without changing anything: the next sign-in still asks for a code. Tested from the admin UI and from the CLI. The user page now shows "Required at sign-in", Reset MFA stays disabled for those users, and the README says to delete and re-invite someone who lost their device (they get a new user ID). Reset MFA still applies to methods Cognito does list.
  • Admin role permissions include AdminSetUserPassword and AdminUpdateUserAttributes, which the set-password and edit screens need. Any member of admin can use them from the browser, so an admin can take over any account. The README says so.
  • App client flows are authFlows: { userSrp: false }. Managed login does not need SRP, and refresh-token auth conflicts with rotation.
  • Login logo: Cognito rejects SVG attributes such as version and xml:space, so they were removed from the default favicon.svg.
  • Route tree: a fresh project with the admin UI failed tsc because the shipped routeTree.gen.ts lacks the admin routes. The generator now runs a build after install to regenerate it.
  • SES: the from address or its domain must already be verified. Cognito drops email from an unverified identity without an error.
  • An earlier version had an apiIdentifier option that added an API scope. It was removed after review because the API never checked it; the API limits tokens to this app by client ID.
  • Any admin can add any user to any group, so a group with an IAM role is open to every admin. The README says so.
  • Refresh tokens last 7 days. The admin group is always created; it only gets AWS permissions when the admin UI is included.

🤖 Generated with Claude Code

Jesse LaVere added 18 commits September 30, 2026 10:34
Router no longer exports isPlainArray/isPlainObject and types route errors as unknown.
getAccessTokenSilently can now resolve undefined, which redirects to login.
signoutRedirect revokes it at /oauth2/revoke before leaving for /logout.
A token with under 60 seconds left counts as expired. Concurrent fetches await the same
signinSilent call.
Also note that the other auth errors can hang as well as loop.
The multiselect validates with resolveAuthProvider instead of re-prompting in a loop.
Jesse LaVere and others added 6 commits October 1, 2026 13:47
Nothing read `features`; templates and synth only use `auth`. With one
union type, resolveAuthProvider only needs to reject more than one pick.
The README already explains the localStorage tradeoff, and the useLogout
docblock no longer spells out signoutRedirect's internals.
Offer Cognito as an alternative to Auth0. The CLI now asks for one
authentication provider (None / Auth0 / Cognito), and Cognito is offered
only when an AWS env is configured, since the CDK stack provisions the
user pool.

- Add a CognitoAuth construct that provisions the user pool, managed
  login domain and branding, the app client, and branded invitation and
  verification emails, with optional SES sending
- Deliver the pool IDs to the app at runtime as /config.json, written by
  the bucket deployment, and load it in entry.ts before the app renders.
  Local dev reads the VITE_APP_COGNITO_* variables from the stack outputs
- Sign in through react-oidc-context with the shared AuthGuard and
  useAuthenticatedFetch, now templated per provider, and add a UserMenu
  with sign-out
- Optional cognito-admin feature: an identity pool scoped to an admin
  group, and /admin routes to list, create, edit, disable and reset
  users and to manage role membership through the Cognito admin API
- Validate the domain prefix against Cognito's reserved words and the
  length limit once the environment suffix is added
- test-synth takes a preset (none, auth0, cognito, cognito-admin) and
  synthesizes into test-synth-<preset>

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dmin UI

Merges Brian's feat/cognito branch. The pool, app client, login domain and
emails now live in the app's CDK stack, and the app loads the pool IDs from
/config.json at runtime. Adds the optional /admin user management UI.

Kept from the earlier Cognito branch: the MFA prompt, token renewal that
shares one refresh, the Auth0 token fix, the SES verified-domain option and
an optional API resource server scope. The stack also outputs the issuer and
pool ARN for the API. The generator now rebuilds the route tree when the
admin UI is included, since tsc failed on a fresh project without it.
Cognito rejects a URL as a resource server name, so the name is now fixed.
It also rejects the version and xml:space attributes on the SVG login logo,
so they are removed from the default favicon.
@lavere lavere changed the title feat: add Cognito as a login option feat: add Cognito login with the user pool in the app stack and an optional user admin UI Oct 6, 2026
Jesse LaVere added 2 commits October 5, 2026 22:35
The API starter's example route checks for the admin group, which only
existed when the user admin UI was included. The README now also says what
an administrator can do to other accounts.
In a pool that requires MFA, Cognito does not list the authenticator a user
enrolls at sign-in, so the user page said "Not set up". It now says
"Required at sign-in". Cognito also ignores a reset for those users, so
the README explains to delete and re-invite someone who lost their device.

@lavere lavere left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: comment; 🔴 1 🟠 3 🟢 22 ❓ 2

Posted as a comment because this is the reviewer's own pull request.

# Repo Issue Severity
1 create-react-app CDK type check fails when the admin UI is picked with MFA optional or off 🔴 Blocker
2 create-react-app A failed renewal redirects to login while the current token is still valid 🟠 Should-fix
3 create-react-app The retry stops for good after a manual renewal times out 🟠 Should-fix
4 create-react-app A Cognito project without the admin UI is never told how to create its first user 🟠 Should-fix
5 create-react-app Every admin can join any group, so any future group with an IAM role is open to all admins ❓ Open question
6 create-react-app [Both] The access scope from apiIdentifier is issued but the API never checks it ❓ Open question
7 create-react-app returnTo is used without checking its shape 🟢 Nit
8 create-react-app This catch cannot run 🟢 Nit
9 create-react-app "Concurrent calls share one renewal" only holds per hook instance 🟢 Nit
10 create-react-app The docblock's example is the one case the PR says does not work 🟢 Nit
11 create-react-app FORCE_CHANGE_PASSWORD is not the same as "has not signed in yet" 🟢 Nit
12 create-react-app The app bar reads only the email, not the name 🟢 Nit
13 create-react-app The ref stops a second refresh, not a redirect 🟢 Nit
14 create-react-app The last two outputs under this comment are not API values 🟢 Nit
15 create-react-app The empty list only holds because rotation is on 🟢 Nit
16 create-react-app The account takeover warning sits under "Lost authenticator" 🟢 Nit
17 create-react-app These HTML comments are sent in every email 🟢 Nit
18 create-react-app The suggested domain prefix can fail the prompt's own validation 🟢 Nit
19 create-react-app Generator behavior with no test 🟢 Nit
20 create-react-app Duplicate module augmentation 🟢 Nit
21 create-react-app The props rename is half applied 🟢 Nit
22 create-react-app No loader or pending component, unlike the sibling routes 🟢 Nit
23 create-react-app The role chip stays clickable while a removal is pending 🟢 Nit
24 create-react-app A failed second call reports failure after the first change was saved 🟢 Nit
25 create-react-app The new test/ folder is never type checked 🟢 Nit
26 create-react-app useCurrentUserGroups is exported but only used in this file 🟢 Nit
27 create-react-app A leftover test-synth/ folder is no longer ignored 🟢 Nit
28 create-react-app The commented-out ses line breaks on a title with a quote 🟢 Nit

Adds Cognito login with the user pool in the app's own CDK stack, runtime /config.json, and an optional browser-only user admin UI. The design holds up and matches the API side on issuer, client id, token type and group name. One change made today breaks the CDK type check for two of the three MFA choices when the admin UI is included, and the token renewal path sends users to the login page on a failed refresh that the guard was written to ride out.

src/tasks/features.ts

🟢 Nit: Generator behavior with no test

Nothing asserts that Cognito is only offered with an AWS env, that cognitoSettings is null unless Cognito is chosen (the templates render with strict variables), the MFA prompt, the ignore list in src/tasks/synth.ts:52-74, or the build step after install. A typo in an ignore path stays green in CI.

Pre-existing, not introduced by this pull request, so not a condition for merging:

.github/workflows/release.yml:37

🟢 Nit: The new test step only runs after merge

The workflow triggers on push to main only, so pnpm test does not run on a pull request, and no workflow runs the four test-synth presets. Fix: add a pull_request trigger.

src/test-cli.ts:54

🟢 Nit: The test account id has 9 digits

accountId: "123456789". create-taxum-api#5 fixed the same value to 12 digits. It matters once a preset needs a valid ARN.

Cross-repo checks that came back clean (against create-taxum-api#5)

  • CognitoIssuer, CognitoClientId and CognitoUserPoolArn exist as outputs for both the cognito and cognito-admin feature sets, with the names the API README asks for.
  • The app sends the access token, not the ID token. The ID token only goes to the identity pool.
  • The group name admin is the same in the CDK construct, useIsAdmin.ts and the API README.
  • Every VITE_APP_* read is declared in vite-env.d.ts.liquid and present in .env.liquid for all four presets. The config schema matches CognitoRuntimeConfig.
  • The ignore list globs match the real files, and no rendered file imports an ignored one in any preset.
  • All 18 SDK commands the admin UI uses are in the admin role's action list.

Security sweep, nothing found: no secrets in source, no dangerouslySetInnerHTML, email templates escape the project title, the ListUsers filter is escaped, the identity pool has allowClassicFlow: false, resolveAmbiguousRoles: false, and a trust policy limited to this pool.

Already stated in the description, not repeated as findings: MFA cannot be reset in a required pool, the admin role can set passwords and attributes, authFlows: { userSrp: false }, the favicon attributes, the build after install for the route tree, SES verification, 7 day refresh tokens, localStorage token storage, and the commits shared with #5.

Dimensions

  • D1 AC consistency: no ticket referenced.
  • D2 design fidelity: skipped, no design mock is configured for this workspace.
  • D3 and D3a ran on sibling comparison and first principles, because no rules shelf is configured.
  • Reviewer Would Flag: patterns unavailable, skipped.
  • D5: the skeleton has no test runner on main, so no gap is raised for React components.

No CI checks are reported on this branch.

Comment thread skeleton/cdk/src/cognito-auth.ts.liquid Outdated
scope: scopes.map((scope) => scope.scopeName).join(" "),
{%- if features contains "cognito-admin" %}
identityPoolId: identityPool.identityPoolId,
mfaRequired: mfa === Mfa.REQUIRED,

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocker: CDK type check fails when the admin UI is picked with MFA optional or off

Line 88 renders const mfa: Mfa = Mfa.OFF; (or Mfa.OPTIONAL). TypeScript narrows the const to that one member, so mfa === Mfa.REQUIRED here fails with TS2367, "the types 'Mfa.OFF' and 'Mfa.REQUIRED' have no overlap". Checked with tsc against the real aws-cdk-lib types: Mfa.OFF errors, Mfa.REQUIRED passes.

That breaks pnpm --dir=./cdk tsc --noEmit in ci-check.sh and the CDK build before deploy, for every new project with the admin UI and MFA optional or off.

It went unseen because src/test-cli.ts:72 renders every preset with mfa: "required".

Fix: render the literal, for example mfaRequired: {% if cognitoSettings.mfa == "required" %}true{% else %}false{% endif %},, and add an optional or off preset to test-cli.ts so the other two branches are rendered and type checked.

}
}

if (!accessToken) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Should-fix: A failed renewal redirects to login while the current token is still valid

signinSilent from useAuth() does not throw. react-oidc-context catches the failure, dispatches an error and returns null, so the catch on line 74 never runs. Any failed renewal in the last 60 seconds of a token, including a network blip, falls through to signinRedirect here, and open form state is lost.

That is the opposite of what AuthGuard.tsx.liquid:65-68 promises (a transient failure keeps the page and retries) and of "A failed renewal is retried" in the description.

Fix: when the renewal returns null and current is not expired, send the request with current.access_token. Redirect only when the token has really expired or the error is invalid_grant.

mustSignIn ||
error === undefined ||
!silentSigninFailed ||
error.innerError instanceof ErrorTimeout

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Should-fix: The retry stops for good after a manual renewal times out

oidc-client-ts retries a timed out automatic renewal itself and raises no error for it (_tokenExpiring, retry in 5 seconds). So an ErrorTimeout only reaches this effect from a manual signinSilent(): this 30 second retry, or the one in useAuthenticatedFetch. Nothing retries those.

Sequence: the automatic renewal fails with a network error, the retry 30 seconds later hangs and times out, this effect returns without a timer, and renewal is dead until the tokens expire.

Fix: drop the ErrorTimeout condition, and correct the comment above, which says each failed attempt re-arms the retry.

Comment thread skeleton/README.md.liquid

The CDK stack owns the Cognito user pool, the app client and the managed login domain
(`{{cognitoSettings.domainPrefix}}-<env>.auth.{{awsEnv.region}}.amazoncognito.com`). Users are invited by an
administrator; self sign-up is disabled.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Should-fix: A Cognito project without the admin UI is never told how to create its first user

The README says users are invited by an administrator and self sign-up is disabled. The only instructions for creating a user, "First administrator" at line 102, sit inside the cognito-admin block. A project with Cognito alone deploys an app nobody can sign in to until someone works out aws cognito-idp admin-create-user.

Fix: move the admin-create-user command outside the admin block, and keep only the admin-add-user-to-group step tied to the admin UI.

"cognito-idp:AdminDeleteUserAttributes",
"cognito-idp:AdminUserGlobalSignOut",
"cognito-idp:AdminSetUserMFAPreference",
"cognito-idp:AdminAddUserToGroup",

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Open question: Every admin can join any group, so any future group with an IAM role is open to all admins

The admin role has AdminAddUserToGroup on the whole pool, so an admin can add anyone, themselves included, to any group. Today only admin carries an IAM role, so nothing escalates beyond what the description discloses.

README.md.liquid:74 invites projects to "Add further groups next to it". If one of those groups gets a stronger role, every admin can take it. Should the README or a comment at the group say so?

}
}

if (attributes.length > 0) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Nit: A failed second call reports failure after the first change was saved

If the delete-attributes call fails after the update succeeded, the user sees "Failed to update user" although the email was already changed. With nothing changed, no call is made but the page still says "User has been updated". Fix: skip the mutation when the form is not dirty.

Comment thread package.json
},
"scripts": {
"test-synth": "rm -rf ./test-synth && tsx ./src/test-cli.ts test-synth",
"test": "tsx --test 'test/**/*.test.ts'",

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Nit: The new test/ folder is never type checked

tsconfig.json includes only src/**/* and tsx does not type check. Fix: a tsconfig for tests, or run tsc --noEmit over test.

*/
export const cognitoAdminGroupName = "admin";

export const useCurrentUserGroups = (): string[] => {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Nit: useCurrentUserGroups is exported but only used in this file

Fix: drop the export.

Comment thread .gitignore
/node_modules
/dist
/test-synth
/test-synth-*

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Nit: A leftover test-synth/ folder is no longer ignored

/test-synth became /test-synth-*, so a folder from before this PR shows as untracked. Fix: keep /test-synth ignored too.

cognito: {
domainPrefix: "{{cognitoSettings.domainPrefix}}-staging",
// The address, or its domain via `verifiedDomain`, must be verified in SES first.
// ses: { fromEmail: "no-reply@example.com", fromName: "{{project.title}}" },

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Nit: The commented-out ses line breaks on a title with a quote

fromName: "{{project.title}}" is unescaped inside a string, so uncommenting it in a project whose title has a double quote gives invalid code. The same line is in env-production.ts.liquid:33. Fix: render the title through a JSON filter.

- Render mfaRequired as a literal. Comparing a narrowed const failed the CDK
  type check when the admin UI was picked with MFA optional or off. Two new
  test-synth presets render those modes.
- Keep using a token that has not expired when an early renewal fails,
  instead of sending the user to the login page.
- Retry a renewal that timed out. Nothing else retries a manual renewal.
- Tell every Cognito project how to create its first user, not only those
  with the admin UI.
The apiIdentifier option added a resource server scope that the API never
checked, so it is removed along with the scope setting it needed. The API
already limits tokens to this app by client ID.

The README and the stack now say that administrators can add any user to
any group, so a role on a further group is open to every administrator.
@lavere
lavere marked this pull request as ready for review October 6, 2026 18:32
@lavere
lavere requested review from DASPRiD and lart2150 October 6, 2026 18:32

@DASPRiD DASPRiD left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a solid, carefully built Cognito integration. The security-sensitive parts look right to me: the identity pool only maps the admin group to a role, ambiguous roles are denied, classic flow is off, and the role is scoped to the one user pool. I found nothing that should block the merge. The main gap is the "Optional" MFA choice: no generated project gives users a way to enroll an authenticator. CI also runs only one small unit test, and none of the synth presets that carry almost all of this change. The rest is small cleanup.

Nits:

  • src/tasks/synth.ts:28 Full production build only to regenerate the route tree

    pnpm vite build runs a complete production build of the new project during synth. That costs time, and it leaves dist/ and the visualizer's stats.html behind in the fresh project. With Sentry enabled and SENTRY_AUTH_TOKEN set in the developer's shell, it also turns on the Sentry plugin, before the project is a git repo and with no BITBUCKET_COMMIT.

    Running only the TanStack Router generator (tsr generate), or deleting dist afterward, would keep synth side-effect free.

  • skeleton/src/routes/admin/users_/$username/-components/RolesCard.tsx:54 This catch can't run: signinSilent resolves to null

    react-oidc-context's signinSilent catches errors itself. It dispatches them to the auth state and resolves to null, as the comment in useAuthenticatedFetch.ts.liquid already notes. So this try/catch never catches anything, and the comment describes a path that never runs. A failed refresh shows up as error.source === "signinSilent" in AuthGuard instead. Checking the resolved value (or just awaiting it) would match what actually happens. The same pattern is in edit.tsx at line 81.

  • skeleton/src/routes/admin/users_/$username/edit.tsx:76 Comment says the app bar shows the name; it shows only the email

    UserMenu renders auth.user?.profile.email and nothing else from the token, so "reads name and email" is wrong about the name. The try/catch below it also can't run, because signinSilent resolves to null instead of throwing.

  • skeleton/src/mutations/admin-user.ts:28 Inline option type in invalidateUser

    { refetchDetail?: boolean } is an inline object shape in the signature. A named alias such as InvalidateUserOptions above the function matches the named-type pattern the rest of the file follows (UsernameValues, CreateAdminUserValues, …).

  • src/tasks/features.ts:13 Name the cognitoSettings shape

    FeaturesContext.cognitoSettings inlines its object shape. A named CognitoSettings type would also let featuresTask (FeaturesContext["cognitoSettings"]) and test-cli.ts refer to it directly.

  • src/test-cli.ts:40 Preset shape is written out twice

    { features: Feature[]; mfa?: MfaMode } appears here and in the satisfies clause on line 28. One named Preset type would keep both in sync.

  • skeleton/src/routes/admin/-components/UserStatusChips.tsx:6 Inline value type in statuses record

    The record's value type { label: string; color: ChipProps["color"] } is inline, and the fallback on line 20 repeats that shape. A named StatusChip type would cover both.

  • src/tasks/synth.ts:61 signOut.ts filename isn't dash-case like its sibling

    src/utils/signOut.ts exports a plain function, so by filename convention it should be sign-out.ts. It sits next to the new dash-case src/utils/cognito-error.ts in the same directory. The ignore list entry here and the imports in UserMenu and AuthGuard would need to follow the rename.

Comment thread src/tasks/features.ts
message: "MFA:",
choices: [
{ message: "Required (authenticator app)", name: "required" },
{ message: "Optional (users are not prompted to set it up)", name: "optional" },

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: "Optional" MFA leaves users no way to enroll

With mfa: "optional", nothing in the generated project lets a user set up an authenticator:

  • cognito-auth.ts.liquid says managed login only walks users through setup when MFA is required.
  • The app requests only openid email profile, so the access token lacks aws.cognito.signin.user.admin. Without that scope the user can't call AssociateSoftwareToken/VerifySoftwareToken themselves.
  • There is no MFA setup UI.

So "Optional" behaves exactly like "Off", except the pool reports MFA as optional. It also means UserMFASettingList stays empty and Reset MFA in the admin UI is always disabled. Either drop the choice, or add a self-service enrollment path (with the extra scope) and mention it in the README.

Comment thread package.json
},
"scripts": {
"test-synth": "rm -rf ./test-synth && tsx ./src/test-cli.ts test-synth",
"test": "tsx --test 'test/**/*.test.ts'",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: CI covers only validateDomainPrefix

The new Test step runs test/features.test.ts, and that file only exercises validateDomainPrefix. Most of the change is template output: the Liquid conditionals across main.tsx, AuthGuard, useAuthenticatedFetch, app-stack.ts and cognito-auth.ts, plus the per-feature ignoreList entries such as the admin-*.ts globs. None of that is checked in CI.

The new presets in test-cli.ts would catch a broken template, but CI never runs them. Consider a CI job that synthesizes each preset and runs tsc/biome on it, at least for none, auth0, cognito and cognito-admin. suggestDomainPrefix has no test either.

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.

3 participants