Mostrar oportunidades publicadas antes do registo de candidatos

This commit is contained in:
2026-10-30 21:15:27 +02:00
parent bf84575d10
commit c22846b2b1
10 changed files with 528 additions and 8 deletions
+20
View File
@@ -1,5 +1,25 @@
# Desenvolvimento do SGC
## Consulta de oportunidades antes do registo, 30 de Outubro de 2026
A entrada da área do candidato mostra oportunidades explicitamente publicadas, abertas e dentro do prazo, com título, tipo, data e descrição pública. Não expõe finalidade interna, regras, candidaturas, avaliações ou documentos. A consulta é paginada por empresa; a última versão da publicação controla a visibilidade, incluindo retirada. O fecho de novos registos mantém a consulta pública e a entrada das contas existentes. Preparar e enviar candidaturas continuam a exigir autenticação própria, perfil e confirmação de email conforme as regras já existentes.
A área autenticada reutiliza a mesma consulta e passa a ter paginação, em vez de omitir oportunidades depois das primeiras 20. Retirada a mensagem desactualizada de que o envio de documentos ainda não estava disponível. Não foram abertas inscrições, publicadas oportunidades ou criadas contas para testar no domínio.
Verificação dirigida: 24 testes PHP/374 asserções em perfil e submissões; PostgreSQL descartável: 64 testes/1401 asserções, incluindo Pessoas e formatos de documentos. Dez testes frontend dirigidos, tipos, PHPStan sem erros, Pint e lint dirigidos aprovados. As provas integrais aceites da entrega bf84575 são reutilizadas, sem alegar nova execução de toda a suíte. Conferência visual tentada novamente: conector devolveu native pipe indisponível e browser host indisponível. Este incremento continua local e não faz parte da release bf84575 activa no domínio. Provas `proofs/candidate-public-opportunities.json` e `candidate-public-opportunities-pg.json`.
## Entrega em produção confirmada — bf84575, 30 de Outubro de 2026
O commit `bf84575d10d9063c2224945e6d5627da826148a9` está em main e activo no domínio, na release `20261030-190744-bf84575d10d9-KyKKDI71`. O serviço existente terminou com Result=success e ExecMainStatus=0. Esta confirmação actualiza as indicações históricas de instalação apenas local abaixo.
O instalador foi corrigido para exigir HTTP 200 em `/dashboard`: o anterior teste da raiz recebia o redireccionamento público esperado e provocava rollback. A validação e o rollback do instalador foram mantidos. Configuração anterior salvaguardada antes da correcção.
Delta reconciliado: 14 migrações, de 000028 a 000041, sem repetir as 30 já registadas. Backup fresco da base e armazenamento, restauro conferido e ensaio das migrações na cópia antes da transacção de produção. As 81 tabelas anteriores conservaram os seus dados nas colunas de origem; 18 novas tabelas conferidas vazias e schema final igual ao ensaio. Existem agora 44 migrações registadas. A migração 000028 acrescenta o parâmetro de IVA por empresa com valor inicial 16%, sem reescrever os valores e snapshots anteriores. Não foram criadas contas, abertas inscrições ou publicadas oportunidades automaticamente.
Armazenamento privado em storage partilhado persistente, com escrita conferida para www-data. Limites específicos do domínio: ficheiro 50M, pedido PHP e Nginx 104M, até 20 ficheiros; configuração Nginx validada e recarregada. Os 2M/8M ainda apresentados pelo PHP CLI são os limites do terminal e não os parâmetros específicos do domínio. PHP 8.4 dispõe de DOM/ZIP/fileinfo; PHP 8.5 CLI continua sem DOM/ZIP e não foi usado na instalação.
Conferência HTTP: 21 ecrãs públicos com componentes esperados, utilizador nulo e âmbito vazio; sete percursos privados protegidos. Prova `proofs/candidate-documents-production.json`. Conferência visual dirigida e ensaio com candidatura real no domínio continuam pendentes; não foram enviados ficheiros pessoais ou emails reais para os simular.
## CV e documentos na candidatura electrónica, 30 de Outubro de 2026
Recepção de documentos integrada no mesmo envio da candidatura. A obrigatoriedade, formatos (PDF, DOCX, JPG e PNG) e limite por ficheiro vêm do formulário preservado na preparação do processo, sem procurar a versão actual da empresa. Recusados documentos desconhecidos, obrigatórios em falta, tamanho excessivo e divergência de extensão/MIME/conteúdo. DOCX exige estrutura Word/XML válida, sem declarações de entidades/DOCTYPE, macros ou executáveis conhecidos, com limites de entradas e expansão do arquivo. A conferência de formato não constitui antivírus, prova de autenticidade, validação do mérito ou aprovação documental.
@@ -0,0 +1,253 @@
{
"checked_at": "2026-10-30T19:09:50.960374+00:00",
"commit": "bf84575d10d9063c2224945e6d5627da826148a9",
"release": "/var/www/compras-deploy/releases/20261030-190744-bf84575d10d9-KyKKDI71",
"deployment_service": "success",
"migration_count": 44,
"migrations_applied": 14,
"existing_tables_preserved": 81,
"new_tables_verified_empty": 18,
"backup": "/root/compras-release-backups/20261030T190740921286Z-bf84575",
"database_restore_verified": true,
"storage_restore_verified": true,
"private_storage_shared": true,
"web_user_can_write_private_uploads": true,
"nginx_validation_ok": true,
"site_upload_configuration": [
"\n client_max_body_size 104M;",
" fastcgi_param PHP_VALUE \"upload_max_filesize=50M\\npost_max_size=104M\\nmax_file_uploads=20\";"
],
"cli_limits_apply_to_cli_only": true,
"application": {
"database_driver": "pgsql",
"migration_count": 44,
"candidate_migrations": [
"2026_10_30_000037_create_candidate_profiles",
"2026_10_30_000038_create_candidate_access_tokens",
"2026_10_30_000039_create_candidate_submissions",
"2026_10_30_000040_create_candidate_triage",
"2026_10_30_000041_create_candidate_submission_documents"
],
"documents_table_exists": true,
"document_count": 0,
"public_navigation_enabled": true,
"candidate_disk_root": "/var/www/compras-deploy/releases/20261030-190744-bf84575d10d9-KyKKDI71/storage/app/candidate-documents"
},
"http": {
"checked_at": "2026-10-30T19:08:35.710090+00:00",
"results": [
{
"path": "/",
"status": 302,
"location": "https://compras.tempo.co.mz/dashboard"
},
{
"path": "/dashboard",
"status": 200,
"component": "dashboard",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/requisicoes",
"status": 200,
"component": "requisitions/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/requisicoes/criar",
"status": 200,
"component": "requisitions/form",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/fornecedores",
"status": 200,
"component": "suppliers/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/cotacoes",
"status": 200,
"component": "quotations/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/ordens",
"status": 200,
"component": "purchases/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/recepcoes",
"status": 200,
"component": "receipts/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/stock",
"status": 200,
"component": "stock/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/stock/catalogo",
"status": 200,
"component": "stock/catalogue",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/stock/operacoes",
"status": 200,
"component": "stock/operations",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/equipamentos",
"status": 200,
"component": "equipment/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/planeamento",
"status": 200,
"component": "planning/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/pessoas",
"status": 200,
"component": "people/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/orcamentos",
"status": 200,
"component": "budgets/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/facturas",
"status": 200,
"component": "invoices/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/pagamentos",
"status": 200,
"component": "payments/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/regras-investimento",
"status": 200,
"component": "investment/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/politica-admissao",
"status": 200,
"component": "purchases/admission-policy",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/politica-recomendacao",
"status": 200,
"component": "purchases/recommendation-policy",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/revisao-compras",
"status": 200,
"component": "purchase-controls/index",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/settings/appearance",
"status": 200,
"component": "settings/appearance",
"anonymous": true,
"data_scope": "none",
"version": "d57b6033713dbe71fe3664abe9f56f4a"
},
{
"path": "/pessoas/cadastro",
"status": 302,
"location": "https://compras.tempo.co.mz/login"
},
{
"path": "/pessoas/1",
"status": 302,
"location": "https://compras.tempo.co.mz/login"
},
{
"path": "/fornecedores/1/dados-bancarios",
"status": 302,
"location": "https://compras.tempo.co.mz/login"
},
{
"path": "/administracao/parametrizacao",
"status": 302,
"location": "https://compras.tempo.co.mz/login"
},
{
"path": "/relatorios",
"status": 302,
"location": "https://compras.tempo.co.mz/login"
},
{
"path": "/settings/profile",
"status": 302,
"location": "https://compras.tempo.co.mz/login"
},
{
"path": "/candidaturas/1/submissoes/1/documentos/cv",
"status": 401
}
],
"public_pages_passed": 21,
"private_routes_protected": 7,
"server_activation_proof": "pending"
},
"visual_review": "pending",
"real_candidate_submission_in_production": "not performed"
}
@@ -0,0 +1,16 @@
{
"checked_at": "2026-10-30T19:14:38+00:00",
"database": "disposable PostgreSQL",
"application_role_reused_without_privilege_change": true,
"result": "passed",
"test_files": [
"CandidateSubmissionsTest",
"PeopleHiringTest",
"CandidatePortalTest",
"CandidateDocumentFormatsTest"
],
"original_evaluation_untouched": true,
"database_removed": true,
"tests": 64,
"assertions": 1401
}
@@ -0,0 +1,44 @@
{
"checked_at": "2026-10-30T19:15:14.138147+00:00",
"base_commit": "bf84575d10d9063c2224945e6d5627da826148a9",
"scope": [
"public published opportunity discovery before candidate registration",
"current publication deadline company and process scope",
"public content minimisation",
"shared public and authenticated pagination",
"authenticated application and document guards preserved"
],
"module_sqlite": {
"tests": 24,
"assertions": 374,
"passed": true
},
"postgresql": {
"tests": 64,
"assertions": 1401,
"passed": true,
"disposable_database_removed": true
},
"frontend": {
"tests": 10,
"passed": true
},
"typescript": true,
"phpstan_errors": 0,
"pint": true,
"targeted_lint": true,
"build": {
"exit_code": 0,
"completed": true
},
"full_suite": "reuse accepted bf84575 suite; not repeated",
"new_migrations": false,
"production_installed": false,
"visual_review": "blocked by unavailable native pipe and browser host",
"source_sha256": {
"app/Services/CandidateSubmissions.php": "63bebd4ccb04e9bc2ab19b0701567f082831814498e83cd7e9755ba2f550f6e4",
"app/Http/Controllers/CandidatePortalController.php": "e37a7df5933da0d9635e91180a027d1d00d5dd3d16efc15c8c36a3ad906f724d",
"resources/js/pages/candidate/entry.tsx": "1fb6c2f3ecd7153fe677c7c8164867df22f0cdc146c0bc32d6c82a0b61cd354e",
"resources/js/pages/candidate/profile.tsx": "3857fec4bb8c10164a13b710f95df916707ebb8e214a05117f1f530b0b7b34c5"
}
}