# RiLiGar Auth — Documentação Completa (LLM-Ready, End-to-End) > Este arquivo é a **documentação integral** do sistema RiLiGar Auth. Não há outra referência: ele deve conter tudo que um desenvolvedor humano ou um LLM precisa para integrar, operar e estender o sistema em produção. > > O sistema é composto por três partes principais: > 1. **`@riligar/auth-react`** — SDK front-end (React + Mantine) com componentes UI, hooks, store e cliente HTTP. > 2. **`@riligar/auth-elysia`** — Plugin back-end para ElysiaJS que valida JWT/JWKS e protege rotas. > 3. **Auth Worker** (`auth.worker.myinfrastructure.click`) — API HTTP em Cloudflare Workers que emite/valida tokens e gerencia usuários, sessões e os códigos de acesso. > > 4. **Servidor MCP** (`auth.worker.myinfrastructure.click/mcp/`) — Model Context Protocol, revisão `2026-07-28`. Permite que agentes de IA administrem o tenant por linguagem natural, e usa o Auth como authorization server OAuth 2.1. **Documentação completa e separada em [/llms-mcp.txt](https://myinfrastructure.click/products/auth/llms-mcp.txt).** > > A base URL padrão da API é `https://auth.worker.myinfrastructure.click`. Autenticação de aplicação é feita via `X-API-Key: pu_...` (public key) no cliente e `X-API-Key: sk_...` (secret key) no servidor. > > --- > > **Verificado contra o código em 2026-09-04.** Trechos marcados com ⛔ descrevem recursos que **não existem** — o SDK exporta funções que chamam rotas mortas, e este arquivo diz quais são. Se você é um agente de IA integrando este sistema, leia a seção **8. Checklist para Implementação por IA** antes de escrever qualquer linha, e principalmente a subseção **"O que NÃO existe"**. --- ## 0. Credenciais — LEIA ANTES DE ESCREVER CÓDIGO O Auth tem **três** identificadores, e eles não são intercambiáveis. Pedir o errado custa uma volta inteira ao usuário. Descubra primeiro **o que você está construindo**: | Se você vai... | Precisa de | Segredo? | | :--- | :--- | :--- | | Montar o `` no React | `pu_…` (public key) | Não — vai no bundle | | Montar o `authPlugin()` no Elysia | `sk_…` (secret key) | **Sim** — só no servidor | | Conectar um agente ao MCP do Auth | `applicationId` + OAuth | Não — login no navegador | | **Ser um agente e ainda não ter conta nem chave** | **nada — use a entrada por código (abaixo)** | Não — um código de 8 caracteres | **Uma integração completa (frontend + backend) precisa das duas chaves.** Peça as duas de uma vez; não descubra a segunda na metade do trabalho. ### Via MCP (para administrar a aplicação) — nenhuma chave Se o seu host suporta Model Context Protocol e o objetivo é **administrar** o tenant (listar usuários, ver estatísticas, revogar sessões), **use MCP com OAuth 2.1**. Não peça chave: o usuário loga no navegador e aprova os escopos. ```bash claude mcp add --transport http riligar-auth \ https://auth.worker.myinfrastructure.click/mcp/ ``` > Preciso do ID da aplicação para conectar. Ele está no seu **dashboard**, nas **Chaves de > API** da aplicação, aba **MCP** — o endereço mostrado já traz o ID no final. Pode colar o > endereço inteiro. O login é no navegador, então não preciso de chave secreta. ⚠️ O MCP **administra**; ele **não** integra login no seu app. Para colocar signin/signup numa aplicação React, o caminho é o SDK, e aí as chaves abaixo são necessárias. ### Via SDK — as chaves `pu_` e `sk_` **Como pedir ao usuário** — use este texto: > Preciso das chaves da sua aplicação no RiLiGar Auth. Elas estão no seu **dashboard**, nas > **Chaves de API** da aplicação. Preciso das duas: > - a **Chave Pública** (`pu_…`) — vai no frontend, no ``; > - a **Chave Secret** (`sk_…`) — vai só no backend, numa variável de ambiente. > > Se já existirem, é só copiar. **Uma chave recém-criada só aparece por inteiro uma vez** — > se essa janela já fechou, gere outra. Regras que o agente não pode violar: - **Nunca** coloque a `sk_` no frontend, em `VITE_*`, em `NEXT_PUBLIC_*` ou em qualquer arquivo que vá para o bundle. Ela assina sessões. - A `pu_` é pública por natureza — pode ficar no código do cliente sem medo. - Se o usuário mandar só uma chave e você precisa das duas, **pare e peça a outra**, dizendo qual das duas está faltando pelo prefixo. ### Você consegue obter as chaves sozinho — a entrada por código **Se você é um agente e o usuário ainda não tem conta, ou não tem as chaves em mãos, você não precisa parar.** A entrada leva você de "nenhuma credencial" a uma `pu_`/`sk_` funcionando com **uma única interação humana**: a pessoa lê um código de 8 caracteres no e-mail e informa a você. Depois disso, você cria organização, aplicação e chaves sozinho, por HTTP. É o MESMO caminho que uma pessoa percorre no painel — não existe um fluxo para humanos e outro para agentes. A única diferença é quem digita o código. ``` POST /auth/code/start {email, name?} → sent, expiresIn, interval, deviceCode ↓ a pessoa recebe um código de 8 caracteres por e-mail (ABCD-EFGH) e informa a você POST /auth/code/verify {email, code} → {user, token, session} ↓ daqui em diante você vai sozinho: POST /organizations {name} → orgId POST /application/:orgId {name} → applicationId POST /api-keys {applicationId, type} → pu_ / sk_ ``` **Como pedir o código** — use este texto: > Mandei um código de 8 caracteres para o seu e-mail. Me diga qual é para eu liberar o > acesso e seguir sozinho a partir daqui. Pode digitar como preferir — maiúsculas, > minúsculas, com ou sem o hífen. Detalhes que importam: - **O e-mail não traz link, traz um código.** Não há URL para abrir, e portanto nada para copiar de um navegador. Foi desenhado assim de propósito (ver abaixo). - **O código vale 10 minutos, cinco tentativas e uma vez só.** Cinco erros destroem o pedido (`429`); aí comece de novo pelo `start`. Cada erro devolve `details.attemptsLeft`. - **O `verify` exige o e-mail junto com o código.** É o que amarra a aprovação a um pedido específico, em vez de a qualquer pedido do sistema. - **Um `start` novo substitui o anterior do mesmo e-mail.** Só o código do último funciona. - **Se o e-mail não puder ser enviado**, o `start` responde `503 SERVICE_UNAVAILABLE` com `retry-after`. Não é falha sua: espere e repita. - **Não existe cadastro separado.** Se o e-mail nunca entrou, a conta nasce aqui — já verificada e com uma organização própria. Se já existe, entra. Você não precisa saber qual é o caso, e a resposta do `start` é a mesma nos dois. - **A sessão que sai daqui é de plataforma** (`applicationId: null`) quando você não manda chave pública, que é o que dá acesso a criar organizações e aplicações. Guarde o token: ele vale 7 dias. **Se você NÃO consegue receber o código** — um agente headless, sem ninguém para ler a caixa de entrada na hora — existe a variante com polling, que segue o RFC 8628: ``` POST /auth/code/start {email} → deviceCode, interval POST /auth/code/poll {deviceCode} → 428 enquanto ninguém apresentou o código → {user, token, session} quando alguém apresentou ``` Enquanto a pessoa não informar o código, o `poll` responde `428` com `authorization_pending`. Faça poll a cada 5 segundos (o campo `details.interval` diz). Se vier `429 slow_down`, use o `interval` novo da resposta — você está mais rápido que o combinado. **No navegador, use `verify`**: ele resolve na mesma chamada, sem espera. **Por que não há link no e-mail.** Um link precisaria de um endereço de retorno, e o Auth grava a primeira origem que vê como a origem oficial da aplicação. Um endereço provisório usado numa única vez ficaria fixado ali. Com um código, esse risco não existe: não há destino para gravar, e não há callback para um atacante sequestrar. **Endereços descartáveis nunca viram a identidade da aplicação.** Previews de deploy (`*.pages.dev`, `*.vercel.app`, `*.netlify.app`, `*.workers.dev`, `*.fly.dev` e afins), túneis de localhost (`*.ngrok-free.app`, `*.trycloudflare.com`, `*.loca.lt`) e domínios de desenvolvimento (`.local`, `.test`) **funcionam normalmente para autenticar, mas não são aprendidos** como a origem da aplicação. Você pode testar a integração por um preview sem medo de fixar aquele endereço para o seu cliente. A origem real é aprendida no primeiro acesso vindo de um domínio de verdade — ou definida por você, no painel. **O que continua exigindo um humano:** só a leitura do código. Não há caminho que dispense isso, e não deve haver — é a prova de que quem pediu o acesso alcança a caixa de e-mail. Não invente rota de criação de chave, e não gere código com placeholder `pu_xxx` fingindo que terminou. --- ## Sumário 0. **Credenciais — leia antes de escrever código** (qual chave pedir, e o texto do pedido) 1. Arquitetura e Fluxo End-to-End 2. Instalação e Requisitos 3. Pacote `@riligar/auth-react` — Referência Completa - 3.1 `AuthProvider` (configuração global) - 3.2 Hooks - 3.3 Componentes de Controle (render condicional) - 3.4 Componente de Proteção de Rota (``) - 3.5 Componentes de Formulário (SignIn, UserProfile) - 3.6 `` e `` - 3.7 Botões Unstyled - 3.8 Funções do SDK HTTP (`authSdk`) - 3.9 Store Zustand (`useAuthStore`) - 3.10 Tipos, Eventos, LocalStorage - 3.11 Nomes removidos na 4.0.0 4. Pacote `@riligar/auth-elysia` — Referência Completa - 4.1 `authPlugin` e `AuthConfig` - 4.2 Rotas auto-registradas - 4.3 Contexto derivado (`user`) - 4.4 `RiLiGarAuthClient` (JWKS + verificação JWT) - 4.5 `fetchAuth` helper - 4.6 Multi-tenancy e RBAC manual 5. Endpoints da API (contrato backend) 6. Blueprint de Rotas SaaS 7. Design System (Zen Aesthetics) 8. Checklist para Implementação por IA 9. Troubleshooting 10. Servidor MCP (documento separado) --- ## 1. Arquitetura e Fluxo End-to-End ``` ┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────────────┐ │ React App │ │ Backend (Elysia) │ │ Auth Worker │ │ @riligar/auth-react│──────────▶│ @riligar/auth-elysia│──────────▶│ auth.worker... │ │ │ Bearer │ │ JWKS │ │ │ useAuth / SignIn │ token │ derive({user}) │ + API │ /auth/* endpoints │ │ + SDK HTTP │ │ onBeforeHandle 401 │ │ /.well-known/jwks │ └─────────────────────┘ └──────────────────────┘ └─────────────────────┘ │ │ │ │ X-API-Key: pu_... (public) │ X-API-Key: sk_... (secret) │ │ Authorization: Bearer │ Authorization: Bearer │ └──────────────────────────────────┴──────────────────────────────────┘ ``` **Ciclo de autenticação típico (código por e-mail — o único que existe):** 1. App React monta ``. 2. `AuthProvider` lê `localStorage["auth:token"]` e, se existir e for válido, hidrata `user` via `GET /auth/session`. 3. Também chama `GET /application/by-api-key` para obter logo/branding da aplicação. 4. Usuário informa o e-mail em `` → `POST /auth/code/start` → um código de 8 caracteres sai por e-mail. 4b. Usuário digita o código na MESMA aba → `POST /auth/code/verify` → resposta traz `{ token, user, session }`. Se a conta não existia, nasce aqui — verificada e com organização própria. 5. Token é gravado em `localStorage["auth:token"]` e um `storage` event sincroniza outras abas. 6. A cada 30s o SDK revalida a expiração do token; a cada 4 minutos, se faltar <5min para expirar, chama `POST /auth/refresh`, que rotaciona o token da sessão atual sem criar linha nova. 7. Requisições subsequentes ao seu backend levam `Authorization: Bearer `. 8. Backend (Elysia) valida o token **localmente** via JWKS (cache 1h) ou faz fallback remoto para `GET /auth/session`. Injeta `user` no contexto. 9. Logout: `POST /auth/sign-out` → remove `auth:token` → dispara `storage` event (`auth:logout`) → outras abas deslogam. **Eventos customizados:** - `auth:session-revoked` (window) — disparado quando o usuário revoga a própria sessão; força signOut local. - `storage` com key `auth:logout` — sincronização cross-tab de logout. - `storage` com key `auth:token` — sincronização cross-tab de login/refresh. --- ## 2. Instalação e Requisitos ### Frontend (React) ```bash npm install @riligar/auth-react npm install react react-dom react-router-dom zustand npm install @mantine/core @mantine/form @mantine/hooks @tabler/icons-react ``` **Peer dependencies:** | Dependência | Versão | | :--- | :--- | | `react` | `^18.0.0 \|\| ^19.0.0` (obrigatório) | | `react-dom` | `^18.0.0 \|\| ^19.0.0` (obrigatório) | | `react-router-dom` | `^6.0.0 \|\| ^7.0.0` (obrigatório) | | `zustand` | `^5.0.0` (obrigatório) | | `@mantine/core` | `^8.0.0` (opcional — necessário para usar componentes UI) | | `@mantine/form` | `^8.0.0` (opcional) | | `@mantine/hooks` | `^8.0.0` (opcional) | | `@tabler/icons-react` | `^3.0.0` (opcional) | ### Backend (Elysia) ```bash bun add @riligar/auth-elysia elysia ``` Peer: `elysia >= 1.0.0`. **Variáveis de ambiente (backend):** ```bash AUTH_SECRET_KEY=sk_... # secret key da aplicação (HS256) AUTH_API_URL=https://auth.worker.myinfrastructure.click # base URL do Auth Worker NODE_ENV=production # ativa cookie.secure=true ``` --- ## 3. Pacote `@riligar/auth-react` — Referência Completa **Exports do entry point** (`src/index.js`): - Funções SDK: `configure`, `isInternal`, `getApiUrl`, `decodeJWT`, `isAuthenticated`, `getCurrentUser`, `requestCode`, `verifyCode`, `pollCode`, `signOut`, `refreshToken`, `getSession`, `listSessions`, `revokeSession`, `revokeOtherSessions`, `getApplicationInfo`, `updateProfile`, `setStoredToken`. - Store: `useAuthStore`. - Provider + Hooks: `AuthProvider`, `useAuth`, `useSignIn`, `useSignOut`, `useCheckToken`, `useSession`, `useSessions`, `useAuthLoading`, `useUser`, `useApplicationLogo`. - Proteção: `Protect`. - Componentes UI: `AuthCard`, `SignIn`, `UserProfile`, `UserInformation`, `Wordmark`. - Controle: `SignedIn`, `SignedOut`, `AuthLoading`, `AuthLoaded`. - Unstyled: `SignInButton`, `SignOutButton`. - Redirect: `resolveRedirect`, `applyRedirect`, `getRedirectFromLocation`. **A 4.0.0 removeu os aliases depreciados** (`SignInForm`, `AccountModal`, `ProtectedRoute`, `useProfile`…) junto com os componentes e funções dos fluxos de senha e link. Se o seu código importa algum deles, troque pelo nome canônico da lista acima. --- ### 3.1 `AuthProvider` Envolve a raiz da aplicação. Inicializa o SDK, hidrata sessão, inicia o refresh loop e sincroniza abas. **Props:** | Prop | Tipo | Default | Descrição | | :--- | :--- | :--- | :--- | | `children` | `ReactNode` | — | Obrigatório. | | `apiKey` | `string` | — | Public key `pu_...`. Obrigatório, exceto quando `internal=true`. Enviado como header `X-API-Key`. | | `apiUrl` | `string` | `"https://auth.worker.myinfrastructure.click"` | Override da base URL da API. | | `internal` | `boolean` | `false` | Quando `true`, dispensa `apiKey` (app same-domain com o Auth Worker). | | `onError` | `(error) => void` | — | Callback global de erro. | **Exemplo:** ```jsx import { AuthProvider } from '@riligar/auth-react' console.error('[Auth]', err)} > ``` **Comportamento interno:** - `init()` ao montar: lê token, valida expiração, chama `GET /auth/session` se válido. - `startRefresh()`: `setInterval` de 30s para checar validade; refresh 4 minutos antes da expiração. - Listener `storage`: reage a `auth:logout` e `auth:token` para manter todas as abas em sincronia. - Listener `auth:session-revoked`: força logout local quando o servidor indica revogação. --- ### 3.2 Hooks Todos usam `zustand/react/shallow` para evitar re-renders desnecessários. #### `useAuth()` Hook central. **Retorna:** ```ts { user: User | null, loading: boolean, error: Error | null, isAuthenticated: boolean, // user !== null requestCode: (email, opts?) => Promise<{ sent, expiresIn, interval, deviceCode }>, verifyCode: (email, code) => Promise<{ token, user, session }>, signOut: () => Promise, } ``` #### `useSignIn()` Os dois passos da entrada, e nada mais. ```ts { requestCode: (email: string, opts?: { name?: string }) => Promise<{ sent, expiresIn, interval, deviceCode }>, verifyCode: (email: string, code: string) => Promise<{ token, user, session }>, sending: boolean, // requestCode em andamento verifying: boolean, // verifyCode em andamento error: Error | null, } ``` Não há `useSignUp`: a conta nasce no primeiro `verifyCode`, já verificada e com uma organização própria. E não há `useMagicLink`, `usePasswordReset` nem `useEmailVerification` — os três fluxos saíram. #### `useSignOut()` Retorna: `() => Promise`. #### `useCheckToken()` Retorna: `() => boolean`. Verifica se o token armazenado ainda é válido (não expirado). #### `useSession()` ```ts { getSession: () => Promise<{ user, session, application }>, user: User | null, setUser: (user | null) => void, } ``` #### `useSessions()` Gestão multi-device. ```ts { currentSession: Session | null, sessions: Session[], getSession: () => Promise, listSessions: () => Promise, revokeSession: (sessionId: string) => Promise, revokeOtherSessions: () => Promise, loadingListSessions: boolean, loadingRevokeSession: null | string | 'all', // id específico, 'all', ou null error: Error | null, } ``` #### `useAuthLoading()` Flags granulares de loading por operação: ```ts { requestCode, verifyCode, signOut, updateProfile, listSessions, // boolean revokeSession: null | string | 'all', } ``` Todos `boolean`, exceto `revokeSession`. #### `useUser()` ```ts { user: User | null, updateProfile: (data: Partial) => Promise, changePassword: (currentPassword, newPassword, revokeOtherSessions?: boolean) => Promise, changeEmail: (newEmail: string, callbackURL?: string) => Promise, loadingUpdateProfile: boolean, loadingChangePassword: boolean, loadingChangeEmail: boolean, error: Error | null, } ``` #### `useApplicationLogo()` Retorna: `string | null`. URL/data-URI do logo da aplicação carregado via `GET /application/by-api-key`. #### `useAuthStore()` Acesso direto ao store Zustand (ver §3.9). Exportado, mas raramente necessário em componentes. --- ### 3.3 Componentes de Controle Renderização condicional baseada em estado de autenticação. | Componente | Renderiza `children` quando | | :--- | :--- | | `` | `user !== null` **e** `loading === false` | | `` | `user === null` **e** `loading === false` | | `` | `loading === true` | | `` | `loading === false` | **Todos aceitam apenas:** `children: ReactNode`. ```jsx ``` --- ### 3.4 `` — Guarda de Rota (React Router) | Prop | Tipo | Default | Descrição | | :--- | :--- | :--- | :--- | | `fallback` | `ReactNode` | `

⌛ Carregando...

` | Exibido enquanto `loading`. | | `redirectTo` | `string` | `'/login'` | Rota para `` se não autenticado. | Renderiza `` quando autenticado. ```jsx }> } /> } /> ``` --- ### 3.5 Componentes de Formulário **Convenções comuns a todos:** - `variant: 'card' | 'modal'` — default: `'card'`. - Se `variant='modal'`: `opened: boolean`, `onClose: () => void`, `modalProps?: object` (spread em `` da Mantine). - `logo?: string`, `logoWidth?: number` (default 133) — sobrescrevem o logo da aplicação. - `labels?: object` — todos os textos são customizáveis (localização/tom). - Props extras fazem spread no `AuthCard` (Paper ou Modal). #### `` Wrapper genérico (usado internamente por todos os formulários). | Prop | Tipo | Default | | :--- | :--- | :--- | | `children` | `ReactNode` | — | | `title` | `string` | — | | `subtitle` | `string` | — | | `logo` | `string` | — | | `logoWidth` | `number` | `133` | | `width` | `number` | `350` | | `variant` | `'card' \| 'modal'` | `'card'` | | `opened` / `onClose` / `modalProps` | — | — | #### `` A tela de entrada inteira: pede o e-mail, depois recebe o código. Os dois passos na mesma rota, sem navegação no meio. | Prop | Tipo | Default | | :--- | :--- | :--- | | `title` | `string` | `'Entrar'` | | `subtitle` | `string` | `'Enviamos um código para o seu e-mail'` | | `logo` / `logoWidth` | — | logo da aplicação, ou o Wordmark | | `variant` | `'card' \| 'modal'` | `'card'` | | `opened` / `onClose` / `modalProps` | — | só em `variant="modal"` | | `authenticatedRedirect` | `string \| null` | `'/'` — para onde mandar quem já tem sessão | | `redirectingFallback` | `node` | `null` — o que mostrar durante o desvio | | `handleRedirect` | `boolean` | `true` — honra `?redirect=` da URL | | `redirectOrigins` | `string[]` | `[]` — origens extras permitidas no redirect | | `onCodeSent(email)` | `fn` | — | | `onSuccess(user, { result, redirectHandled })` | `fn` | — | | `onError(error)` | `fn` | — | | `labels` | `object` | ver abaixo | **Labels de ``:** `email`, `emailPlaceholder`, `emailRequired`, `invalidEmail`, `sendCodeButton`, `sendingCode`, `codeSentTo`, `codeLabel`, `verifyingCode`, `invalidCode`, `resendCode`, `changeEmail`. **`redirectHandled`** diz que o SDK já assumiu a navegação — é o fluxo OAuth voltando ao ponto de origem. Quando vier `true`, não navegue no `onSuccess`: você levaria o usuário para a home no meio da autorização. **Não existem ``, ``, ``, ``, `` nem ``.** Saíram na 4.0.0. A conta nasce no primeiro código apresentado, então cadastro e verificação deixaram de ser telas. #### `` Modal/card completo de gestão de conta. Seções: Avatar, Nome, Email (somente leitura) e Sessões. **Props principais:** | Prop | Tipo | Default | | :--- | :--- | :--- | | `variant` | `'card' \| 'modal'` | `'modal'` | | `opened` / `onClose` | — | controla o modal | | `title` | `string` | `'Account'` | | `subtitle` | `string` | `'Manage your account info.'` | | `logo` / `logoHeight` | `string / number` | — / `28` | | `width` | `number` | `500` | | `maxAvatarSize` | `number` (bytes) | `512000` (500 KB) | | `showAvatar` / `showName` / `showEmail` / `showSessions` | `boolean` | `true` | | `customSections` | `ReactNode` | — (renderizado após seções built-in) | **Callbacks:** `onProfileUpdate(data)`, `onSessionRevoked(sessionId)`, `onOtherSessionsRevoked()`, `onError(err)`. **Comportamento:** - Avatar é enviado como base64 (validado contra `maxAvatarSize`). - Seção de sessões lista `GET /auth/list-sessions` com parsing de user-agent; destaca "Este dispositivo". - **O e-mail não se edita**: é ele que recebe o código de acesso, então trocá-lo é trocar de identidade — e isso exige provar a posse da caixa nova, que é o próprio fluxo de entrada. - Não há seção de senha: não há senha. **Labels** (extenso — ver código para lista completa): `avatar`, `update`, `updateAvatar`, `clickToChange`, `avatarRequired`, `avatarInvalidType`, `avatarTooLarge`, `avatarHint`, `remove`, `cancel`, `save`, `name`, `change`, `changeName`, `namePlaceholder`, `nameRequired`, `notDefined`, `email`, `sessions`, `manage`, `manageSessions`, `close`, `loadingSessions`, `noSessionsFound`, `endSession`, `signOutAndEnd`, `end`, `endOtherSessions`, `thisDevice`, `unknownIP`, `createdAt`, `at`, `profileSection`, `profileDescription`, `securitySection`, `securityDescription`. #### `` Bloco compacto (header/sidebar/menu) com avatar + nome + email + signOut. | Prop | Tipo | Default | | :--- | :--- | :--- | | `user` | `User` | obrigatório | | `signOut` | `() => void` | obrigatório | | `onAccountClick` / `onBillingClick` | `fn` | — | | `accountLabel` | `string` | `'Conta'` | | `billingLabel` | `string` | `'Assinatura'` | | `padded` | `boolean` | `true` | | `size` | `'sm' \| 'md' \| 'lg'` | `'sm'` | Inclui rodapé "Secured by Auth". --- ### 3.7 Botões Unstyled Elementos `