Skip to content

Feature/projeto web - #9

Merged
argentinaluiz merged 55 commits into
mainfrom
feature/projeto-web
Oct 9, 2026
Merged

argentinaluiz merged 55 commits into
mainfrom
feature/projeto-web

Conversation

@argentinaluiz

Copy link
Copy Markdown
Contributor

No description provided.

argentinaluiz and others added 30 commits October 8, 2026 13:23
Add section 6 to the HLD covering local, CI, staging and production
environments, and the delivery flow. Renumber decisions to section 7
and record the new decisions, risk and open questions.

Update the LLD so deadlines and token lifetimes are read from
environment variables, and list the new variables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep the repository root free for the monorepo that will be created,
with the brief, HLD and LLD grouped in one place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Give future agent sessions the document hierarchy, the planned
architecture and the working rules (Docker networking, definition of
done, Git conventions, scope limits and library documentation lookup).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use the agent-neutral file name so the same guidance serves tools
other than Claude Code, and trim it to the current working rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scaffold apps/web with create-next-app, following the structure in the
LLD. Development and production use separate Dockerfiles: the dev
container only stays up so commands run through docker compose exec,
while the production image runs the standalone server for Cloud Run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Share the chrome-devtools and playwright servers so everyone working on
the repo gets the same browser tooling without approving them by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Installing inside the dev container created a .pnpm-store folder in
apps/web, because pnpm places the store next to the bind-mounted code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Document how to start and stop the project and how to run commands in
the container, so nobody runs pnpm or node directly on the host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scaffold apps/api with the Nest CLI, following the structure in the LLD,
with separate development and production Dockerfiles like the web app.
The dev image includes procps because Nest's watch mode needs ps to stop
the previous process on each reload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the node_modules volumes so dependencies land in the project folder,
where the editor can read them, and are installed when the container
starts instead of by hand. Also add the api service to the dev compose.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Record the decisions from the planning session so the Linear tickets
have a single source of truth: the LLD now covers users and sessions,
the glossary fixes the terms Usuário and Sessão, and AGENTS.md
describes how specs and tickets are managed in Linear.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AGENTS.md now sends specs and tickets to Linear, so the server has to
be available to anyone working in the repository.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The LLD and the API AGENTS.md were describing the same rules in two
places and had to change together. Each piece of information now has a
single owner: what the system does lives in docs/, how the code is
written lives in the AGENTS.md of each project, and the root AGENTS.md
records that rule.

- apps/api/AGENTS.md: commands, layers, what the service layer may
  import, domain errors translated by an exception filter, Nest file
  naming, test levels by suffix, and the config module.
- apps/web/AGENTS.md: Server Components first, data access, and the
  cache trade-offs under Cache Components.
- docs/lld.md: keeps the folder tree and the library choices, and
  gains the config module and the PORT variable.
- docs/plans/01-auth.md: removed. The plan lives in Linear (LUI-133).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Versions the skills used to plan features (grilling, domain modeling,
research, spec and tickets), installed from mattpocock/skills, together
with the lock file that pins their hashes, so every clone plans with
the same workflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The authentication screens were drawn in Figma (LUI-134) and needed a
success banner, a narrow banner layout and extra auth-card content that
the design system did not describe yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The components in Figma gained hover, focus and disabled variants, and
the design system did not say how a filled control looks when disabled
or how the focus outline is represented.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hover and disabled controls were unreadable on the Figma page background
and the disabled button vanished in the dark theme. A dedicated
fill-disabled token replaces surface, the field hover now changes the
border, and the file pages and their showcase rules are documented.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pointer was lost when the placeholder line was removed, so the
design system no longer said where the Figma file lives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nticacao-no-figma

docs: authentication screens in Figma (LUI-134)
The auth slices need a database and an inbox from the first run. The api container now prepares its own .env, RS256 keys and migrations on start, so a fresh clone needs no manual step, and healthchecks let 'up --wait' block until that is done.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
Every auth slice relies on these: routes under /v1, one filter that shapes all errors with a stable code, env vars validated at boot, an e-mail interface with an SMTP driver, and e2e/integration suites that run against a real test database and Mailpit. The example controller is gone, so the unit suite must pass empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…body

Keeps each fact in its owner: environment in the root guide, code practices and commands in the API guide, error contract, env vars and the Prisma 7 pin in the LLD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
A third-party SDK error carrying statusCode 404 was answered as a client error and never logged. The filter now takes the status only from HttpException and body-parser errors, keeps deliberate 5xx statuses instead of flattening them to 500, and drops the connection when the response has already started.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
Subject configs re-read raw process.env, so conversion and defaults lived outside the schema and a value changed after boot skipped validation. The PEM regex also accepted unparsable keys and refused valid PKCS#1 ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
nodemailer defaults keep a send hanging for minutes on a stuck server, so the timeouts are now explicit and configurable. The Mailpit helper returned as soon as any message existed, which would hand a resend test the first e-mail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
pg_isready over the unix socket also passes on the temporary init server, letting the api start migrating too early. The production image cannot apply migrations; that is out of scope here, so the open decision is written down in the HLD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
argentinaluiz and others added 25 commits October 9, 2026 02:59
…ne place

The three Vitest configs, the env stub cleanup and the problem+json
assertions were copied across files, and the env schema ran through two
separate mechanisms. Each now has a single owner, so the next feature
copies one pattern instead of four.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
With the pg adapter, $connect() opens no connection, so the API booted
against a dead database and only failed on the first request. The env
setup script also replaced a key the developer had put in .env when the
other half of the pair was missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
The test database URL is now derived once per run and handed to the test
files, so a development database whose name already ends in _test can no
longer be truncated. The env is validated once per set of values, SMTP
connections are pooled, tests read mail from the server SMTP_URL points
to, and the scaffold leftovers are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…ecks

A database that accepts the connection and never answers held the boot
forever, because pg waits without a limit by default. The env schema now
also refuses a JWT public key that is not the pair of the private one
and a MAIL_FROM without an address, which used to fail only at runtime.

The test base hands the Mailpit address to the test files once, so a
test that swaps SMTP_URL keeps reading from the right server, and a test
app that fails to boot is closed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…he SMTP idle wait

A HttpException carrying a 2xx/3xx status went out as a problem document
with a success status. The SMTP socket timeout doubled as the pool's
idle limit, so pooled connections were dropped before being reused; the
inactivity wait now has its own, longer setting.

Also documents how to repair the environment when the API container
exits during setup, and the Prisma CLI config as the second place that
reads the environment directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
The filter took any thrown object with expose, a string type and a 4xx
statusCode as an Express body-reader error, so a third-party error with
that shape leaked its status instead of becoming a 500.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…ente-banco-email-erros

feat: foundation for auth — environment, database, e-mail and error format (LUI-135)
…rowser tests (LUI-136)

The auth screens of feature 01 need a shared base before the first slice
(LUI-137): the design-system tokens in Tailwind, the primitives and the auth
card from the approved Figma screens, a server-only API client that returns
errors typed by `code`, and a Playwright service in the dev Compose.

The default Tailwind colour, text, radius and shadow scales are wiped so only
token classes generate CSS. A dev-only showcase under /vitrine gives the
components somewhere to be validated and tested until the screens exist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…and give Chromium shared memory

Review findings on the web base: a caller could override the `aria-busy`
derived from `loading`, a disabled text link still looked and hovered like an
enabled one, and Chromium ran on Docker's 64 MB /dev/shm with a parallel suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…omponentes-auth

feat: web base for auth — design tokens, components, API client and browser tests (LUI-136)
…eens (LUI-137)

A visitor can now create a User with e-mail and password, receive the
verification link, open it and land on the sign-in screen with the success
notice, or ask for another link when the first one is lost, expired or used.

Sign-up never reveals whether an e-mail already has a User: the answer is
always 201 and only the e-mail sent differs. While an e-mail is unverified the
last sign-up wins (password and terms acceptance), decided by a conditional
update so a verification that lands in between is not overwritten. A
verification token is unique per User and type, so concurrent resends cannot
leave two valid links.

The users module owns the users table and the auth module reaches it only
through its public service. WEB_ORIGIN and EMAIL_VERIFICATION_TTL_SECONDS are
new, and the setup script now adds to an existing .env whatever .env.example
gained, so the API keeps booting on machines that already have one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…en verification fails

Review findings on sign-up and verification. The "confira seu e-mail" screen
received the address in the query string, which left it in browser history and
access logs and let anyone craft a link with arbitrary text on the screen. The
address now travels in a one-hour HttpOnly cookie scoped to that screen, and
the resend reads it from there instead of from a form field.

Verification spent the token and then marked the User in a second statement;
a failure in between left the link dead with the User still unverified. The
token is now released when marking fails, so the same link works again.

The local web container sets COOKIE_SECURE=false, because it runs over HTTP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…rificacao

feat: sign-up and e-mail verification, from the API routes to the screens (LUI-137)
A verified User can now sign in with e-mail and password, land on a
provisional page that shows their e-mail and sign out. Opening a protected
page without a Session leads to the sign-in screen and back to the requested
page after login; opening an auth screen with a Session leads to the product.

Login opens a Session: an RS256 access token and an opaque refresh token
stored only as a hash, grouped by a session id. A wrong password and an
unknown e-mail get the same answer, and the password is checked even without a
User so the response time does not tell them apart. Logout deletes the
Session's tokens and answers 204 whatever the token is. GET /me belongs to the
users module, behind a guard that checks only the signature.

On the web the tokens live in HttpOnly cookies. The Proxy is an optimistic
filter that reads the token expiry without checking the signature, and every
route outside its two lists is protected. The data access layer asks the API on
each protected page; a Session the API refuses is cleared by a route that
checks it again first, because rendering a page cannot delete cookies. The
return destination accepts internal paths only.

Session renewal is not here yet, so an expired access token leads to the
sign-in screen. ACCESS_TOKEN_TTL_SECONDS and REFRESH_TOKEN_TTL_SECONDS are new.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
… of any size

Review findings on the session routes: the guard compared the scheme
case-sensitively, although RFC 7235 makes it case-insensitive, and accepted a
header with anything after the token. The logout route refused a token longer
than 512 characters with validation_error, while the contract says 204 even
for an invalid token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
feat: sign-in and sign-out, from the API routes to the screens (LUI-138)
…xy (LUI-139)

A User now stays signed in after the 15-minute access token expires, without
noticing, for as long as the Session is in use. Several tabs can renew at the
same time. When the Session is really over, the sign-in screen says so.

POST /auth/refresh trades the refresh token for a new pair in the same
Session and marks the old token as rotated. A rotated token is still accepted
for REFRESH_TOKEN_REUSE_GRACE_SECONDS (10 by default), so parallel requests
do not knock each other out; each use opens another branch of the Session.
After the window, reuse means possible theft and ends every Session of the
User, even if the rotated token has already expired. Rotation, logout and
that mass revocation queue up per User in the database, so a refresh that
races a logout cannot leave a new token in a Session that was just deleted.

On the web the Proxy renews before the route renders and passes the new
tokens along in the request. If the API refuses the refresh token, it clears
the cookies and leads to the sign-in screen with "Sua sessão expirou"; if the
API fails, the Session is kept. A Server Action is never redirected by the
Proxy, because the browser would replay it on the sign-in screen and show an
error. That is what lets sign-out work with an expired access token, which
used to leave the Session alive on the server. /sessao-encerrada also tries
to renew before it clears anything.

The two logout tests left as todo in LUI-138 are now real: the refresh route
makes the end of a Session observable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…reuse

Review findings on the refresh route. Reuse was detected in one transaction
and the Sessions were deleted in another, so a refresh on another branch of
the User could take the lock in between and still get a new pair. The
rotation now deletes the User's tokens itself, under the same lock.

The grace window is closed at its end: a token rotated exactly at the limit
is refused, so a window of zero really turns the tolerance off.

A new test fires refresh and logout together, through the routes, and checks
that no token of the Session renews afterwards. It fails without the lock.

apps/api/AGENTS.md said the service owns transactions, while only
repositories have the database client. The rule now says the repository
guarantees the atomicity of each command and returns a typed outcome.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…-renova

feat: a Session that renews itself, from the refresh route to the Proxy (LUI-139)
A User who forgot the password asks for a link by e-mail, sets a new
password and lands on the sign-in screen with the "Senha redefinida" notice.
Neither the answer nor the screens say whether the e-mail has a User.

POST /auth/forgot-password always answers 204 and only sends the link when
the e-mail has a User, verified or not. The token lasts
PASSWORD_RESET_TTL_SECONDS (1 hour by default), is stored as a hash and is
replaced by the next request. POST /auth/reset-password spends it, ends every
Session of the User, changes the password, marks the e-mail as verified and
sends "Sua senha foi alterada". It opens no Session.

The Sessions end before the password changes: if the change then fails, the
person only has to sign in again and the link is given back, instead of a
new password living next to the old Sessions. The token is checked before
the Argon2 hash runs, so a made-up token does not cost one. "Spend the token
and give it back if what it authorises fails" now lives in
EmailTokensService.redeem(), shared with e-mail verification.

On the web, /esqueci-minha-senha and /redefinir-senha open with or without a
Session, because the links in the e-mails and the invalid-link screen lead
there. Only the API knows whether a token is valid, so an invalid link is
found when the new password is sent. The reset form is rendered only after
the token is read from the URL: as a hidden field streamed in later, it was
left out of a fast submit and sent a good link to the invalid-link screen.
After the reset the web clears the token cookies of the browser, so the
sign-in screen opens instead of the Proxy leading back to the product.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
Review finding on the forgot-password route: an e-mail without a User
returned at once, while an e-mail with one still wrote the token before
answering, so the response time told the two apart despite the same 204.

The route now answers right after looking the User up, which costs the same
in both cases. The token and the e-mail follow without being awaited. A
failure to write the token goes to the log, as a failure to send already
did, and the person asks for another link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…e-senha

feat: password recovery, from the reset routes to the screens (LUI-140)
…IP (LUI-141)

Login, registration, verification resend and "forgot password" now count
attempts per e-mail and per IP in PostgreSQL and answer rate_limited until
the window closes, so guessing a password or flooding a mailbox stops
being free. The web forwards the browser's IP with a shared secret, so
one abuser does not lock everyone out behind the web server's address.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgE8sJLFxENgwV47XrwDGP
…tativas-e-ip-real

feat: attempt limits on the auth routes, keyed by the browser's real IP (LUI-141)
Copilot AI lite review requested due to automatic review settings October 9, 2026 10:42
@argentinaluiz
argentinaluiz merged commit e9cbf88 into main Oct 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

One or more issues must be addressed before approval.

7 open findings
What changed in this PR

Adds the initial web application, authentication flows, session handling, API authentication infrastructure, database schema, testing setup, and project skills.

Changes:

  • Adds Next.js authentication UI, Server Actions, session cookies, proxy renewal, and Playwright tests.
  • Adds NestJS users/auth modules, tokens, rate limiting, mail delivery, configuration, Prisma schema, and tests.
  • Adds glossary, Docker setup, and agent skill documentation.
File Description
GLOSSARY.md Updated as part of this pull request.
apps/​web/​tsconfig.json Updated as part of this pull request.
apps/​web/​README.md Updated as part of this pull request.
apps/​web/​public/​.gitkeep Updated as part of this pull request.
apps/​web/​pnpm-workspace.yaml Updated as part of this pull request.
apps/​web/​playwright.config.ts Updated as part of this pull request.
apps/​web/​package.json Updated as part of this pull request.
apps/​web/​next.config.ts Updated as part of this pull request.
apps/​web/​lib/​session/​tokens.ts Updated as part of this pull request.
apps/​web/​lib/​session/​token-cookies.ts Updated as part of this pull request.
apps/​web/​lib/​session/​return-path.ts Updated as part of this pull request.
apps/​web/​lib/​session/​renewal.ts Updated as part of this pull request.
apps/​web/​lib/​session/​paths.ts Updated as part of this pull request.
apps/​web/​lib/​session/​login-path.ts Updated as part of this pull request.
apps/​web/​lib/​session/​cookie-options.ts Updated as part of this pull request.
apps/​web/​lib/​session/​access-token.ts Updated as part of this pull request.
apps/​web/​lib/​dal/​user.ts Updated as part of this pull request.
apps/​web/​lib/​api/​users.ts Updated as part of this pull request.
apps/​web/​lib/​api/​types.ts Updated as part of this pull request.
apps/​web/​lib/​api/​link-errors.ts Updated as part of this pull request.
apps/​web/​lib/​api/​error-messages.ts Updated as part of this pull request.
apps/​web/​lib/​api/​endpoint.ts Updated as part of this pull request.
apps/​web/​lib/​api/​client-ip.ts Updated as part of this pull request.
apps/​web/​lib/​api/​auth.ts Updated as part of this pull request.
apps/​web/​eslint.config.mjs Updated as part of this pull request.
apps/​web/​e2e/​support/​mailpit.ts Updated as part of this pull request.
apps/​web/​e2e/​support/​env.ts Updated as part of this pull request.
apps/​web/​e2e/​support/​account.ts Updated as part of this pull request.
apps/​web/​e2e/​smoke.spec.ts Updated as part of this pull request.
apps/​web/​e2e/​mailpit.spec.ts Updated as part of this pull request.
apps/​web/​e2e/​components.spec.ts Updated as part of this pull request.
apps/​web/​e2e/​api-client.spec.ts Updated as part of this pull request.
apps/​web/​Dockerfile.dev Updated as part of this pull request.
apps/​web/​Dockerfile Updated as part of this pull request.
apps/​web/​components/​ui/​text-link.tsx Updated as part of this pull request.
apps/​web/​components/​ui/​text-field.tsx Updated as part of this pull request.
apps/​web/​components/​ui/​password-field.tsx Updated as part of this pull request.
apps/​web/​components/​ui/​button-primary.tsx Updated as part of this pull request.
apps/​web/​components/​ui/​button-icon.tsx Updated as part of this pull request.
apps/​web/​components/​ui/​banner.tsx Updated as part of this pull request.
apps/​web/​components/​auth/​auth-card.tsx Updated as part of this pull request.
apps/​web/​app/​vitrine/​layout.tsx Updated as part of this pull request.
apps/​web/​app/​vitrine/​auth-card/​page.tsx Updated as part of this pull request.
apps/​web/​app/​vitrine/​api/​page.tsx Updated as part of this pull request.
apps/​web/​app/​termos/​page.tsx Updated as part of this pull request.
apps/​web/​app/​sessao-encerrada/​route.ts Updated as part of this pull request.
apps/​web/​app/​privacidade/​page.tsx Updated as part of this pull request.
apps/​web/​app/​layout.tsx Updated as part of this pull request.
apps/​web/​app/​(drive)/​page.tsx Updated as part of this pull request.
apps/​web/​app/​(drive)/​actions.ts Updated as part of this pull request.
apps/​web/​app/​(auth)/​verificar-email/​route.ts Updated as part of this pull request.
apps/​web/​app/​(auth)/​verificar-email/​link-invalido/​page.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​request-link-form.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​redefinir-senha/​reset-password-form.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​redefinir-senha/​page.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​redefinir-senha/​link-invalido/​page.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​pending-email.ts Updated as part of this pull request.
apps/​web/​app/​(auth)/​paths.ts Updated as part of this pull request.
apps/​web/​app/​(auth)/​form-state.ts Updated as part of this pull request.
apps/​web/​app/​(auth)/​esqueci-minha-senha/​page.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​esqueci-minha-senha/​enviado/​page.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​entrar/​page.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​entrar/​login-form.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​email-field.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​criar-conta/​register-form.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​criar-conta/​page.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​confira-seu-email/​resend-verification.tsx Updated as part of this pull request.
apps/​web/​app/​(auth)/​confira-seu-email/​page.tsx Updated as part of this pull request.
apps/​web/​.gitignore Updated as part of this pull request.
apps/​web/​.dockerignore Updated as part of this pull request.
apps/​api/​vitest.shared.ts Updated as part of this pull request.
apps/​api/​vitest.config.ts Updated as part of this pull request.
apps/​api/​vitest.config.int.ts Updated as part of this pull request.
apps/​api/​vitest.config.e2e.ts Updated as part of this pull request.
apps/​api/​tsconfig.json Updated as part of this pull request.
apps/​api/​tsconfig.build.json Updated as part of this pull request.
apps/​api/​test/​support/​test-env.ts Updated as part of this pull request.
apps/​api/​test/​support/​setup.ts Updated as part of this pull request.
apps/​api/​test/​support/​problem.ts Updated as part of this pull request.
apps/​api/​test/​support/​global-setup.ts Updated as part of this pull request.
apps/​api/​test/​support/​database.ts Updated as part of this pull request.
apps/​api/​test/​support/​create-test-app.ts Updated as part of this pull request.
apps/​api/​src/​modules/​users/​users.service.ts Updated as part of this pull request.
apps/​api/​src/​modules/​users/​users.module.ts Updated as part of this pull request.
apps/​api/​src/​modules/​users/​users.controller.ts Updated as part of this pull request.
apps/​api/​src/​modules/​users/​entities/​user.entity.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​registration.service.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​password.service.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​password-recovery.service.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​opaque-token.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​format-duration.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​format-duration.spec.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​errors/​invalid-token.error.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​errors/​invalid-credentials.error.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​errors/​email-not-verified.error.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​email-tokens.service.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​email-tokens.repository.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​email-token-type.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​verify-email.dto.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​reset-password.dto.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​resend-verification.dto.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​register.dto.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​refresh.dto.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​new-password.decorator.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​logout.dto.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​login.dto.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​forgot-password.dto.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​email.decorator.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​dto/​email-link-token.decorator.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​auth.module.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​auth.controller.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​auth-mailer.service.ts Updated as part of this pull request.
apps/​api/​src/​modules/​auth/​auth-attempts.service.ts Updated as part of this pull request.
apps/​api/​src/​main.ts Updated as part of this pull request.
apps/​api/​src/​infra/​mail/​smtp-mail-sender.ts Updated as part of this pull request.
apps/​api/​src/​infra/​mail/​mail.module.ts Updated as part of this pull request.
apps/​api/​src/​infra/​mail/​mail-sender.ts Updated as part of this pull request.
apps/​api/​src/​infra/​database/​prisma.service.ts Updated as part of this pull request.
apps/​api/​src/​infra/​database/​database.module.ts Updated as part of this pull request.
apps/​api/​src/​config/​rate-limit.config.ts Updated as part of this pull request.
apps/​api/​src/​config/​mail.config.ts Updated as part of this pull request.
apps/​api/​src/​config/​env.ts Updated as part of this pull request.
apps/​api/​src/​config/​database.config.ts Updated as part of this pull request.
apps/​api/​src/​config/​config.module.ts Updated as part of this pull request.
apps/​api/​src/​config/​auth.config.ts Updated as part of this pull request.
apps/​api/​src/​config/​app.config.ts Updated as part of this pull request.
apps/​api/​src/​common/​validation/​input-validation.pipe.ts Updated as part of this pull request.
apps/​api/​src/​common/​rate-limit/​rate-limited.error.ts Updated as part of this pull request.
apps/​api/​src/​common/​rate-limit/​rate-limit.service.ts Updated as part of this pull request.
apps/​api/​src/​common/​rate-limit/​rate-limit.repository.ts Updated as part of this pull request.
apps/​api/​src/​common/​rate-limit/​rate-limit.module.ts Updated as part of this pull request.
apps/​api/​src/​common/​errors/​input-validation.error.ts Updated as part of this pull request.
apps/​api/​src/​common/​errors/​error-code.ts Updated as part of this pull request.
apps/​api/​src/​common/​errors/​domain-error.ts Updated as part of this pull request.
apps/​api/​src/​common/​client-ip/​client-ip.guard.ts Updated as part of this pull request.
apps/​api/​src/​common/​client-ip/​client-ip.guard.spec.ts Updated as part of this pull request.
apps/​api/​src/​common/​client-ip/​client-ip.decorator.ts Updated as part of this pull request.
apps/​api/​src/​common/​client-ip/​canonical-ip.ts Updated as part of this pull request.
apps/​api/​src/​common/​client-ip/​canonical-ip.spec.ts Updated as part of this pull request.
apps/​api/​src/​common/​auth/​unauthenticated.error.ts Updated as part of this pull request.
apps/​api/​src/​common/​auth/​current-user-id.decorator.ts Updated as part of this pull request.
apps/​api/​src/​common/​auth/​auth.guard.ts Updated as part of this pull request.
apps/​api/​src/​common/​auth/​access-tokens.service.ts Updated as part of this pull request.
apps/​api/​src/​common/​auth/​access-tokens.module.ts Updated as part of this pull request.
apps/​api/​src/​app.setup.ts Updated as part of this pull request.
apps/​api/​src/​app.module.ts Updated as part of this pull request.
apps/​api/​scripts/​setup-env.mjs Updated as part of this pull request.
apps/​api/​README.md Updated as part of this pull request.
apps/​api/​prisma/​schema.prisma Updated as part of this pull request.
apps/​api/​prisma/​migrations/​migration_lock.toml Updated as part of this pull request.
apps/​api/​prisma/​migrations/​20261009100010_rate_limits/​migration.sql Updated as part of this pull request.
apps/​api/​prisma/​migrations/​20261009081006_refresh_tokens/​migration.sql Updated as part of this pull request.
apps/​api/​prisma/​migrations/​20261009075226_users_and_email_tokens/​migration.sql Updated as part of this pull request.
apps/​api/​prisma/​migrations/​20261009000000_enable_extensions/​migration.sql Updated as part of this pull request.
apps/​api/​prisma.config.ts Updated as part of this pull request.
apps/​api/​pnpm-workspace.yaml Updated as part of this pull request.
apps/​api/​package.json Updated as part of this pull request.
apps/​api/​nest-cli.json Updated as part of this pull request.
apps/​api/​Dockerfile.dev Updated as part of this pull request.
apps/​api/​Dockerfile Updated as part of this pull request.
apps/​api/​.prettierrc Updated as part of this pull request.
apps/​api/​.prettierignore Updated as part of this pull request.
apps/​api/​.oxlintrc.json Updated as part of this pull request.
apps/​api/​.gitignore Updated as part of this pull request.
apps/​api/​.env.example Updated as part of this pull request.
apps/​api/​.dockerignore Updated as part of this pull request.
.mcp.json Updated as part of this pull request.
.claude/​skills/​to-tickets/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​to-spec/​SKILL.md Updated as part of this pull request.
.claude/​skills/​to-spec/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​tdd/​tests.md Updated as part of this pull request.
.claude/​skills/​tdd/​SKILL.md Updated as part of this pull request.
.claude/​skills/​tdd/​mocking.md Updated as part of this pull request.
.claude/​skills/​tdd/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​research/​SKILL.md Updated as part of this pull request.
.claude/​skills/​research/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​implement/​SKILL.md Updated as part of this pull request.
.claude/​skills/​implement/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​implement-spec/​SKILL.md Updated as part of this pull request.
.claude/​skills/​implement-spec/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​handoff/​SKILL.md Updated as part of this pull request.
.claude/​skills/​handoff/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​grilling/​SKILL.md Updated as part of this pull request.
.claude/​skills/​grilling/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​grill-with-docs/​SKILL.md Updated as part of this pull request.
.claude/​skills/​grill-with-docs/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​grill-me/​SKILL.md Updated as part of this pull request.
.claude/​skills/​grill-me/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​domain-modeling/​SKILL.md Updated as part of this pull request.
.claude/​skills/​domain-modeling/​GLOSSARY-FORMAT.md Updated as part of this pull request.
.claude/​skills/​domain-modeling/​agents/​openai.yaml Updated as part of this pull request.
.claude/​skills/​domain-modeling/​ADR-FORMAT.md Updated as part of this pull request.
.claude/​skills/​codebase-design/​DESIGN-IT-TWICE.md Updated as part of this pull request.
.claude/​skills/​codebase-design/​DEEPENING.md Updated as part of this pull request.
.claude/​skills/​codebase-design/​agents/​openai.yaml Updated as part of this pull request.
.claude/​settings.json Updated as part of this pull request.

🧠 Review effort: Lite


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/api/src/app.setup.ts
Comment on lines +1 to +13
import { INestApplication } from '@nestjs/common';

/** Prefixo e versão de todas as rotas (seção 3.1 do docs/lld.md). */
export const API_PREFIX = 'v1';

/**
* Configuração da aplicação HTTP que vale tanto para o `main.ts` quanto para a
* base de testes. O que depende de injeção (filtro de erros, validação de
* entrada) é registrado no `AppModule`.
*/
export function configureApp(app: INestApplication): void {
app.setGlobalPrefix(API_PREFIX);
}
* constructor(@Inject(mailConfig.KEY) config: ConfigType<typeof mailConfig>)
*/
export class AppConfigModule {
static forRoot(options: AppConfigModuleOptions = {}): Promise<DynamicModule> {
import { SessionsService, type TokenPair } from './sessions.service.js';

@Controller('auth')
@UseGuards(ClientIpGuard)
Comment on lines +51 to +55
if (unverified) {
await this.sendVerification(user);
} else {
this.mailer.sendAlreadyRegistered(user.email);
}
Comment on lines +15 to +18
execFileSync('node_modules/.bin/prisma', ['migrate', 'deploy'], {
env: { ...process.env, DATABASE_URL: testDatabaseUrl },
stdio: 'pipe',
});
async function requestLink(
formData: FormData,
send: (input: { email: string }) => Promise<ApiResult<void>>,
pending: typeof PENDING_VERIFICATION,
Comment thread apps/web/README.md
Comment on lines +5 to +15
First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
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.

2 participants