Conversation
There was a problem hiding this comment.
🟡 Changes recommended
There are correctness/compilation issues in the RegisterTenant handler (typing/return contract and username usage), plus operational risk from a new dependency that requires newer Node versions than some existing workflows.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR introduces an administrative “RegisterTenant” Lambda (deployed via CDK) intended to manually register new tenants, generating a temporary password and sending a tenant welcome email using SES with sender/domain configuration stored in SSM Parameter Store.
Changes:
- Add a new CDK-managed RegisterTenant Lambda and wire it into the main stack with required IAM permissions (AppSync, Cognito, SES, SSM).
- Extend the
@platelet-app/lambdapackage with secure password generation and a new SES welcome email helper that reads FromEmail/DomainName from SSM. - Add a new Node-based Lambda project under
cdk/lib/lambda/node/RegisterTenantwith Jest coverage for the handler.
File summaries
| File | Description |
|---|---|
| packages/lambda/src/lambda/sendTenantWelcomeEmail.ts | New SES welcome email helper that includes tenant URL, username, and temporary password. |
| packages/lambda/src/lambda/index.ts | Exports generateSecurePassword and sendTenantWelcomeEmail from the lambda package. |
| packages/lambda/src/lambda/getEmailSSMParams.ts | New helper to fetch FromEmail/DomainName from SSM. |
| packages/lambda/src/lambda/generateSecurePassword.ts | New secure password generator meeting typical Cognito complexity requirements. |
| packages/lambda/src/lambda/generateSecurePassword.test.ts | Unit tests validating password length, character classes, and allowed alphabet. |
| packages/lambda/package.json | Bumps package version and adds @aws-sdk/client-ssm dependency. |
| package-lock.json | Lockfile updates for the new SSM client and related dependency graph changes. |
| cdk/lib/ssm-params-construct.ts | Exposes domainNameArn for granting SSM read access to the new function. |
| cdk/lib/register-tenant-function-construct.ts | New construct defining the RegisterTenant Lambda, env vars, and IAM permissions. |
| cdk/lib/platelet-cdk-stack.ts | Instantiates the RegisterTenant construct and imports the existing AppSync API attributes. |
| cdk/lib/lambda/node/RegisterTenant/tsconfig.json | TypeScript config for the new RegisterTenant Lambda project. |
| cdk/lib/lambda/node/RegisterTenant/src/interfaces.ts | Defines the RegisterTenant Lambda event shape. |
| cdk/lib/lambda/node/RegisterTenant/src/index.ts | Implements tenant/user creation via AppSync, Cognito provisioning, role assignment, and welcome email. |
| cdk/lib/lambda/node/RegisterTenant/src/index.test.ts | Jest tests for success path and cleanup behavior on failures. |
| cdk/lib/lambda/node/RegisterTenant/setupTests.ts | Test-time env var setup for the RegisterTenant Lambda tests. |
| cdk/lib/lambda/node/RegisterTenant/package.json | New Lambda subproject dependencies/scripts for build/package/test. |
| cdk/lib/lambda/node/RegisterTenant/jest.config.js | Jest config for ESM + ts-jest in the RegisterTenant subproject. |
| cdk/lib/lambda/node/RegisterTenant/babel.config.cjs | Babel config for TypeScript preset support in tests/tooling. |
| cdk/lib/lambda/node/package.json | Adds build/package scripts for the new RegisterTenant Lambda subproject. |
| cdk/lib/cypress-test-role-construct.ts | Renames the IAM Role construct ID for Cypress test role creation. |
Review details
Suppressed comments (1)
cdk/lib/lambda/node/RegisterTenant/src/index.ts:295
- This block doesn’t type newUser/newTenant/cognitoUser (strict tsconfig) and also sets Cognito groups using the pre-create username rather than the persisted username returned from createUser. This can both fail compilation (implicit any) and assign groups to the wrong Cognito user if the stored username differs.
let newUser, newTenant, cognitoUser;
try {
newUser = await createNewAdminUser(user);
newTenant = await addTenant({
...tenant,
- Files reviewed: 19/21 changed files
- Comments generated: 7
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| export const handler = async ( | ||
| event: LambdaEvent | ||
| ): Promise<CreateTenantMutation> => { |
| "@aws-crypto/sha256-js": "^1.0.0-alpha.0", | ||
| "@aws-sdk/client-s3": "^3.954.0", | ||
| "@aws-sdk/client-ses": "^3.946.0", | ||
| "@aws-sdk/client-ssm": "^3.1106.0", | ||
| "@aws-sdk/credential-provider-node": "^3.6.1", |
| <p> | ||
| <b>Username:</b> ${emailAddress} | ||
| </p> | ||
| <p> | ||
| <b>Password:</b> ${password} | ||
| </p> | ||
| <p> | ||
| <b>This temporary password will expire in one week.</b> | ||
| </p> |
| const cleanUp = async ( | ||
| user: User, | ||
| tenant: Tenant, | ||
| cognitoUser?: { username: string } | ||
| ) => { | ||
| console.log("Cleaning up user and tenant"); | ||
| if (cognitoUser) { | ||
| console.log("Deleting cognito user:", cognitoUser.username); | ||
| const params = { | ||
| UserPoolId: USER_POOL_ID, | ||
| Username: user.username, | ||
| }; |
| if (!GRAPHQL_ENDPOINT) { | ||
| throw new Error("Missing env variables"); | ||
| } |
|
Preview deployment is ready: https://pr-282.platelet-soft.com (deploy logs) |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Refactor to retrieve ENV variable once and validate it. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This reverts commit 451e851.
Adds a register tenant lambda function to the supporting CDK. This function can be run manually from the AWS console to register a new tenant.
Should eventually replace the registerTenant mutation.