Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
351 commits
Select commit Hold shift + click to select a range
e6e6cd5
style(frontend): normalize formatting via editor format-on-save
Ochoa-Stack Jun 23, 2026
f2573ec
fix(frontend): keep skills chart legible on narrow viewports and add …
Ochoa-Stack Jun 23, 2026
46e5914
feat(frontend): build comparar.html structure with header, skill sele…
Ochoa-Stack Jun 23, 2026
ed93ab2
feat(frontend): implement compare flow with real API data, salary con…
Ochoa-Stack Jun 23, 2026
bab1d96
fix(frontend): keep skills chart legible on narrow viewports and add …
Ochoa-Stack Jun 23, 2026
2bba56c
fix(backend): require uppercase, number, and special character in pas…
Ochoa-Stack Jun 24, 2026
ccd1166
feat(backend): implement httpOnly cookie-based sessions with CSRF pro…
Ochoa-Stack Jun 24, 2026
972d29c
feat(frontend): generalize API client with credentials, POST support,…
Ochoa-Stack Jun 24, 2026
6883663
feat(frontend): build login and registration forms with live password…
Ochoa-Stack Jun 24, 2026
7f59a1b
feat(frontend): wire logout button to real session termination
Ochoa-Stack Jun 24, 2026
1f96bd5
Merge pull request #23 from Ochoa-Stack/feature/development-frontend-p2
Ochoa-Stack Jun 24, 2026
b8127b6
Merge pull request #24 from Ochoa-Stack/feature/development-frontend-p3
Ochoa-Stack Jun 24, 2026
54aed3c
feat(backend): add oauth_accounts table and make password_hash nullab…
Ochoa-Stack Jun 25, 2026
133cd72
feat(backend): implement Google Sign-In endpoint with automatic accou…
Ochoa-Stack Jun 25, 2026
56c772f
feat(frontend): add Google Sign-In button with FedCM and One Tap, and…
Ochoa-Stack Jun 25, 2026
0e2bfa9
fix(frontend): make [hidden] override component display rules and tog…
Ochoa-Stack Jun 25, 2026
887407d
fix(frontend): replace dead auth button with real link to register.html
Ochoa-Stack Jun 25, 2026
41d0216
Merge pull request #25 from Ochoa-Stack/feature/development-frontend-p4
Ochoa-Stack Jun 25, 2026
85e02d7
feat(auth): add password reset request and confirmation endpoints
Ochoa-Stack Jun 28, 2026
f2d05fa
fix(auth): reject login for OAuth-only accounts instead of raising
Ochoa-Stack Jun 28, 2026
1547c04
feat(auth): invalidate active sessions on password change
Ochoa-Stack Jun 28, 2026
2679a92
feat(frontend): add forgot and reset password screens
Ochoa-Stack Jun 28, 2026
8e82acf
Merge pull request #26 from Ochoa-Stack/feature/development-frontend-p5
Ochoa-Stack Jun 29, 2026
fafa350
fix(auth): remove obsolete GUEST value from role constraint
Ochoa-Stack Jun 29, 2026
5ccf137
feat(profile): add user_skills table for skill gap tracking
Ochoa-Stack Jun 29, 2026
1d4b612
feat(auth): add role-based access decorator
Ochoa-Stack Jun 30, 2026
1e1da7e
Merge pull request #27 from Ochoa-Stack/feature/user-skills-and-role-…
Ochoa-Stack Jun 30, 2026
0f0ad63
feat(profile): add profile endpoints with intent field and skill gap
Ochoa-Stack Jul 2, 2026
3ff5537
feat(frontend): add CSRF support and apiPatch/apiDelete to API client
Ochoa-Stack Jul 2, 2026
1d7d3e2
feat(frontend): add profile page with skill gap and security sections
Ochoa-Stack Jul 2, 2026
e45e2be
fix(frontend): fix carousel scroll bug and expand index layout for de…
Ochoa-Stack Jul 2, 2026
0fbfc99
Merge pull request #28 from Ochoa-Stack/feature/profile-and-skill-gap
Ochoa-Stack Jul 2, 2026
60913f7
feat(panorama): add category field to skills/top endpoint
Ochoa-Stack Jul 3, 2026
1a431fa
fix(frontend): color all tied top skills and add btn--sm variant
Ochoa-Stack Jul 3, 2026
94b1121
feat(frontend): add habilidades page with category and demand filters
Ochoa-Stack Jul 3, 2026
4a32ec1
feat(frontend): add salarios page and update navbar links across all …
Ochoa-Stack Jul 3, 2026
7ba39de
Merge pull request #29 from Ochoa-Stack/feature/navbar-pending-pages
Ochoa-Stack Jul 3, 2026
2867fa4
chore(gitignore): ignore rotated log files (*.log.*)
Ochoa-Stack Jul 5, 2026
e91a31b
feat(db): add email_verification_tokens table and users.email_verifie…
Ochoa-Stack Jul 5, 2026
485b6fe
fix(db): enforce NOT NULL and server default on users.created_at
Ochoa-Stack Jul 5, 2026
524f5e2
feat(email): add Resend email service with fail-fast config guard
Ochoa-Stack Jul 5, 2026
ab86d57
refactor(auth): decouple resend-verification schema from forgot-password
Ochoa-Stack Jul 5, 2026
21352ae
feat(auth): require email verification before login, split verify-ema…
Ochoa-Stack Jul 5, 2026
73029c6
feat(frontend): add verificar-correo view with four-state verificatio…
Ochoa-Stack Jul 5, 2026
2145af9
feat(frontend): remove auto-login on register, handle EMAIL_NOT_VERIF…
Ochoa-Stack Jul 5, 2026
9902d9e
Merge pull request #30 from Ochoa-Stack/feature/email-verification
Ochoa-Stack Jul 5, 2026
45c74cd
fix(repositories): remove redundant truncation, dedupe city lookup logic
Ochoa-Stack Jul 7, 2026
5f43ad4
feat(geocoding): add Nominatim client with rate limiting and query di…
Ochoa-Stack Jul 7, 2026
ba1da7c
feat(ingestion): geocode job locations via Nominatim, add ingest-jobs…
Ochoa-Stack Jul 7, 2026
5b3fc30
fix(trends): upsert snapshots by (skill_id, city_id, date) to prevent…
Ochoa-Stack Jul 7, 2026
d1755fb
feat(api): add group_by=state to /panorama/geo with is_fallback flag
Ochoa-Stack Jul 7, 2026
e0ecbbd
feat(frontend): add getGeoDistribution client for regional grouping
Ochoa-Stack Jul 7, 2026
6944706
feat(frontend): add regiones view with state-level demand distribution
Ochoa-Stack Jul 7, 2026
c97c70d
chore(navbar): link Regiones page across existing views
Ochoa-Stack Jul 7, 2026
39b1596
docs: document mandatory ingest-jobs then generate-snapshots sequence
Ochoa-Stack Jul 7, 2026
cee6c05
Merge pull request #31 from Ochoa-Stack/feature/nominatim-geocoding
Ochoa-Stack Jul 7, 2026
384e081
chore(cleanup): remove dead backend/clients duplicate and empty trend…
Ochoa-Stack Jul 8, 2026
2c7e543
Merge pull request #32 from Ochoa-Stack/chore/remove-dead-code
Ochoa-Stack Jul 8, 2026
a8bb858
refactor(auth): populate auth.api.js and auth.utils.js
Ochoa-Stack Jul 8, 2026
c8c67bd
refactor(auth): consume shared auth layer in verificar-correo.js
Ochoa-Stack Jul 8, 2026
461c303
refactor(auth): consume shared auth layer in verificar-correo.js
Ochoa-Stack Jul 8, 2026
00ed150
refactor(auth): consume shared auth layer in restablecer-contrasena.js
Ochoa-Stack Jul 8, 2026
16793b9
refactor(auth): consume shared auth layer in register.js
Ochoa-Stack Jul 8, 2026
2436bdd
Merge pull request #33 from Ochoa-Stack/refactor/auth-frontend-layer
Ochoa-Stack Jul 8, 2026
1f537b8
feat(navbar): resolve pending Reportes link across shared views
Ochoa-Stack Jul 8, 2026
d5c98f6
feat(reportes): add dedicated printable market report view
Ochoa-Stack Jul 8, 2026
ea33c1b
refactor(metrics): extract shared market metrics rendering
Ochoa-Stack Jul 8, 2026
7cb6144
Merge pull request #34 from Ochoa-Stack/feature/reportes-print
Ochoa-Stack Jul 8, 2026
4820cca
fix(alerts): rename user_alerts.threshold to threshold_value
Ochoa-Stack Jul 9, 2026
f7f25d2
fix(alerts): bind AlertRepository.model as a class attribute
Ochoa-Stack Jul 9, 2026
d5d7731
refactor(alerts): migrate alert emails from SendGrid to Resend
Ochoa-Stack Jul 9, 2026
6303143
feat(alerts): add evaluate-alerts CLI command
Ochoa-Stack Jul 9, 2026
ce03de0
Merge pull request #35 from Ochoa-Stack/feature/alerts-absolute-thres…
Ochoa-Stack Jul 9, 2026
3d27ec6
feat(alerts): add frontend logic for creating, listing, and deleting …
Ochoa-Stack Jul 9, 2026
73c948b
feat(alerts): add mobile-first styles with desktop two-column layout
Ochoa-Stack Jul 9, 2026
9dedacf
feat(alerts): add Alertas view
Ochoa-Stack Jul 9, 2026
70ec48a
feat(navbar): add Alertas link across shared views
Ochoa-Stack Jul 9, 2026
9d8ec05
Merge pull request #36 from Ochoa-Stack/feature/alerts-frontend
Ochoa-Stack Jul 9, 2026
1b201a9
feat(navbar): add profile access icon across shared views
Ochoa-Stack Jul 10, 2026
425040b
Merge pull request #37 from Ochoa-Stack/feature/navbar-profile-link
Ochoa-Stack Jul 10, 2026
9cd1a1d
fix(backup): repair three stacked bugs in the never-tested backup flow
Ochoa-Stack Jul 10, 2026
4e039c7
feat(auth): add real email delivery for password reset
Ochoa-Stack Jul 10, 2026
dec12c6
feat(auth): wire real email delivery into forgot_password
Ochoa-Stack Jul 10, 2026
c03390d
Merge pull request #38 from Ochoa-Stack/docs/backend-technical-audit
Ochoa-Stack Jul 11, 2026
6cc8971
feat(admin): add paginated backup/user listing, unify role check
Ochoa-Stack Jul 11, 2026
6f55a24
feat(admin): show Admin navbar link only for ADMIN role
Ochoa-Stack Jul 11, 2026
b029322
feat(admin): add Backups view with real pagination
Ochoa-Stack Jul 11, 2026
891e64c
fix(layout): reserve scrollbar space globally to prevent layout shift
Ochoa-Stack Jul 11, 2026
28283bb
feat(admin): add Users view (read-only) and admin sub-navigation
Ochoa-Stack Jul 11, 2026
20c7829
feat(admin): show real user email instead of Usuario #N in backups table
Ochoa-Stack Jul 11, 2026
d9ae2bc
Merge pull request #39 from Ochoa-Stack/feature/admin-panel
Ochoa-Stack Jul 12, 2026
00701fe
feat(users): add is_active column for soft-delete
Ochoa-Stack Jul 13, 2026
48a03e0
fix(users): restore created_at not null after unrelated autogenerate …
Ochoa-Stack Jul 13, 2026
bc412f4
feat(auth): revoke sessions for deactivated users
Ochoa-Stack Jul 13, 2026
36b969a
feat(admin): add role and status mutation endpoints with last-admin p…
Ochoa-Stack Jul 13, 2026
f53eee4
feat(admin): add role/status mutation controls to users panel
Ochoa-Stack Jul 13, 2026
8aae627
Merge pull request #40 from Ochoa-Stack/feature/active-user-management
Ochoa-Stack Jul 13, 2026
a5399ae
feat(jobs): harden created_at not null
Ochoa-Stack Jul 13, 2026
d103811
feat(trends): calculate growth_rate using 30-day activity window
Ochoa-Stack Jul 13, 2026
bd6cf90
feat(panorama): expose growth_rate in compare endpoint
Ochoa-Stack Jul 13, 2026
4b77985
Merge pull request #41 from Ochoa-Stack/feature/growth-rate-calculation
Ochoa-Stack Jul 13, 2026
aa21b4e
feat(alerts): add alert_type and threshold_percentage schema
Ochoa-Stack Jul 13, 2026
a0e5602
feat(alerts): validate threshold fields conditionally by alert_type
Ochoa-Stack Jul 13, 2026
815746b
fix(alerts): add get_active to filter out deactivated alerts
Ochoa-Stack Jul 13, 2026
b9cc10f
fix(alerts): filter active alerts and evaluate by type
Ochoa-Stack Jul 14, 2026
4f67a5b
feat(alerts): add conditional form for absolute vs trend alerts
Ochoa-Stack Jul 14, 2026
fdd298d
Merge pull request #42 from Ochoa-Stack/feature/trend-based-alerts
Ochoa-Stack Jul 14, 2026
ec4bdec
feat(backup): add restore with automatic safety backup
Ochoa-Stack Jul 14, 2026
a82696b
feat(backup): add restore endpoint with filename confirmation
Ochoa-Stack Jul 14, 2026
b3a6fc9
feat(backup): add restore UI with double-confirmation dialog
Ochoa-Stack Jul 14, 2026
6cf6575
Merge pull request #44 from Ochoa-Stack/feature/backup-restore
Ochoa-Stack Jul 14, 2026
f3388eb
fix(frontend): escape user-provided data before HTML injection
Ochoa-Stack Jul 15, 2026
986e234
docs(env): fix outdated SendGrid reference in RESEND_API_KEY comment
Ochoa-Stack Jul 15, 2026
0e45e6f
docs(setup): update environment guide with PostgreSQL and current dep…
Ochoa-Stack Jul 15, 2026
f63fc6f
Merge pull request #45 from Ochoa-Stack/fix/unescaped-html-rendering
Ochoa-Stack Jul 15, 2026
4cf957c
feat(errors): add global AppError handler and typed repository except…
Ochoa-Stack Jul 17, 2026
0d3bdbe
fix(auth): preserve anti-enumeration and fix exception ordering after…
Ochoa-Stack Jul 17, 2026
053fcc2
fix(backup): prevent secondary update failures from masking original …
Ochoa-Stack Jul 17, 2026
bf2af56
Merge pull request #46 from Ochoa-Stack/refactor/repository-error-han…
Ochoa-Stack Jul 17, 2026
5a67f2c
fix(core): add missing Limiter instance to extensions.py
Ochoa-Stack Jul 17, 2026
900f69e
Merge pull request #47 from Ochoa-Stack/feature/rate-limiting
Ochoa-Stack Jul 17, 2026
796a561
fix(admin): use row lock to prevent last-admin race condition
Ochoa-Stack Jul 17, 2026
52ea0af
fix(alerts): tighten constraint to reject cross-type threshold values
Ochoa-Stack Jul 17, 2026
eac4743
Merge pull request #48 from Ochoa-Stack/fix/admin-and-alert-integrity
Ochoa-Stack Jul 17, 2026
761cf6b
fix(categories): correct repository inheritance and seed base categories
Ochoa-Stack Jul 18, 2026
9508e35
feat(scripts): populate seed_db.py with example skills for local deve…
Ochoa-Stack Jul 18, 2026
c8e7b3f
docs(setup): document seed_db.py usage
Ochoa-Stack Jul 18, 2026
7b894bb
Merge pull request #49 from Ochoa-Stack/fix/category-seed-and-repository
Ochoa-Stack Jul 18, 2026
df9be65
feat(errors): add global 404 and 500 handlers for API consistency
Ochoa-Stack Jul 18, 2026
54fe6af
feat(errors): build 404 and 500 pages with context-aware back button
Ochoa-Stack Jul 18, 2026
a69e14a
Merge pull request #50 from Ochoa-Stack/feature/error-pages
Ochoa-Stack Jul 18, 2026
e601b00
feat(backup): add file_size_bytes column to backups table
Ochoa-Stack Jul 20, 2026
b961478
chore(deps): replace sendgrid with boto3
Ochoa-Stack Jul 20, 2026
d24107a
feat(storage): add Cloudflare R2 client via boto3
Ochoa-Stack Jul 20, 2026
ddc8fad
feat(backup): integrate R2 upload/download into backup flow
Ochoa-Stack Jul 20, 2026
a0a1a26
fix(storage): validate R2_BUCKET_NAME before creating client
Ochoa-Stack Jul 20, 2026
b516fd3
Merge pull request #51 from Ochoa-Stack/feature/backup-remote-storage
Ochoa-Stack Jul 20, 2026
ca82064
chore(testing): add pytest stack and configure TestingConfig for skil…
Ochoa-Stack Jul 21, 2026
a4fe36e
test(conftest): add app fixture and isolated db_session fixture
Ochoa-Stack Jul 21, 2026
0f218f8
test(foundation): verify environment sanity and transaction isolation
Ochoa-Stack Jul 21, 2026
dea4022
Merge pull request #52 from Ochoa-Stack/test/pytest-foundation
Ochoa-Stack Jul 21, 2026
7d2e377
fix(backup): auto-sync schema via flask db upgrade after restore
Ochoa-Stack Jul 21, 2026
6cd40c0
test(backup): cover execute_database_backup and restore_database_backup
Ochoa-Stack Jul 21, 2026
13af282
Merge pull request #53 from Ochoa-Stack/fix/auto-migrate-after-restore
Ochoa-Stack Jul 21, 2026
0f7fc10
test(backup): add integration coverage for backup and restore flows
Ochoa-Stack Jul 21, 2026
8bf2915
Merge pull request #54 from Ochoa-Stack/test/backup-restore-coverage
Ochoa-Stack Jul 21, 2026
039664b
test(auth): cover JWT revocation via is_active and password_changed_at
Ochoa-Stack Jul 21, 2026
e62bb79
test(auth): cover role_required authorization scenarios
Ochoa-Stack Jul 21, 2026
35c5184
fix(auth): return 401 instead of 403 when token user no longer exists
Ochoa-Stack Jul 21, 2026
a46f9a9
test(admin): cover last-admin protection logic (sequential)
Ochoa-Stack Jul 21, 2026
6679035
Merge pull request #55 from Ochoa-Stack/test/auth-admin-coverage
Ochoa-Stack Jul 21, 2026
0ca1189
fix(tests): restore original db.session on teardown, order schema-syn…
Ochoa-Stack Jul 22, 2026
e5d04c5
test(alerts): cover AlertRequestSchema conditional validation
Ochoa-Stack Jul 22, 2026
646a45c
test(alerts): cover evaluate_and_notify threshold logic and historica…
Ochoa-Stack Jul 22, 2026
8c619cd
test(alerts): cover alerts_bp endpoints (create, list, delete)
Ochoa-Stack Jul 23, 2026
7c6572b
Merge pull request #56 from Ochoa-Stack/test/alerts-coverage
Ochoa-Stack Jul 23, 2026
19eb87e
test(panorama): cover growth_rate calculation logic
Ochoa-Stack Jul 23, 2026
7495e29
test(panorama): cover panorama_bp read-only endpoints
Ochoa-Stack Jul 23, 2026
a73fe64
Merge pull request #57 from Ochoa-Stack/test/panorama-coverage
Ochoa-Stack Jul 23, 2026
8b0a7d9
feat(alerts): add PATCH /api/alerts/<id>/status endpoint
Ochoa-Stack Jul 23, 2026
bfb653a
test(alerts): cover PATCH /status endpoint end-to-end
Ochoa-Stack Jul 23, 2026
335cbfa
Merge pull request #58 from Ochoa-Stack/feature/alert-deactivation
Ochoa-Stack Jul 23, 2026
dc7ec9d
fix(tests): close leaked db.session for tests using client without db…
Ochoa-Stack Jul 24, 2026
a1a7ffd
test(auth): cover all auth_bp.py endpoints (Fase 5, no planeada origi…
Ochoa-Stack Jul 24, 2026
cd534b7
Merge pull request #59 from Ochoa-Stack/test/auth-endpoints-coverage
Ochoa-Stack Jul 24, 2026
a7f8f1e
feat(frontend): centralize API_BASE_URL in config.js
Ochoa-Stack Jul 24, 2026
8ab051f
feat(frontend): load config.js before client.js across all views
Ochoa-Stack Jul 24, 2026
dbb480d
refactor(scheduler): replace in-process APScheduler with on-demand tr…
Ochoa-Stack Jul 24, 2026
d5a3447
fix(tests): force RESEND_API_KEY test override, prevent real credenti…
Ochoa-Stack Jul 24, 2026
99c98d2
feat(pipeline): authenticate trigger-pipeline endpoint with dedicated…
Ochoa-Stack Jul 24, 2026
406b6d1
fix(config): isolate Windows lc_messages fix to Development/Testing, …
Ochoa-Stack Jul 25, 2026
9ebc548
feat(frontend): set production backend URL to skillstat.onrender.com
Ochoa-Stack Jul 25, 2026
43a5d5f
fix(frontend): normalize all internal navigation links to absolute /v…
Ochoa-Stack Jul 25, 2026
42025bb
fix(auth): use SameSite=None in production for cross-origin cookie su…
Ochoa-Stack Jul 25, 2026
c77af91
fix(frontend): add missing profile link to alertas.html navbar
Ochoa-Stack Jul 25, 2026
039086f
Merge pull request #60 from Ochoa-Stack/feature/deploy-preparation
Ochoa-Stack Jul 25, 2026
54d30a3
chore(docs): remove outdated duplicate GUIA_ENTORNO.md from root, kee…
Ochoa-Stack Jul 25, 2026
1adbddd
chore(license): add MIT license
Ochoa-Stack Jul 25, 2026
54085ff
fix(data): seed México Nacional fallback city (id=1) to prevent PK co…
Ochoa-Stack Jul 25, 2026
8223d82
Merge pull request #61 from Ochoa-Stack/chore/post-deploy-hygiene
Ochoa-Stack Jul 26, 2026
7639680
docs(adr): add ADR-001 and ADR-002
Ochoa-Stack Jul 26, 2026
901efab
docs(adr): add ADR-003 through ADR-007, link ADR-002 to ADR-005
Ochoa-Stack Jul 26, 2026
ab0611a
chore(docs): remove obsolete frontend diagnostic and empty propuesta …
Ochoa-Stack Jul 26, 2026
e01bcf0
docs(architecture): add entity-relationship diagram
Ochoa-Stack Jul 26, 2026
163d4c0
chore(docs): remove obsolete diagram placeholders
Ochoa-Stack Jul 27, 2026
32617e0
docs(architecture): add deployment diagram
Ochoa-Stack Jul 27, 2026
ef94234
docs(architecture): add alerts sequence diagram
Ochoa-Stack Jul 27, 2026
25eb844
docs(architecture): add use case diagrams (complete and high-level vi…
Ochoa-Stack Jul 27, 2026
5638282
docs(architecture): add class diagram
Ochoa-Stack Jul 27, 2026
54aafe1
docs(architecture): add components diagram
Ochoa-Stack Jul 27, 2026
6b874c6
Merge pull request #62 from Ochoa-Stack/docs/architecture-decision-re…
Ochoa-Stack Jul 27, 2026
382655a
ci(tests): add pytest coverage workflow with Codecov upload and ephem…
Ochoa-Stack Jul 27, 2026
c6b1767
fix(deps): remove duplicate pytest-cov from requirements.txt
Ochoa-Stack Jul 27, 2026
bbdd511
ci(tests): add missing required environment variables for flask db up…
Ochoa-Stack Jul 27, 2026
44b825b
fix(ci): correct env var name from DATABASE_URL to TEST_DATABASE_URL
Ochoa-Stack Jul 27, 2026
d3a2be8
fix(db): sync categories_id_seq after seed migration missing setval
Ochoa-Stack Jul 27, 2026
44e75f1
fix(tests): make _make_city idempotent against pre-seeded city id=1
Ochoa-Stack Jul 27, 2026
461127e
ci(tests): install postgresql-client-18 to match Neon server version
Ochoa-Stack Jul 27, 2026
6f3e82b
Merge pull request #64 from Ochoa-Stack/ci/pytest-coverage-codecov
Ochoa-Stack Jul 27, 2026
1ccdb30
fix(security): add rate limiting to reset-password and alert creation…
Ochoa-Stack Jul 28, 2026
8c6ae2e
Merge pull request #66 from Ochoa-Stack/fix/security-hardening-round-one
Ochoa-Stack Jul 28, 2026
1585e48
refactor(admin): extract last-admin protection into shared method
Ochoa-Stack Jul 29, 2026
0efb0c0
refactor(alerts): extract HTML template and add missing failure logging
Ochoa-Stack Jul 29, 2026
c940a94
refactor(backup): extract database connection parsing
Ochoa-Stack Jul 29, 2026
0249872
refactor(user-repo): remove unused count_active_admins, extract dupli…
Ochoa-Stack Jul 29, 2026
a5d09d1
test(city-repo): add characterization tests before refactor
Ochoa-Stack Jul 29, 2026
0cdf768
test(nominatim): add characterization tests before refactor
Ochoa-Stack Jul 29, 2026
591511b
fix(nominatim): replace personal email with GitHub noreply address in…
Ochoa-Stack Jul 29, 2026
444328a
test(ingestion): add characterization tests including documented is_r…
Ochoa-Stack Jul 29, 2026
e6d8465
fix(auth): add rate limiting to google login endpoint
Ochoa-Stack Jul 29, 2026
cc89cf2
refactor(city-repo): extract duplicated unicode normalization
Ochoa-Stack Jul 29, 2026
649f4f3
refactor(nominatim): decompose geocode_city into named steps
Ochoa-Stack Jul 29, 2026
272a9e4
fix(ingestion): scope is_remote detection to title and description wi…
Ochoa-Stack Jul 29, 2026
a761d9f
refactor(ingestion): extract is_remote computation and add backfill s…
Ochoa-Stack Jul 29, 2026
b313e15
Merge pull request #67 from Ochoa-Stack/refactor/backend-deduplicatio…
Ochoa-Stack Jul 30, 2026
0e7e213
feat(jobs): add remote column to Job model with migration
Ochoa-Stack Jul 31, 2026
48041cd
test(jobs): add characterization tests for remote column persistence
Ochoa-Stack Jul 31, 2026
5182fb9
fix(backfill): correct column reference from description to raw_descr…
Ochoa-Stack Jul 31, 2026
023a619
Merge pull request #68 from Ochoa-Stack/fix/add-remote-column-to-jobs
Ochoa-Stack Jul 31, 2026
e2b9c02
test(panorama): add query-count characterization test for get_compare
Ochoa-Stack Jul 31, 2026
74b1104
feat(repositories): add batch query methods for skills and trend snap…
Ochoa-Stack Jul 31, 2026
33d5f9f
refactor(panorama): resolve DT-26 N+1 in get_compare via PanoramaService
Ochoa-Stack Jul 31, 2026
301b2ca
feat(cities): add unaccent-based indexed city name search
Ochoa-Stack Jul 31, 2026
a9addce
refactor(cities): move geocoding orchestration to CityService
Ochoa-Stack Jul 31, 2026
a580fb9
test(cities): relocate get_or_create_city tests to CityService
Ochoa-Stack Aug 1, 2026
83e6c63
refactor(panorama): eliminate Fat Controller pattern across all endpo…
Ochoa-Stack Aug 1, 2026
6e6a9be
Merge pull request #69 from Ochoa-Stack/refactor/panorama-service-and…
Ochoa-Stack Aug 1, 2026
063acac
fix(backup): reset schema before restore instead of relying on pg_res…
Ochoa-Stack Aug 2, 2026
8a9f5c3
Merge pull request #70 from Ochoa-Stack/fix/backup-restore-schema-reset
Ochoa-Stack Aug 2, 2026
6659e10
refactor(auth): extract AuthService, consolidate /me, add Google acco…
Ochoa-Stack Aug 2, 2026
ee3e6b5
refactor(auth): add production guard for secret keys, remove dead imp…
Ochoa-Stack Aug 2, 2026
785592a
Merge pull request #71 from Ochoa-Stack/refactor/auth-service-consoli…
Ochoa-Stack Aug 2, 2026
173c229
feat(auth): add confirmation modal for Google account linking
Ochoa-Stack Aug 3, 2026
7cc5907
feat(catalog): show login prompt before redirect on unauthenticated a…
Ochoa-Stack Aug 3, 2026
d8b20e5
Merge pull request #72 from Ochoa-Stack/feature/frontend-auth-and-cat…
Ochoa-Stack Aug 3, 2026
cf785a9
fix(auth): implement lazy fetch for CSRF token to bypass PSL restrict…
Ochoa-Stack Aug 3, 2026
47fb54d
Merge pull request #73 from Ochoa-Stack/fix/csrf-cross-origin-cookie
Ochoa-Stack Aug 3, 2026
afe69fb
hotfix(auth): fix deadlock in ensureCsrfToken blocking all login flows
Ochoa-Stack Aug 3, 2026
e3a5358
Merge pull request #74 from Ochoa-Stack/hotfix/csrf-token-login-deadlock
Ochoa-Stack Aug 3, 2026
f9e586b
fix(navbar): ocultar iconos de sesion para invitados y agregar CTA de…
Ochoa-Stack Aug 7, 2026
007d965
fix(habilidades): marcar visualmente habilidades ya agregadas al usuario
Ochoa-Stack Aug 7, 2026
e476294
fix(auth): retomar intencion pendiente de invitado tras login
Ochoa-Stack Aug 7, 2026
443cdd8
refactor(ui): unificar logo completo y eliminar texto desglosado en t…
Ochoa-Stack Aug 7, 2026
533549a
Merge pull request #75 from Ochoa-Stack/fix/guest-session-state-consi…
Ochoa-Stack Aug 7, 2026
33805ad
style(ui): actualizar logo y favicons de la marca
Ochoa-Stack Aug 25, 2026
1561f88
Merge pull request #76 from Ochoa-Stack/fix/guest-session-state-consi…
Ochoa-Stack Aug 25, 2026
ffd2c3b
docs(readme): agregar documentacion completa del proyecto
Ochoa-Stack Sep 1, 2026
ec6c04a
feat(legal): agregar vista de aviso de cookies
Ochoa-Stack Sep 1, 2026
ef66cce
chore(editorconfig): definir reglas de formato del proyecto
Ochoa-Stack Sep 1, 2026
482f730
Merge pull request #77 from Ochoa-Stack/chore/repo-housekeeping-pre-main
Ochoa-Stack Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.py]
indent_style = space
indent_size = 4

[*.{js,html,css}]
indent_style = space
indent_size = 2
19 changes: 19 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Descripción
<!-- ¿Qué cambia y por qué? -->

## Tipo de cambio
- [ ] feat
- [ ] fix
- [ ] refactor
- [ ] chore
- [ ] docs
- [ ] test

## Cómo probar
<!-- Pasos para verificar que el cambio funciona correctamente -->

## Checklist
- [ ] Sigue las convenciones de commits del proyecto
- [ ] Las pruebas existentes pasan sin errores
- [ ] Se agregaron pruebas para el nuevo comportamiento (si aplica)
- [ ] No se incluyen archivos .env ni credenciales
1 change: 1 addition & 0 deletions .github/workflows/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

33 changes: 33 additions & 0 deletions .github/workflows/daily-pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Daily Pipeline

on:
# Disparo programado: todos los días a las 00:00 UTC.
schedule:
- cron: "0 0 * * *"

# Disparo manual desde la interfaz de GitHub para poder probar sin esperar al horario programado o depurar fallos.
workflow_dispatch:

jobs:
trigger-pipeline:
name: Trigger Daily Pipeline
runs-on: ubuntu-latest

steps:
- name: POST /api/admin/trigger-pipeline
run: |
HTTP_STATUS=$(curl --silent --output /tmp/pipeline_response.json \
--write-out "%{http_code}" \
--request POST \
--header "X-Pipeline-Trigger-Key: ${{ secrets.PIPELINE_TRIGGER_SECRET }}" \
--header "Content-Type: application/json" \
"${{ secrets.PIPELINE_BACKEND_URL }}/api/admin/trigger-pipeline")

echo "HTTP status: $HTTP_STATUS"
echo "Response body:"
cat /tmp/pipeline_response.json

if [ "$HTTP_STATUS" != "200" ]; then
echo "::error::El pipeline falló con HTTP $HTTP_STATUS. Ver el body de arriba para detalles."
exit 1
fi
84 changes: 84 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Tests

on:
push:
branches: [develop]
pull_request:
branches: [develop]

jobs:
test:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:18
env:
POSTGRES_USER: usuario
POSTGRES_PASSWORD: password
POSTGRES_DB: skillstat_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
working-directory: backend
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt

- name: Run database migrations
working-directory: backend
run: flask db upgrade
env:
FLASK_ENV: "testing"
SECRET_KEY: "test-secret-key"
TEST_DATABASE_URL: "postgresql://usuario:password@localhost:5432/skillstat_test"
JWT_SECRET_KEY: "test-jwt-secret"
GOOGLE_CLIENT_ID: "test-google-client-id"
FRONTEND_BASE_URL: "http://localhost:5500/frontend"
PIPELINE_TRIGGER_SECRET: "test-pipeline-secret"
RESEND_API_KEY: "test-resend-api-key"

- name: Install PostgreSQL 18 client tools
run: |
sudo apt-get install -y curl ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
sudo sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
sudo apt-get update
sudo apt-get install -y postgresql-client-18
pg_dump --version

- name: Run tests with coverage
working-directory: backend
run: pytest --cov=app --cov-report=xml
env:
FLASK_ENV: "testing"
SECRET_KEY: "test-secret-key"
TEST_DATABASE_URL: "postgresql://usuario:password@localhost:5432/skillstat_test"
JWT_SECRET_KEY: "test-jwt-secret"
GOOGLE_CLIENT_ID: "test-google-client-id"
FRONTEND_BASE_URL: "http://localhost:5500/frontend"
PIPELINE_TRIGGER_SECRET: "test-pipeline-secret"
RESEND_API_KEY: "test-resend-api-key"

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: backend/coverage.xml
fail_ci_if_error: false
45 changes: 45 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Python
__pycache__/
*.py[cod]
*.pyo
.Python
*.egg-info/
dist/
build/
.eggs/
venv/
.venv/
env/

# Environment
.env
.env.local
.env.*.local

# Database
*.db
*.sqlite3

# IDE
.vscode/
.idea/
*.swp
*.swo
.DS_Store
Thumbs.db

# Logs
*.log
logs/

# Testing
.pytest_cache/
.coverage
htmlcov/

# Migrations (solo rastrear estructura, no datos generados)
migrations/versions/
*.log.*

# Backups
backend/data/backups/*.sql
24 changes: 24 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Normativa de Colaboración y Desarrollo

Este documento establece las reglas operativas inquebrantables para el equipo de SkillStat. No son sugerencias, son requisitos para la integración de código.

## 1. Flujo de Git y Ramas
* **Ramas Protegidas:** `main` y `develop` están protegidas. Nadie hace un push directo a estas ramas bajo ninguna circunstancia.
* **Nomenclatura de Ramas:** Toda rama nueva se crea a partir de `develop` utilizando el formato: `tipo/descripcion-en-kebab-case` (ej. `feature/sqlalchemy-models`).
* **Integración:** Todo código entra a `develop` exclusivamente mediante un Pull Request revisado. No se deja deuda técnica sin corregir.

## 2. Historial y Commits (Conventional Commits)
Cada sub-ronda o bloque de trabajo debe ser un commit atómico. El mensaje debe seguir el estándar:
`tipo(scope): descripción en imperativo`
Tipos permitidos: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `perf`.

## 3. Convención Estricta de Comentarios en Código
Todo comentario debe explicar el **POR QUÉ**, nunca el **QUÉ**.
* **Regla:** Si el código no deja clara la intención por sí solo, refactoriza. Si la regla de negocio es compleja, se comenta el razonamiento.
* **Tono:** Primera persona del plural implícita en español. Sin tecnicismos innecesarios, sin emojis, sin numeración de pasos.
* **Correcto:** `Descartamos las vacantes ya procesadas para no duplicar los resultados.`
* **Incorrecto:** `Filtramos jobs / Función para filtrar`

## 4. Seguridad
* El archivo `.env` nunca se sube al repositorio.
* Las contraseñas se manejan siempre mediante hashes (bcrypt) y el acceso a rutas protegidas se valida estrictamente por roles mediante tokens JWT.
142 changes: 142 additions & 0 deletions INDUCCION_EQUIPO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Cómo trabajamos en SkillStat

Este documento describe cómo organizamos el trabajo, cómo nos comunicamos
a través del historial de cambios y cómo escribimos código. Lo leemos todos
antes de tocar cualquier archivo del repositorio.

## Ramas del repositorio

Tenemos dos ramas permanentes que nunca se modifican directamente:

- `main` - contiene el código que está en producción. Solo recibe cambios
desde `develop` a través de un Pull Request revisado y aprobado.
- `develop` - es la rama de trabajo activo del equipo. Aquí integramos
todo antes de que llegue a producción.

Para cualquier tarea nueva creamos una rama temporal que nace desde
`develop` y muere cuando hacemos merge:

| Tipo | Cuándo usarla | Ejemplo |
|------|---------------|---------|
| `feature/` | Funcionalidad nueva | `feature/jwt-authentication` |
| `fix/` | Corrección de error en desarrollo | `fix/city-normalization` |
| `hotfix/` | Corrección urgente en producción | `hotfix/token-exposure` |
| `refactor/` | Reorganización sin cambiar comportamiento | `refactor/ingestion-cleanup` |
| `chore/` | Mantenimiento, dependencias, configuración | `chore/update-requirements` |
| `docs/` | Documentación únicamente | `docs/guia-entorno` |
| `test/` | Pruebas nuevas o actualizadas | `test/trends-service-unit` |
| `release/` | Preparación de versión para producción | `release/v1.0.0` |

Los nombres van en minúsculas, con guiones y sin acentos.

## Flujo de trabajo paso a paso

Cada vez que vamos a trabajar en algo seguimos estos pasos:

```bash
# Nos aseguramos de que develop esté al día antes de empezar
git checkout develop
git pull origin develop

# Creamos nuestra rama desde develop
git checkout -b feature/nombre-descriptivo

# Trabajamos y guardamos nuestros avances en commits
git add .
git commit -m "feat(scope): descripcion del cambio"

# Mantenemos nuestra rama sincronizada con develop mientras trabajamos
git fetch origin
git rebase origin/develop

# Subimos nuestra rama y abrimos el Pull Request hacia develop
git push origin feature/nombre-descriptivo
```

Nadie toca `main` ni `develop` directamente. Todo pasa por un Pull Request.
Nadie hace merge de su propio trabajo sin que alguien más lo haya revisado.
Después del merge borramos la rama.

## Formato de commits

Cada commit sigue esta estructura:

```
tipo(alcance): descripcion breve en imperativo
```

Los tipos disponibles:

| Tipo | Cuándo usarlo |
|------|---------------|
| `feat` | Funcionalidad nueva |
| `fix` | Corrección de error |
| `docs` | Cambio de documentación |
| `style` | Formato sin cambio de lógica |
| `refactor` | Reorganización sin cambio de comportamiento |
| `test` | Agregar o modificar pruebas |
| `chore` | Mantenimiento, dependencias, configuración |
| `perf` | Mejora de rendimiento |

Ejemplos reales del proyecto:

```
feat(auth): implement JWT login and token validation
fix(nlp): resolve phrase matcher failure on multi-word skills
chore(deps): add Flask-JWT-Extended and spaCy to requirements
docs(contributing): add commit format and branching guide
test(trends): add unit tests for weekly growth rate calculation
refactor(ingestion): isolate Adzuna client from ingestion logic
```

## Cómo escribimos comentarios en el código

Comentamos solo cuando el código por sí solo no deja clara la intención
detrás de lo que hace. Si el código se entiende solo, no ponemos comentario.

El comentario explica el por qué, no el qué. El qué ya lo dice el código.

Escribimos en primera persona del plural, en español, sin tecnicismos,
sin emojis y sin numerar los pasos. Aplica a todos los lenguajes del
proyecto: Python, JavaScript, CSS e HTML.

Así escribimos:

```python
# Descartamos las vacantes que ya procesamos para no duplicar los resultados.
pending = jobs.filter(processed=False)

# Guardamos el hash para detectar si la descripcion cambio en la fuente original.
job.description_hash = compute_hash(raw_description)

# Si el umbral ya se supero avisamos al usuario antes de continuar.
if demand_count >= alert.threshold:
notify_user(alert)
```

```javascript
// Esperamos el token antes de hacer la peticion para no enviar una solicitud sin autenticar.
const token = await getAuthToken();

// Mostramos el mensaje directamente para que el usuario sepa que paso sin tener que buscar.
showErrorMessage(error.message);
```

Así no escribimos:

```python
# 1. Filtramos los jobs
# Funcion para filtrar vacantes usando ORM
# Filter unprocessed jobs from database
# 🔍 Buscamos vacantes sin procesar
```

## Reglas que no se negocian

- Nadie hace push directo a `main` ni a `develop`.
- Nadie hace merge de su propio Pull Request sin revision previa.
- Un commit representa un solo cambio logico. No mezclamos cosas distintas.
- No dejamos deuda tecnica sin documentar. Si algo quedo incompleto
abrimos un issue o lo anotamos en el PR.
- Si una rama lleva mas de una semana sin actividad, revisamos si sigue
siendo necesaria o la cerramos.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Elías Ochoa

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Binary file modified README.md
Binary file not shown.
Loading
Loading