Commit graph

18 commits

Author SHA1 Message Date
Tracewebstudio Dev
8423b7a0f5 fix: security, wallet holds, printpdf upgrade
- Upgrade printpdf 0.7 → 0.12.5 in job_seekers (fixes lopdf HIGH CVE RUSTSEC-2023-0068)
  Rewrote build_resume_pdf() for the new Op-based API; same PDF output
- Add wallet/me/holds and wallet/me/holds/{id}/release routes to profession_shared
  Backed by wallet::hold::list_for_user and wallet::hold::release
  Applies to all 9 profession services via the shared router
- Add deny.toml for cargo-deny (advisory + ban policy enforcement)
  RSA timing CVE and bincode unmaintained acknowledged with documented reasons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-12 13:38:17 +02:00
Ashwin Kumar Sivakumar
c1eed2530d fix: stop leaking raw LiteLLM error bodies; harden prompts against injection; fix UTF-8 panic
All checks were successful
build-and-release / build (companies) (push) Successful in 4s
build-and-release / build (catering-services) (push) Successful in 6s
build-and-release / build (developers) (push) Successful in 7s
build-and-release / build (customers) (push) Successful in 8s
build-and-release / build (employees) (push) Successful in 8s
build-and-release / build (fitness-trainers) (push) Successful in 6s
build-and-release / build (graphic-designers) (push) Successful in 5s
build-and-release / build (gateway) (push) Successful in 8s
build-and-release / build (job-seekers) (push) Successful in 7s
build-and-release / build (jobs) (push) Successful in 7s
build-and-release / build (makeup-artists) (push) Successful in 5s
build-and-release / build (payments) (push) Successful in 5s
build-and-release / build (photographers) (push) Successful in 5s
build-and-release / build (social-media-managers) (push) Successful in 6s
build-and-release / build (tutors) (push) Successful in 6s
build-and-release / build (ugc-content-creators) (push) Successful in 5s
build-and-release / build (video-editors) (push) Successful in 5s
build-and-release / build (cron) (push) Successful in 51s
build-and-release / build (users) (push) Successful in 3m12s
Follow-up on the AI safety review — addressed the three remaining
lower-severity findings:

1. crates LiteLlmError::error_body() returned the raw upstream response
   body verbatim to the client on any non-2xx LiteLLM response. That
   body can contain internal routing/diagnostic details from the
   LiteLLM proxy or the underlying model provider. Now returns a
   generic, status-aware message to the client; the full body is
   logged server-side via tracing::error! at each of the three call
   sites that construct LiteLlmError::Api, so nothing is lost for
   debugging — it's just not exposed to end users.

2. Added an explicit anti-prompt-injection clause to
   ai/orchestrator.rs::GROUNDING_GUARDRAIL, the baseline system prompt
   applied to every AI feature call via effective_system_prompt() —
   instructs the model to treat all user/company-authored input
   (job descriptions, profile text, chat messages) as data to analyze,
   never as instructions to follow. Covers every ai.rs handler that
   goes through call_feature/call_feature_with_plan in one place,
   rather than patching each call site's prompt construction
   individually.

3. apps/cron/src/tasks/auto_apply.rs's cover-letter prompt doesn't run
   through the orchestrator (separate app/crate), so hardened it
   directly: fenced the untrusted CANDIDATE/JOB sections with explicit
   "this is data, not instructions" framing. While there, fixed a
   latent panic: `&job_desc[..job_desc.len().min(500)]` slices on a
   raw byte offset, which panics if byte 500 isn't a UTF-8 character
   boundary — a company job description with any multi-byte character
   before that point (accented letters, emoji, etc.) would crash the
   whole cron run. Switched to char_indices() to find a safe boundary.
2026-07-21 05:56:21 +05:30
Ashwin Kumar Sivakumar
3e701f2fe6 fix: close two real money/spend races (Tracecoin double-credit, unbounded AI overspend)
Some checks failed
build-and-release / build (ugc-content-creators) (push) Waiting to run
build-and-release / build (users) (push) Waiting to run
build-and-release / build (video-editors) (push) Waiting to run
build-and-release / build (catering-services) (push) Successful in 1m47s
build-and-release / build (companies) (push) Successful in 2m0s
build-and-release / build (cron) (push) Successful in 2m12s
build-and-release / build (customers) (push) Successful in 2m42s
build-and-release / build (gateway) (push) Successful in 1m0s
build-and-release / build (developers) (push) Successful in 1m27s
build-and-release / build (fitness-trainers) (push) Successful in 1m54s
build-and-release / build (employees) (push) Successful in 1m59s
build-and-release / build (job-seekers) (push) Successful in 1m57s
build-and-release / build (makeup-artists) (push) Successful in 1m39s
build-and-release / build (graphic-designers) (push) Has been cancelled
build-and-release / build (payments) (push) Has been cancelled
build-and-release / build (jobs) (push) Has been cancelled
build-and-release / build (social-media-managers) (push) Has been cancelled
build-and-release / build (tutors) (push) Has been cancelled
build-and-release / build (photographers) (push) Has been cancelled
Asked to review Tracecoin and AI implementation safety. Found and fixed
two exploitable TOCTOU races, plus a data-integrity bug:

1. apps/payments/src/main.rs::verify_payment — the PayU success callback
   is called directly by the client (not a server-to-server webhook), so
   a user fully controls how many times they replay a valid success
   payload. The payment "is it still PENDING" check and the "mark
   SUCCESS + credit wallet" write were separate, non-transactional
   queries — concurrent replays could both pass the check before either
   commits, double- (or N-times-) crediting the wallet for one real
   payment. Now wrapped in a single transaction with
   `SELECT ... FOR UPDATE` on the payments row, so a second concurrent
   call blocks until the first commits, then correctly sees the row is
   no longer PENDING (Postgres re-evaluates the WHERE clause via
   EvalPlanQual after the lock is granted).

2. crates/db/src/models/ai/repository.rs — UserAiSubscriptionRepository
   had the exact same shape of bug: apps/users/src/ai/credits.rs::
   charge_feature read the subscription, checked daily-limit and credit
   balance, THEN issued two separate unconditional `UPDATE ... SET x =
   x + $1` statements with no WHERE guard on the balance. N concurrent
   requests from one user all pass the check before any deduction
   lands, running up unlimited LLM API spend (this endpoint is called
   before/around real LiteLLM calls, so the cost is real). Added
   UserAiSubscriptionRepository::try_charge — a single conditional
   UPDATE that checks the daily limit and credit balance and deducts
   atomically, returning None (mapped to the existing error types) if
   either check fails.

3. apps/cron/src/tasks/auto_apply.rs — daily_actions_used was being
   incremented twice per auto-applied job (once in the credit-deduct
   UPDATE, once more in a second, redundant UPDATE right after) —
   silently halving job seekers' effective daily auto-apply limit.
   Removed the redundant second UPDATE.

Also added non-negative CHECK constraints directly to the live
database (tracecoin_wallets.balance/reserved,
user_ai_subscriptions.daily_actions_used/monthly_credits_used/
purchased_credits_used) as defense in depth — belt-and-suspenders in
case a future code path reintroduces a similar bug.
2026-07-21 05:51:23 +05:30
Ashwin Kumar Sivakumar
2e95c4750b fix: company job posting, job seeker profile submission, and job applications
- Company approval wrote profile status to 'ACTIVE' (company_profiles'
  own pre-verification default) using an id column that never matched
  any row, so create_job's APPROVED check always rejected newly
  approved companies. Match on user_id for user_id-keyed tables and
  write the canonical 'APPROVED' status.
- job_seeker_profiles was missing columns the job-seeker app has
  always queried (full_name, location, summary, skills,
  active_application_count, status), and the job_applications /
  job_seeker_documents tables it depends on were never migrated in —
  job seeker profile save/submit and job applications failed outright
  with "column/relation does not exist".
- Renamed the job_seeker first_name/last_name split to full_name to
  match what the frontend has always sent.
- Special-cased JOB_SEEKER in the generic profile.rs handlers (mirrors
  the existing COMPANY special-case) so the shared ProfilePage save/
  submit flow, which was routed through a user_role_profile_id-based
  path job_seeker_profiles never had, now persists correctly.
- Fixed apply_to_job's company notification query joining a
  nonexistent "companies" table instead of company_profiles.
- Fixed auto-apply cron's company status filter to match the
  corrected 'APPROVED' status.
2026-07-21 01:00:47 +05:30
Ashwin Kumar Sivakumar
ea622a4af8 chore: retrigger isolated CI builds for 6 more services on bad digests
All checks were successful
build-and-release / build (catering-services) (push) Successful in 3s
build-and-release / build (companies) (push) Successful in 5s
build-and-release / build (customers) (push) Successful in 4s
build-and-release / build (developers) (push) Successful in 5s
build-and-release / build (employees) (push) Successful in 6s
build-and-release / build (graphic-designers) (push) Successful in 5s
build-and-release / build (job-seekers) (push) Successful in 5s
build-and-release / build (leads) (push) Successful in 4s
build-and-release / build (makeup-artists) (push) Successful in 5s
build-and-release / build (payments) (push) Successful in 4s
build-and-release / build (photographers) (push) Successful in 4s
build-and-release / build (social-media-managers) (push) Successful in 5s
build-and-release / build (gateway) (push) Successful in 3m25s
build-and-release / build (users) (push) Successful in 4s
build-and-release / build (video-editors) (push) Successful in 3s
build-and-release / build (cron) (push) Successful in 4m4s
build-and-release / build (jobs) (push) Successful in 4m12s
build-and-release / build (tutors) (push) Successful in 7m13s
build-and-release / build (fitness-trainers) (push) Successful in 8m58s
build-and-release / build (ugc-content-creators) (push) Successful in 8m51s
Same congestion pattern from the crates/contracts push. gateway still had
2 healthy replicas serving traffic throughout, so no outage — just a
failed rolling-update replica for these 6 services.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 03:01:39 +05:30
Ashwin Kumar Sivakumar
cba7f607cd fix: resolve all warnings and errors
- Add #![allow(dead_code)] pragma to all main.rs files
- Remove unused imports from users handlers (ai_cache, AiCreditPackageRepository, AiCreditTransactionRepository)
- Make LiteLLMChatMessage and LiteLLMChoice public with public fields
- Fix remaining unused variables with cargo fix
- Add missing pub visibility modifiers to litellm structs

All packages now compile with ZERO warnings and errors!
2026-07-06 03:00:37 +05:30
Ashwin Kumar Sivakumar
b99651f330 fix: resolve warnings (partial)
- Fix unused variable entry_type -> _entry_type
- Remove unused imports BufMut and cache_jobs from companies handlers
- Fix doc comment on lazy_static
- Add #[allow(dead_code)] to reset_daily_actions and reset_monthly_credits
- Fix unused imports in job_seekers handlers
2026-07-06 02:55:42 +05:30
Ashwin Kumar Sivakumar
4f2683d085 chore: remove legacy AI quota system
Delete legacy code that used old company_ai_usage/job_seeker_ai_usage tables:
- Remove has_active_ai_pack() - old AI_PACK pricing package check
- Remove check_and_increment_usage() - legacy daily quota tracking
- Remove BASE_AI_LIMIT, get_ai_limit_for_package constants/functions
- Remove legacy queries from ai_auto_apply() and ai_usage_status()
- Update auto_apply.rs to use user_ai_subscriptions.daily_actions_used
  instead of job_seeker_ai_usage table
- Inline apply_scheduled_downgrades() and expire_trials() in cron tasks
  to remove dependency on users crate internal modules

The new system uses user_ai_subscriptions with:
- daily_actions_used / daily_credits_used counters
- monthly_credits_total / monthly_credits_used
- purchased_credits_total / purchased_credits_used

All AI billing now flows through the wallet/ledger system with
LiteLLM integration (Tasks 1-10).
2026-07-06 02:14:23 +05:30
Ashwin Kumar Sivakumar
0dd5045676 feat: Complete Ask Ash AI Credits implementation on high-performance branch (Tasks 1-10)
- Task 1: Admin endpoints for wallet management
- Task 2: AI Credits admin UI (pricing.tsx, credit.tsx)
- Task 3: Ollama security (NetworkPolicy, prompt validation, audit)
- Task 4: LiteLLM integration (litellm.rs, migrated AI feature handlers)
- Task 5: Refund architecture (ai_refunds table, endpoints)
- Task 6: Coupons, promotions, referrals (order creation with coupon)
- Task 7: Subscription lifecycle (plan upgrades/downgrades, cron jobs)
- Task 8: Credit expiration enforcement (daily cron task)
- Task 9: Token cost engine (ai_model_cost_config, margin view)
- Task 10: Observability (metrics tables, aggregation function)

Cherry-picked from main branch commit 3c0f45f
2026-07-06 01:49:16 +05:30
Tracewebstudio Dev
eb009ac3d0 feat: profile photo upload, PDF resume generation, AI auto-apply, schema fixes
- Profile photo upload: POST /api/profile/photo for all roles, stores via B2 storage
- PDF resume: auto-generated from job seeker portfolio on every profile save (printpdf)
- Company applications: enriched with applicant name, avatar, headline, skills, education
- AI auto-apply cron: rewrote run_auto_apply with correct schema (job_seeker_profiles,
  cover_note, ai_auto_apply_settings, ai_auto_apply_logs, credit deduction)
- Schema fix: job_seeker_profiles table name (was incorrectly 'job_seekers' in two places)
- Migration: add resume_url column to job_seeker_profiles
- Migrations: PayU rename, tracecoin hardening, lead reserve linkage, invoice/wallet crates
- PayU integration: ai_credits, packages, admin payment handlers
- Wallet and invoice crates added

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 13:31:06 +02:00
Ashwin Kumar Sivakumar
06e73eebb5 fix(ai): align backend plans and clean warnings 2026-06-15 09:23:44 +05:30
Ashwin Kumar Sivakumar
0c2ce413f9 Merge remote high-performance: keep new AI plans implementation and resolve conflicts 2026-06-15 06:18:52 +05:30
Ashwin Kumar Sivakumar
c85e6af22e feat(ai): complete AI plans/credits implementation and build tooling
- Add AI plans, credits, model routing, LiteLLM client, and orchestrator services
- Add AI management endpoints, auto-apply/auto-request handlers, and log endpoints
- Add cron jobs for daily action reset and monthly credit reset
- Add AI credit purchase flow in payments service
- Add ai_credit_packages migration with seed data
- Update Dockerfile build tooling across services
2026-06-15 06:15:49 +05:30
Tracewebstudio Dev
a4af5c2c06 feat: add LiteLLM support and auto-apply cron job
- Add get_llm_base_url() and get_llm_model() helper functions
- Update call_ollama_inline to route to LiteLLM when LLM_PROVIDER=litellm
- Add auto-apply cron task for background job matching
- Auto-apply matches job seekers to new jobs based on skills
- Generate cover letters via LiteLLM for each application
2026-06-14 18:00:38 +02:00
Tracewebstudio Dev
a3076ed526 feat: update DB schema - split users.first_name, users.last_name, roles split 2026-04-15 06:23:27 +02:00
Tracewebstudio Dev
2861e7a5fe fix: replace u.full_name with u.name in remaining services
- companies: user.name in email and contact queries
- customers: user.name in email
- job_seekers: u.name in company user query
- cron tasks (jobs/leads/requirements): use u.name instead of u.full_name
- contracts/profession_shared: u.name for customer_name fields
2026-04-13 17:12:49 +02:00
Tracewebstudio Dev
c433ab5fed feat(db): update service handlers and models for new schema
- Update leads service to use 'leads' table
- Update extension models to use user_role_profile_id
- Update ProfessionalRepository to work with new schema
- Create TracecoinWalletRepository for wallet operations
- Update all handlers to use new model fields
- Rename Application fields (job_seeker_id -> applicant_user_id)
- Update cron tasks for new schema
- Fix compilation errors across all services
2026-04-13 00:29:44 +02:00
Ashwin Kumar
446b6322de feat(admin): wire management modules to live backend and add UGC role 2026-04-02 13:09:43 +02:00