tests/
├── application/
│ └── use-cases/
│ ├── register-organization.test.ts
│ └── login.test.ts
├── infra/
│ └── auth/
│ ├── argon2-password-hasher.test.ts
│ └── jose-access-token-service.test.ts
├── delivery/
│ └── graphql/
│ ├── auth.test.ts
│ └── context.test.ts
└── database/
├── prisma-organization-registration-store.test.ts
└── prisma-user-repo.test.ts
register mutation
↓
argon2.hash(password)
↓
store passwordHash on User
login mutation
↓
argon2.verify(user.passwordHash, password)
↓
new SignJWT({ sub: user.id})
↓
return access token
every GraphQL request
↓
read Authorization: Bearer <token>
↓
jose.jwtVerify(...)
↓
put authenticated user/claims in GraphQL context
↓
resolvers/use-cases check context.actor
tests/application/use-cases/register-organization.test.ts
describe("RegisterOrganization", () => {
it("registers an organization with its initial user");
it("normalizes the organization and user email addresses");
it("hashes the raw password before persisting the user");
it("does not call the registration store when password hashing fails");
it("returns the created organization and user IDs");
});tests/database/prisma-organization-registration-store.test.ts
describe("PrismaOrganizationRegistrationStore", () => {
it("persists the organization and its linked initial user");
it("rolls back the organization when initial user creation fails");
it("translates a duplicate email constraint into a controlled error");
});tests/delivery/graphql/auth.test.ts
describe("registerOrganization", () => {
it("registers without an actor and returns the organization and user IDs");
it("returns a controlled error for a duplicate email");
it("rejects invalid registration input");
});tests/application/use-cases/login.test.ts
describe("Login", () => {
it("returns an access token for valid credentials");
it("normalizes the email before looking up the user");
it("rejects an unknown email with invalid credentials");
it("rejects a wrong password with invalid credentials");
});tests/infra/auth/argon2-password-hasher.test.ts
describe("Argon2PasswordHasher", () => {
it("hashes a password without retaining the plaintext");
it("verifies the correct password");
it("rejects an incorrect password");
});tests/infra/auth/jose-access-token-service.test.ts
describe("JoseAccessTokenService", () => {
it("creates and verifies a token containing the user ID");
it("rejects an expired token");
it("rejects a token signed with another secret");
it("rejects a token with an invalid issuer");
it("rejects a token with an invalid audience");
});tests/delivery/graphql/auth.test.ts
describe("login", () => {
it("returns an access token for valid credentials");
it("returns a controlled error for invalid credentials");
it("rejects invalid login input");
});tests/database/prisma-user-repo.test.ts
describe("PrismaUserRepository", () => {
it("finds and maps a user by email");
it("returns undefined when no user has the email");
it("finds and maps a user by ID");
it("returns undefined when no user has the ID");
});tests/delivery/graphql/context.test.ts
describe("GraphQL context", () => {
it("creates a context without an actor when no token is provided");
it("rejects a malformed authorization header");
it("rejects an invalid token");
it("rejects a valid token when the user no longer exists");
it("creates an authenticated actor from a valid token and existing user");
it("returns a controlled GraphQL error for an invalid token");
});