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.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 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.