feat: add local signup and Kakao verification gate

This commit is contained in:
2026-07-26 10:17:16 +00:00
parent c364552960
commit a7bb352ba2
41 changed files with 2293 additions and 95 deletions
@@ -0,0 +1,19 @@
import { constants, publicEncrypt } from 'node:crypto';
export interface GatewayPasswordPublicKey {
keyId: string;
algorithm: 'RSA-OAEP-256';
publicKeyPem: string;
}
export const sealGatewayPassword = (password: string, key: GatewayPasswordPublicKey) => ({
keyId: key.keyId,
ciphertext: publicEncrypt(
{
key: key.publicKeyPem,
padding: constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha256',
},
Buffer.from(password, 'utf8')
).toString('base64'),
});
@@ -5,6 +5,7 @@ import { execFile } from 'node:child_process';
import { beforeAll, afterAll, describe, expect, it } from 'vitest';
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import { sealGatewayPassword } from '../src/passwordEnvelope.js';
import type { AppRouter as GatewayAppRouter } from '@sammo-ts/gateway-api';
import { createGatewayApiServer } from '@sammo-ts/gateway-api';
@@ -305,7 +306,7 @@ describe('auction integration flow', () => {
for (const user of demoUsers) {
const login = await gatewayClient.auth.login.mutate({
username: user.username,
password: user.password,
credential: sealGatewayPassword(user.password, await gatewayClient.auth.passwordKey.query()),
});
const gatewayToken = await gatewayClient.auth.issueGameSession.mutate({
sessionToken: login.sessionToken,
@@ -5,6 +5,7 @@ import { execFile } from 'node:child_process';
import { beforeAll, afterAll, describe, expect, it } from 'vitest';
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import { sealGatewayPassword } from '../src/passwordEnvelope.js';
import type { AppRouter as GatewayAppRouter } from '@sammo-ts/gateway-api';
import type { AppRouter as GameAppRouter } from '@sammo-ts/game-api';
@@ -228,7 +229,7 @@ describe('integration initialization flow', () => {
expect(lookup?.username).toBe(user.username);
const login = await gatewayClient.auth.login.mutate({
username: user.username,
password: user.password,
credential: sealGatewayPassword(user.password, await gatewayClient.auth.passwordKey.query()),
});
expect(login.sessionToken).toBeTruthy();
}
@@ -298,7 +299,7 @@ describe('integration initialization flow', () => {
for (const [idx, user] of demoUsers.entries()) {
const login = await gatewayClient.auth.login.mutate({
username: user.username,
password: user.password,
credential: sealGatewayPassword(user.password, await gatewayClient.auth.passwordKey.query()),
});
const gatewayToken = await gatewayClient.auth.issueGameSession.mutate({
sessionToken: login.sessionToken,
@@ -7,6 +7,7 @@ import { execFile } from 'node:child_process';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import { sealGatewayPassword } from '../src/passwordEnvelope.js';
import type { AppRouter as GatewayAppRouter } from '@sammo-ts/gateway-api';
import type { AppRouter as GameAppRouter } from '@sammo-ts/game-api';
@@ -518,7 +519,7 @@ describe('pm2 orchestrator e2e', () => {
const login = await gatewayClient.auth.login.mutate({
username: 'e2e-user',
password: 'e2e-pass-123',
credential: sealGatewayPassword('e2e-pass-123', await gatewayClient.auth.passwordKey.query()),
});
const gameSession = await gatewayClient.auth.issueGameSession.mutate({
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'node:url';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import { sealGatewayPassword } from '../src/passwordEnvelope.js';
import type { AppRouter as GatewayAppRouter } from '@sammo-ts/gateway-api';
import { createGatewayApiServer } from '@sammo-ts/gateway-api';
@@ -223,7 +224,10 @@ describe('actual tournament lifecycle', () => {
for (const [username, displayName] of users) {
const login = await gatewayClient.auth.login.mutate({
username,
password: `${username}-pass`,
credential: sealGatewayPassword(
`${username}-pass`,
await gatewayClient.auth.passwordKey.query()
),
});
const gatewayToken = await gatewayClient.auth.issueGameSession.mutate({
sessionToken: login.sessionToken,