Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
Translation pending
Restaurants, shops, hotels or any business: stick up an NFC tag and receive job applications with a PDF CV, organised in one dashboard. No apps, no paperwork.
BusinessJavaScript · EJSGitHub @JpsoaresfigOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Candidaturas por NFC para qualquer negócio em Espanha — restaurantes, lojas, hotéis, cabeleireiros, ginásios…
O candidato aproxima o telemóvel da etiqueta NFC do estabelecimento, abre a página do negócio, preenche o formulário e envia o CV em PDF. A candidatura aparece no painel do restaurante, onde o dono a organiza, contacta o candidato e acompanha o processo até à contratação.
Etiqueta NFC → /r/:slug → formulário + CV (PDF) → painel do restaurante → Nuevo … Contratado
A etiqueta não é programada pelo sistema: o Fíchame fornece a URL e o dono grava-a na tag com qualquer app de escrita NFC (ex.: NFC Tools).
🎨 Logo e cores da marca:
brand/📄 Documentação técnica completa (rotas, fluxos, modelo de dados, segurança, testes):
docs/DOCUMENTACAO.md⚖️ Auditoria jurídica e de segurança (2026-10):
docs/legal/(em espanhol, para o assessor jurídico) edocs/security/
Candidato — sem conta, mobile-first, em espanhol
/r/:slug com logo, descrição e estado de contratação (🟢 / 🔴)./r/:slug/privacidad./r/:slug/privacidad#derechos) que chega ao painel do negócio com prazo de 1 mês.Restaurante — painel /panel
tel:, mailto: e WhatsApp./panel/qr).Landing page — /
Página de apresentação — /conoce
?lang=en (ou se o browser estiver em inglês). Texto em src/lib/conoce.js — só descreve o que o produto faz hoje.public/video/fichame-demo.mp4 (legendas em espanhol) e fichame-demo-en.mp4 (inglês), ~1 min 45 s, gravados da aplicação real com dados fictícios. Para regenerar depois de mudar a interface: ver o cabeçalho de scripts/demo-video/record.js. Sem ficheiro, a página mostra «Vídeo en preparación». Nada é descarregado até carregar no play.CONTACT_EMAIL (opcional) mostra um botão «Escríbenos» na secção de opinião.Idiomas — espanhol, inglês e português
fichame_lang, só quando se escolhe).tr('…'); traduções em src/locales/. node scripts/i18n-check.js lista o que falta./admin também.Demo — /demo (botão na /conoce)
npm run demo:seed (correr de novo recria-o com datas atuais)./r/demo não aceita candidaturas. Emails em example.com, telefones 000….Admin da plataforma — /admin
/admin/divulgacion): o QR único que leva a /conoce, para descarregar (PNG/SVG), imprimir ou copiar o link. Só o admin o vê./admin/reportes): reportes enviados pelos negócios (erro, sugestão, dúvida), com estado Nuevo → En revisión → Resuelto, e os últimos erros 500 do servidor. Cada erro tem um código (ex.: A3F9C2) que a pessoa vê no ecrã; se reportar a partir dali, o reporte fica ligado ao erro. Aviso por email para ADMIN_EMAIL (com SMTP), sem o texto do reporte.Reportar un problema — /panel/reportar (no menu lateral; no telemóvel em Ajustes)
ERROR_EVENT_DAYS (90) e REPORT_DAYS (365) dias.| Camada | Tecnologia |
|---|---|
| Servidor | Node.js 22 + Express 5 |
| Views | EJS server-rendered, CSS mobile-first, sem build step |
| Base de dados | Supabase PostgreSQL via PostgREST (@supabase/supabase-js) |
| Ficheiros | Supabase Storage — buckets privados cvs e media |
| Uploads | Multer (em memória) + validação por magic bytes |
| Autenticação | Sessões próprias em BD (não usa Supabase Auth) |
A lógica que o PostgREST não exprime (agregações, pesquisa em vários campos, operações transacionais) vive no Postgres como views e funções jsonb — ver migrations/0002_views_rpc.sql.
Requisitos: Node.js ≥ 22 e um projeto Supabase.
git clone https://github.com/Jpsoaresfig/EZCV.git
cd EZCV
npm install
cp .env.example .env
Preencher o .env com os dados de Supabase → Project Settings → API:
SUPABASE_URLSUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEY — secreta, só no backendOpção A — pelo terminal (requer psql e DATABASE_URL no .env):
npm run migrate
Opção B — pelo painel: em SQL Editor → New query, colar e correr por ordem:
migrations/0001_init.sqlmigrations/0002_views_rpc.sqlmigrations/0003_storage.sqlmigrations/0004_notifications_cascade.sqlmigrations/0005_privacy_hardening.sqlmigrations/0006_tenant_fk_cleanup.sqlmigrations/0007_google_login.sqlmigrations/0008_onboarding_steps.sqlmigrations/0009_problem_reports.sqlmigrations/0010_terms_acceptances.sqlAs migrations são idempotentes. 0000_reset.sql é destrutivo (apaga o schema) e só corre com npm run migrate -- --reset.
npm run check # valida .env, migrations, views e buckets privados
npm run setup # cria o admin da plataforma (requer ADMIN_PASSWORD)
npm run dev # http://localhost:3000, com auto-reload
O servidor verifica o Supabase no arranque e recusa-se a servir se faltar uma migration ou um bucket, indicando o que corrigir.
/registro — entra direto no painel.https://<APP_URL>/r/<slug>) e gravá-la na tag NFC.Defina
APP_URLcom o domínio real antes de gravar as etiquetas.
| Comando | Descrição |
|---|---|
npm start | Arranca o servidor |
npm run dev | Arranca com auto-reload (node --watch) |
npm run migrate | Aplica as migrations via psql (--reset, --so <n>) |
npm run check | Diagnóstico do ambiente e do Supabase |
npm run setup | Cria o admin da plataforma |
npm run retention | Retenção por negócio — simula por omissão; --aplicar suprime candidaturas vencidas, CVs (BD + Storage), CVs órfãos, sessões/tokens/logs expirados |
npm run delete-account | Fecho de conta sem órfãos (--id, --slug, --aplicar) |
npm test | Unitários + migrations numa BD temporária + E2E contra o Supabase |
npm run test:unit / test:db / test:e2e | Cada suite isoladamente |
npm run audit | npm audit das dependências de produção |
Ver .env.example para a lista comentada.
| Variável | Padrão | Descrição |
|---|---|---|
PORT | 3000 | Porta HTTP |
APP_URL | http://localhost:3000 | URL pública — base das URLs NFC |
SUPABASE_URL | — | Obrigatória |
SUPABASE_ANON_KEY | — | Chave publishable |
SUPABASE_SERVICE_ROLE_KEY | — | Obrigatória. Nunca no frontend, no git ou em logs |
SUPABASE_BUCKET_CVS / _MEDIA | cvs / media | Buckets privados |
DATABASE_URL | — | Só para npm run migrate; a app não a usa |
SESSION_TTL_DAYS | 30 | Validade da sessão de negócio (sessões anónimas: 2 h) |
COOKIE_SECURE / TRUST_PROXY | 0 | 1 em produção com HTTPS / atrás de proxy |
MAX_CV_MB / MAX_IMAGE_MB | 5 / 2 | Limites de upload |
ADMIN_EMAIL / ADMIN_PASSWORD / ADMIN_NAME | — | Seed do admin |
SMTP_* | vazio | Sem SMTP não há avisos por email nem recuperação de senha (o conteúdo nunca vai para o log) |
OPERATOR_* | marcadores | Identificação do titular do Fíchame nas páginas legais |
CRON_SECRET / RETENTION_AUTO | — / 0 | Retenção automática via GET /internal/retention |
SECURITY_LOG_DAYS / RIGHTS_REQUEST_DAYS | 365 / 1095 | Conservação de logs e pedidos de direitos fechados |
migrations/ SQL versionado: tabelas, RLS, views/RPC, storage
src/
server.js arranque (verifica o Supabase antes de servir)
app.js Express: middlewares, cabeçalhos de segurança, rotas
config.js leitura e validação do ambiente
db/ cliente Supabase, migrate, check, seed, retention
middleware/ session, csrf, auth, rate limit, uploads
lib/ crypto, slug, statuses, consent, storage, mailer
routes/ public (NFC), auth, panel, admin, legal
views/ templates EJS
public/ CSS e JS do cliente
test/smoke.js teste E2E
docs/ documentação técnica
restaurant_id da sessão — IDs alheios devolvem 404.anon/authenticated.(id, restaurant_id) e CHECK da pasta do CV no Storage.scrypt (mín. 10); login sem enumeração; recuperação de senha com token de uso único (hash, 30 min); mudar/repor a senha termina as outras sessões.__Host- + Secure em produção, HttpOnly, SameSite=Lax.no-store em respostas dinâmicas, noindex fora das páginas públicas.Inventário completo em docs/DOCUMENTACAO.md §8.
Proteção de dados: o Fíchame foi desenhado com medidas de proteção de dados e segurança, sujeitas à configuração adequada, às responsabilidades de cada parte e à revisão jurídica aplicável. Não é uma declaração de conformidade. Há PRODUCTION BLOCKERS e pontos de LEGAL REVIEW REQUIRED — ver
docs/security/production-compliance-gate.mdedocs/legal/00-legal-review-required.md. Para os dados de candidatos, o papel proposto é: negócio = responsável, Fíchame = encarregado (análise por tratamento emdocs/legal/02-…).
npm test
test/unit.test.js — sem rede: validação de PDF e nomes de ficheiro, detetor de características protegidas, truncagem de IP, política de senha, textos de consentimento, cabeçalhos.test/db.js — cria um PostgreSQL temporário (initdb), simula o Supabase, aplica as migrations 2× e testa isolamento entre tenants na BD, reserva/consentimento, retenção por tenant, legal_hold, supressão, permissões de anon e autodiagnóstico. Requer os binários do PostgreSQL (PG_BIN).test/smoke.js — E2E contra o Supabase real: fluxo completo, informação legal, IDOR A↔B, uploads maliciosos, XSS, CSRF, cabeçalhos, enumeração, força bruta, recuperação de senha, invalidação de sessões, direitos (exportação, supressão, retirada), auditoria, admin sem acesso a candidatos.Cada execução marca os seus dados com um prefixo único e apaga-os no fim com purge_test_data, incluindo os objetos no Storage.
Resolver os BLOCKERS de docs/security/production-compliance-gate.md, em especial:
docs/legal/01-….OPERATOR_*), regiões UE e DPA de Supabase/Vercel, textos legais revistos.COOKIE_SECURE=1, TRUST_PROXY=1, APP_URL=https://…; SMTP real.CRON_SECRET, RETENTION_AUTO=1).Lista completa em docs/DOCUMENTACAO.md §12.