Commit graph

450 commits

Author SHA1 Message Date
Ashwin Kumar Sivakumar
b9133018a5 fix(admin-auth): add rate limiting to admin login endpoint
All checks were successful
build-and-release / build (makeup-artists) (push) Successful in 8m13s
build-and-release / build (cron) (push) Successful in 4m39s
build-and-release / build (gateway) (push) Successful in 2m47s
build-and-release / build (employees) (push) Successful in 8m49s
build-and-release / build (fitness-trainers) (push) Successful in 7m42s
build-and-release / build (payments) (push) Successful in 8m6s
build-and-release / build (jobs) (push) Successful in 4m19s
build-and-release / build (catering-services) (push) Successful in 9m29s
build-and-release / build (photographers) (push) Successful in 8m44s
build-and-release / build (customers) (push) Successful in 9m30s
build-and-release / build (tutors) (push) Successful in 7m8s
build-and-release / build (developers) (push) Successful in 9m35s
build-and-release / build (graphic-designers) (push) Successful in 9m33s
build-and-release / build (social-media-managers) (push) Successful in 8m57s
build-and-release / build (leads) (push) Successful in 9m9s
build-and-release / build (ugc-content-creators) (push) Successful in 8m52s
build-and-release / build (video-editors) (push) Successful in 8m14s
build-and-release / build (companies) (push) Successful in 9m58s
build-and-release / build (job-seekers) (push) Successful in 9m55s
build-and-release / build (users) (push) Successful in 10m21s
The admin/employee login handler had no brute-force protection, unlike
the regular user login path. Given these accounts hold internal/
super-admin privileges, add a tighter limit (5 attempts/15min vs 10
for regular users) using the existing sliding-window Redis limiter.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 16:12:52 +05:30
Ashwin Kumar Sivakumar
e53098728a refactor(companies): remove local-disk fallback from submit_with_documents — B2 only
All checks were successful
build-and-release / build (social-media-managers) (push) Successful in 4s
build-and-release / build (ugc-content-creators) (push) Successful in 4s
build-and-release / build (users) (push) Successful in 4s
build-and-release / build (companies) (push) Successful in 6m14s
build-and-release / build (developers) (push) Successful in 7s
build-and-release / build (fitness-trainers) (push) Successful in 3s
build-and-release / build (catering-services) (push) Successful in 13s
build-and-release / build (customers) (push) Successful in 12s
build-and-release / build (cron) (push) Successful in 15s
build-and-release / build (employees) (push) Successful in 14s
build-and-release / build (makeup-artists) (push) Successful in 4s
build-and-release / build (gateway) (push) Successful in 3s
build-and-release / build (graphic-designers) (push) Successful in 4s
build-and-release / build (jobs) (push) Successful in 4s
build-and-release / build (job-seekers) (push) Successful in 4s
build-and-release / build (leads) (push) Successful in 4s
build-and-release / build (payments) (push) Successful in 4s
build-and-release / build (tutors) (push) Successful in 4s
build-and-release / build (video-editors) (push) Successful in 4s
build-and-release / build (photographers) (push) Successful in 4s
2026-07-11 02:13:56 +05:30
Ashwin Kumar Sivakumar
a019f86477 feat(companies): add /profile/submit-with-documents endpoint with local-disk fallback for B2 outages
All checks were successful
build-and-release / build (cron) (push) Successful in 14s
build-and-release / build (graphic-designers) (push) Successful in 3s
build-and-release / build (jobs) (push) Successful in 4s
build-and-release / build (job-seekers) (push) Successful in 6s
build-and-release / build (leads) (push) Successful in 4s
build-and-release / build (customers) (push) Successful in 7s
build-and-release / build (makeup-artists) (push) Successful in 3s
build-and-release / build (payments) (push) Successful in 4s
build-and-release / build (photographers) (push) Successful in 3s
build-and-release / build (catering-services) (push) Successful in 9s
build-and-release / build (tutors) (push) Successful in 5s
build-and-release / build (ugc-content-creators) (push) Successful in 4s
build-and-release / build (social-media-managers) (push) Successful in 6s
build-and-release / build (users) (push) Successful in 4s
build-and-release / build (fitness-trainers) (push) Successful in 4s
build-and-release / build (video-editors) (push) Successful in 3s
build-and-release / build (developers) (push) Successful in 13s
build-and-release / build (gateway) (push) Successful in 4s
build-and-release / build (companies) (push) Successful in 6m38s
build-and-release / build (employees) (push) Successful in 13s
2026-07-11 01:31:03 +05:30
Ashwin Kumar Sivakumar
5fa1f8f74c fix(profile): persist all COMPANY profile fields, not just company_name
All checks were successful
build-and-release / build (developers) (push) Successful in 7s
build-and-release / build (video-editors) (push) Successful in 4s
build-and-release / build (companies) (push) Successful in 10s
build-and-release / build (fitness-trainers) (push) Successful in 3s
build-and-release / build (users) (push) Successful in 7m44s
build-and-release / build (cron) (push) Successful in 15s
build-and-release / build (customers) (push) Successful in 13s
build-and-release / build (employees) (push) Successful in 12s
build-and-release / build (gateway) (push) Successful in 3s
build-and-release / build (catering-services) (push) Successful in 16s
build-and-release / build (graphic-designers) (push) Successful in 4s
build-and-release / build (job-seekers) (push) Successful in 4s
build-and-release / build (jobs) (push) Successful in 5s
build-and-release / build (makeup-artists) (push) Successful in 4s
build-and-release / build (leads) (push) Successful in 4s
build-and-release / build (payments) (push) Successful in 5s
build-and-release / build (photographers) (push) Successful in 4s
build-and-release / build (social-media-managers) (push) Successful in 4s
build-and-release / build (tutors) (push) Successful in 3s
build-and-release / build (ugc-content-creators) (push) Successful in 4s
2026-07-10 14:27:15 +05:30
Ashwin Kumar Sivakumar
9d475858ab fix(auth): default role assignment to APPROVED at signup
All checks were successful
build-and-release / build (fitness-trainers) (push) Successful in 3s
build-and-release / build (catering-services) (push) Successful in 13s
build-and-release / build (customers) (push) Successful in 12s
build-and-release / build (gateway) (push) Successful in 4s
build-and-release / build (employees) (push) Successful in 14s
build-and-release / build (graphic-designers) (push) Successful in 3s
build-and-release / build (cron) (push) Successful in 16s
build-and-release / build (job-seekers) (push) Successful in 5s
build-and-release / build (jobs) (push) Successful in 3s
build-and-release / build (leads) (push) Successful in 5s
build-and-release / build (payments) (push) Successful in 3s
build-and-release / build (makeup-artists) (push) Successful in 5s
build-and-release / build (photographers) (push) Successful in 5s
build-and-release / build (tutors) (push) Successful in 4s
build-and-release / build (social-media-managers) (push) Successful in 4s
build-and-release / build (ugc-content-creators) (push) Successful in 5s
build-and-release / build (video-editors) (push) Successful in 4s
build-and-release / build (users) (push) Successful in 7m30s
build-and-release / build (companies) (push) Successful in 9s
build-and-release / build (developers) (push) Successful in 8s
Roles assigned at registration are immediately active for login + session.
Document/profile approval (handled separately by user_role_profiles in
onboarding/verifications) is the correct gate for review workflows —
do not gate raw role assignment on that flow.

Previously defaulted to PENDING for non-demo accounts, which get filtered
out by get_user_role_keys (WHERE status = 'APPROVED') and produced JWTs
with empty roles, causing the 'role is not assigned' UX bug after login.
2026-07-09 23:41:49 +05:30
Ashwin Kumar Sivakumar
f7d0f6f9f5 fix: Update Dockerfiles to use ci.nxtgauge.com registry
Some checks failed
build-and-release / build (companies) (push) Failing after 39s
build-and-release / build (catering-services) (push) Failing after 57s
build-and-release / build (cron) (push) Failing after 1m4s
build-and-release / build (gateway) (push) Successful in 3m46s
build-and-release / build (fitness-trainers) (push) Successful in 9m8s
build-and-release / build (graphic-designers) (push) Successful in 8m58s
build-and-release / build (employees) (push) Successful in 9m17s
build-and-release / build (customers) (push) Successful in 9m47s
build-and-release / build (developers) (push) Successful in 9m48s
build-and-release / build (job-seekers) (push) Successful in 9m1s
build-and-release / build (jobs) (push) Successful in 4m17s
build-and-release / build (leads) (push) Successful in 8m23s
build-and-release / build (makeup-artists) (push) Successful in 8m40s
build-and-release / build (payments) (push) Successful in 9m21s
build-and-release / build (photographers) (push) Successful in 9m20s
build-and-release / build (social-media-managers) (push) Successful in 8m9s
build-and-release / build (tutors) (push) Successful in 8m16s
build-and-release / build (ugc-content-creators) (push) Successful in 6m59s
build-and-release / build (video-editors) (push) Successful in 6m9s
build-and-release / build (users) (push) Successful in 8m37s
2026-07-08 03:37:18 +05:30
Ashwin Kumar Sivakumar
8a8372850f perf(ci): settle on capacity 2/node x 3 workers = 6 concurrent slots
All checks were successful
build-and-release / build (catering-services) (push) Successful in 9m29s
build-and-release / build (cron) (push) Successful in 4m33s
build-and-release / build (gateway) (push) Successful in 2m57s
build-and-release / build (companies) (push) Successful in 8m56s
build-and-release / build (customers) (push) Successful in 8m53s
build-and-release / build (developers) (push) Successful in 9m8s
build-and-release / build (employees) (push) Successful in 9m8s
build-and-release / build (fitness-trainers) (push) Successful in 8m27s
build-and-release / build (jobs) (push) Successful in 3m48s
build-and-release / build (graphic-designers) (push) Successful in 8m36s
build-and-release / build (social-media-managers) (push) Successful in 7s
build-and-release / build (tutors) (push) Successful in 6s
build-and-release / build (job-seekers) (push) Successful in 9m5s
build-and-release / build (leads) (push) Successful in 9m12s
build-and-release / build (makeup-artists) (push) Successful in 9m10s
build-and-release / build (video-editors) (push) Successful in 9s
build-and-release / build (payments) (push) Successful in 8m42s
build-and-release / build (photographers) (push) Successful in 8m32s
build-and-release / build (ugc-content-creators) (push) Successful in 8m44s
build-and-release / build (users) (push) Successful in 9m58s
capacity=3/node (9 total) oversubscribed the 8 physical cores per
node - individual builds slowed roughly 3x under contention (observed
directly: builds that took ~2m37s standalone were still running after
8+ minutes), for no clear net throughput win since this workload is
CPU-bound. Also found and fixed the actual reason capacity wasn't
taking effect at all initially: the runner daemon command never
passed --config, so it was silently running on default settings
regardless of config.yaml. Settled on 2/node (6 total, matching
docker-ready runner-2/3/4 - the control-plane node nxtgauge-1 is
deliberately excluded from the runner DaemonSet and should stay that
way, not used for build load).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 02:43:46 +05:30
Ashwin Kumar Sivakumar
ba1b0ebcc0 fix(ci): raise max-parallel to 9, make gitops push failures actually fail the job
Some checks failed
build-and-release / build (cron) (push) Successful in 3m8s
build-and-release / build (gateway) (push) Successful in 5m7s
build-and-release / build (jobs) (push) Successful in 6m39s
build-and-release / build (payments) (push) Failing after 2m34s
build-and-release / build (graphic-designers) (push) Failing after 7m40s
build-and-release / build (job-seekers) (push) Failing after 7m38s
build-and-release / build (employees) (push) Failing after 8m8s
build-and-release / build (developers) (push) Failing after 8m10s
build-and-release / build (fitness-trainers) (push) Failing after 8m6s
build-and-release / build (leads) (push) Failing after 7m54s
build-and-release / build (photographers) (push) Failing after 1m17s
build-and-release / build (makeup-artists) (push) Failing after 7m52s
build-and-release / build (customers) (push) Failing after 13m56s
build-and-release / build (companies) (push) Failing after 17m4s
build-and-release / build (catering-services) (push) Failing after 17m5s
build-and-release / build (tutors) (push) Successful in 9m19s
build-and-release / build (social-media-managers) (push) Successful in 9m26s
build-and-release / build (ugc-content-creators) (push) Successful in 9m36s
build-and-release / build (video-editors) (push) Successful in 9m37s
build-and-release / build (users) (push) Successful in 12m26s
Bumped runner.capacity from 1 to 3 on all 3 runner pods (9 total
concurrent slots - nodes were sitting at 7-11% CPU during builds, so
plenty of headroom), matched here with max-parallel: 9.

Also fixed a real bug: the gitops-push retry loop had no check after
exhausting all attempts, so a job whose every push attempt failed
would still exit 0 and report "success" - which is exactly what
happened on the previous run (verified: all 20 services built and
pushed their images correctly, but the actual GITOPS_PAT secret was
invalid/expired, and the retry loop silently swallowed the resulting
failure across all 20 jobs). Fixed the secret itself (confirmed the
existing admin-scoped Forgejo token has valid push access to
ashwin/nxtgauge-gitops and rotated GITOPS_PAT to it), and added an
explicit exit 1 if the retry loop exhausts without a successful push.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 02:30:36 +05:30
Ashwin Kumar Sivakumar
9efb733974 fix(ci): use GITOPS_PAT instead of never-configured GITOPS_PUSH_TOKEN
All checks were successful
build-and-release / build (catering-services) (push) Successful in 49s
build-and-release / build (cron) (push) Successful in 49s
build-and-release / build (developers) (push) Successful in 39s
build-and-release / build (employees) (push) Successful in 38s
build-and-release / build (fitness-trainers) (push) Successful in 38s
build-and-release / build (gateway) (push) Successful in 38s
build-and-release / build (graphic-designers) (push) Successful in 38s
build-and-release / build (job-seekers) (push) Successful in 39s
build-and-release / build (jobs) (push) Successful in 39s
build-and-release / build (leads) (push) Successful in 39s
build-and-release / build (makeup-artists) (push) Successful in 39s
build-and-release / build (companies) (push) Successful in 6m56s
build-and-release / build (payments) (push) Successful in 39s
build-and-release / build (customers) (push) Successful in 6m33s
build-and-release / build (social-media-managers) (push) Successful in 39s
build-and-release / build (ugc-content-creators) (push) Successful in 39s
build-and-release / build (users) (push) Successful in 39s
build-and-release / build (video-editors) (push) Successful in 39s
build-and-release / build (photographers) (push) Successful in 6m28s
build-and-release / build (tutors) (push) Successful in 6m32s
Confirmed via the matrix run: every service's actual docker build and
push succeeded, but the GitOps-update step failed on all of them with
"GITOPS_PUSH_TOKEN is empty". Checked the repo's configured secrets -
GITOPS_PUSH_USERNAME/GITOPS_PUSH_TOKEN were never set; only a leftover
GITOPS_GITHUB_USERNAME/GITOPS_GITHUB_TOKEN pair (from before the
gitops repo moved to Forgejo) and GITOPS_PAT exist. Confirmed
ashwin/nxtgauge-gitops lives on ci.nxtgauge.com matching this
workflow's defaults, so GITOPS_PAT is the one meant for this.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 02:10:33 +05:30
Ashwin Kumar Sivakumar
e8651cf6c6 perf(ci): parallelize service builds across all 3 runners via matrix strategy
Some checks failed
build-and-release / build (companies) (push) Failing after 8s
build-and-release / build (customers) (push) Failing after 7s
build-and-release / build (developers) (push) Failing after 7s
build-and-release / build (employees) (push) Failing after 7s
build-and-release / build (fitness-trainers) (push) Failing after 8s
build-and-release / build (gateway) (push) Failing after 7s
build-and-release / build (graphic-designers) (push) Failing after 7s
build-and-release / build (job-seekers) (push) Failing after 8s
build-and-release / build (jobs) (push) Failing after 7s
build-and-release / build (leads) (push) Failing after 6s
build-and-release / build (makeup-artists) (push) Failing after 7s
build-and-release / build (payments) (push) Failing after 8s
build-and-release / build (photographers) (push) Failing after 7s
build-and-release / build (social-media-managers) (push) Failing after 7s
build-and-release / build (tutors) (push) Failing after 7s
build-and-release / build (ugc-content-creators) (push) Failing after 8s
build-and-release / build (users) (push) Failing after 7s
build-and-release / build (video-editors) (push) Failing after 7s
build-and-release / build (cron) (push) Failing after 3m19s
build-and-release / build (catering-services) (push) Failing after 5m54s
The build was structured as a single job looping through all ~20
services sequentially, so only 1 of the 3 deployed runner pods (one
per worker node) was ever used - the other 2 sat idle for the entire
build. Switched to a static per-service matrix (max-parallel: 3,
matching the 3 runners at capacity 1 each) so independent services
build concurrently. Each matrix job does its own quick "does this
service need building" check up front (same change-detection logic,
now per-job) rather than relying on a shared job output, to avoid
needing cross-job artifact/output passing.

GitOps updates also move into each matrix job (previously a single
step at the end) since there's no longer one job aggregating all
results - added a fetch/reset/retry loop since multiple jobs can now
push to the same gitops branch concurrently.

Tried adding cargo registry/target cache mounts to Dockerfile.simple
for a bigger per-build win too, but measured it directly (local A/B:
cold build 2m37s vs a second, supposedly-cached build 7m18s) and it
made things slower here, likely cargo's own cache-verification pass
outweighing the benefit for this dependency set - reverted that part,
Dockerfile.simple is unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 01:54:47 +05:30
Ashwin Kumar Sivakumar
968960fb3d fix(ci): tolerate buildx's pretty-printed metadata-file JSON when extracting digest
Some checks failed
build-and-release / build (push) Failing after 1h49m45s
docker buildx --metadata-file writes pretty-printed JSON (space after
the colon: "containerimage.digest": "sha256:..."), but the digest
grep required compact JSON with no space, so it always matched
nothing. That produced an empty $digest, which the script correctly
treated as fatal and exited on - right after the first service
(gateway) had already built and pushed successfully, silently
aborting the rest of the service loop. Verified the fix against a
real locally-generated metadata file from the same buildx command.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 00:03:32 +05:30
Ashwin Kumar Sivakumar
d422139e48 fix(ci): remove redundant rustup install now that base image already has it
Some checks failed
build-and-release / build (push) Failing after 2m44s
The official rust:alpine base (unlike whatever image the old defunct
registry.nxtgauge.com mirror actually held) already ships a full
rustup-installed toolchain, so the extra `curl rustup.rs | sh` step
now fails with "cannot install while Rust is installed". Drop it and
the /root/.cargo/bin PATH override (the base image already sets PATH
to its own /usr/local/cargo/bin) - just add the musl target, which the
existing rustup binary can do directly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 23:41:31 +05:30
Ashwin Kumar Sivakumar
ae9c38a3af fix(ci): point Dockerfile.simple at ci.nxtgauge.com instead of the defunct registry.nxtgauge.com mirror
Some checks failed
build-and-release / build (push) Failing after 2m36s
registry.nxtgauge.com was set up back in April for the old Woodpecker
CI (commit 09df032) as a manual one-time mirror of rust:alpine to
dodge Docker Hub rate limits. It never had a real ingress route wired
up on the current cluster (confirmed: no Ingress/IngressRoute matches
that host anywhere), so every build has been failing at the base-image
pull. ci.nxtgauge.com is the registry actually in active use since the
Forgejo migration, and the build job already authenticates against it
for pushing service images, so no new credentials are needed. Manually
mirrored rust:alpine there as a one-time step.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 23:36:23 +05:30
Ashwin Kumar Sivakumar
c8fa02a9a4 fix(ci): derive DOCKER_HOST from the job container's own default gateway
Some checks failed
build-and-release / build (push) Failing after 16s
--add-host=host.docker.internal:host-gateway is not being honored by
this act_runner setup (tried via the runner's global container.options
and a per-job container: block; neither worked, confirmed by two
separate failed runs with identical DNS-lookup errors). Read the
container's real default-route gateway from /proc/net/route instead
(portable, no iproute2 dependency) and export it as DOCKER_HOST via
GITHUB_ENV. This is the actual IP of the dind engine that spawned the
job container, regardless of hostname-aliasing support.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 22:50:54 +05:30
Ashwin Kumar Sivakumar
dcf573e0f6 fix(ci): use explicit container: block for reliable job-level docker options
Some checks failed
build-and-release / build (push) Failing after 16s
Forgejo's docs note --add-host via the runner's global
container.options config is not reliably honored for jobs using pure
label-based runs-on mapping. Setting the same image + options
explicitly per-job via jobs.build.container is the more directly
supported path for per-job container customization.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 22:45:35 +05:30
Ashwin Kumar Sivakumar
b9e0ba247c fix(ci): route job-container DOCKER_HOST via host.docker.internal
Some checks failed
build-and-release / build (push) Failing after 16s
127.0.0.1:2375 only worked from the runner container's own network
namespace (sibling to the dind sidecar in the same pod). The actual
job container that runs each step is spawned *by* that dind engine,
one level deeper, so its own loopback doesn't reach the sidecar.
host.docker.internal (mapped to the job container's real gateway via
--add-host=host.docker.internal:host-gateway in the runner's
container.options) reaches back to the dind engine that created it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 19:59:27 +05:30
Ashwin Kumar Sivakumar
e6e503ca69 ci: trigger build after enabling docker-in-docker privileged mode
Some checks failed
build-and-release / build (push) Failing after 15s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 19:07:50 +05:30
Ashwin Kumar Sivakumar
0ea4024657 fix(ci): fix YAML syntax error in build.yaml that silently disabled Actions
Some checks failed
build-and-release / build (push) Failing after 14s
The unindented heredoc terminator (<<EOF2 ... EOF2 flush-left) broke the
YAML block-scalar indentation contract for the `run: |` step, causing
Forgejo to log "ignore invalid workflow build.yaml: yaml: line 75:
could not find expected ':'" and silently skip the workflow entirely
on every push since this line was introduced. No builds have run on
main or high-performance since 2026-07-05 as a result. Replaced the
multi-line heredoc with a single-line bash here-string, which needs
no extra indentation and keeps the shell logic identical.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 18:34:45 +05:30
Ashwin Kumar Sivakumar
519a52813f fix(jobs): nest jobs router under /api/jobs to match gateway routing
The gateway forwards /api/jobs unmodified to the jobs service, but the
service registered its routes at bare /jobs with no prefix — every
other service (companies, users) nests under /api/<service> to match.
This made the public job listing endpoint unreachable (404) through
the gateway on test111.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 18:15:34 +05:30
Ashwin Kumar Sivakumar
afb4dc9ae6 fix(ci): use docker-ready runner label in Forgejo workflow
- Change runs-on from self-hosted to docker-ready
- Add DOCKER_HOST and DOCKER_BUILDKIT env vars
- Align with other repo workflows
2026-07-06 04:24:06 +05:30
Ashwin Kumar Sivakumar
67d372c160 ci: remove GitHub Actions workflow - using Forgejo CI exclusively
- Remove build-and-deploy-forgejo.yml from GitHub Actions
- Forgejo CI at ci.nxtgauge.com now handles all builds and deployments
- All images pushed to Forgejo registry (ci.nxtgauge.com/ashwin/*)
- GitOps updates handled by Forgejo workflows
2026-07-06 04:19:40 +05:30
Ashwin Kumar Sivakumar
b8939e6384 fix(k8s): switch db-migrate image from GHCR to Forgejo registry 2026-07-06 03:52:54 +05:30
Ashwin Kumar Sivakumar
6b1b38e04a fix(docker-compose): switch from GHCR to Forgejo registry 2026-07-06 03:52:35 +05:30
Ashwin Kumar Sivakumar
76e8646c7c fix(ci): switch from GHCR to Forgejo registry
- Update workflow to push to ci.nxtgauge.com/ashwin/*
- Use FORGEJO_USERNAME and FORGEJO_TOKEN secrets
- Fix gitops repo cloning to use x-access-token
- Add ai-assistant to deployment scripts
2026-07-06 03:49:11 +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
e83271c300 fix: resolve payments package compilation errors
- Remove duplicate 'name' field from PricingPackageRow struct
- Add tracecoins_credited variable from package.tracecoins_amount
- Change rust_decimal to use i32 instead of Decimal for SQL compatibility
- Simplify discount calculation to work with paise (integer) values
- Fix payu config field names (merchant_key, merchant_salt)

payments package now compiles successfully.
2026-07-06 02:32:14 +05:30
Ashwin Kumar Sivakumar
0ac0527232 fix: resolve match arm type mismatches and add Deserialize trait
- Fix match arm type errors in ai.rs: wrap bare String returns in (String, bool)
  tuples to match expected return type (response_text, _ollama_used)
- Add Deserialize trait to LiteLLMChatMessage for deserialization
- Add missing fields to GenerateFieldResponse constructors
- Remove body.user_id reference from form extraction (field doesn't exist)
- Add get_llm_base_url() and get_llm_model() helper functions

users package now compiles successfully (only warnings remain).
2026-07-06 02:27:09 +05:30
Ashwin Kumar Sivakumar
339325091c fix: resolve cherry-pick breakage and add missing modules
- Restore deleted module declarations (tutor, ugc_content_creator, user,
  user_role_profile, verification, video_editor) in db/models/mod.rs
- Add mod ai; to users/src/main.rs (fixes crate::ai import)
- Add pub mod ai_auto; to handlers/mod.rs
- Add rust_decimal dependency to payments/Cargo.toml
- Fix missing PgPool import in payments/src/ai_credits.rs
- Make LiteLLMUsage fields public in users/src/litellm.rs
- Add get_llm_base_url() and get_llm_model() helper functions
- Remove leading underscore from variables that are used

Partial fix for high-performance branch build issues.
2026-07-06 02:23:29 +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
c795242040 chore: remove broken company_ai_credits stub
- Delete apps/companies/src/handlers/ai.rs (broken placeholder code)
- Remove ai module export from handlers/mod.rs
- Remove /api/companies/ai route from main.rs

The broken stub had:
- Uuid::parse_str("placeholder") that always errored
- Uuid::new_v4() generating random IDs instead of using auth
- Queries to non-existent company_ai_credits/ai_usage_log tables

AI credits are now properly handled by the users service with
the new ai_credits module (wallet, ledger, LiteLLM integration).
2026-07-06 02:08:07 +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
Ashwin Kumar Sivakumar
f5831da1f5 ci(forgejo): update backend build pipeline 2026-07-03 19:51:37 +05:30
Ashwin Kumar Sivakumar
fcb40c3590 ci: sync GitHub pushes to Forgejo 2026-07-03 18:59:02 +05:30
Ashwin Kumar Sivakumar
fda72c8698 fix(auth): add logging for role assignment debugging
- Enhanced logging for role assignment to track intent/profession
- Better error handling for role insertion
2026-07-03 17:40:19 +05:30
Ashwin Kumar Sivakumar
eaae3d470f Fix /api/ai/* returning 500 on every request, close credit-minting bugs, add grounding guardrail
Critical: ai_access_middleware was wired via from_fn_with_state((), ...)
- passing the unit type as state - and pulled AppState from request
extensions, which nothing ever populated. Every request through
/api/ai/* and /api/ai/auto/* returned 500 INCOMPLETE_CONTEXT. Fixed by
extracting State<AppState> properly and passing the real state at both
call sites; removed the redundant, identically-broken inner middleware
layer inside ai_router().

Security: ai_addon_purchase (/api/ai/addons/purchase, /api/ai/credits/buy)
and ai_plan_upgrade (/api/ai/plans/upgrade) granted AI credits / plan
upgrades (including enterprise) with zero payment verification - any
authenticated user could mint unlimited free credits, and the frontend
already called this directly. Disabled both until wired to a real
payment flow.

Quality: added a grounding/anti-hallucination system prompt applied to
every AI feature call (orchestrator::call_feature /
call_feature_with_plan, plus the handful of call sites that bypass the
orchestrator). Verified against the live model that it reduces but does
not eliminate fabrication on harder reasoning tasks - even the larger
model invents facts not present in the input on some prompts. This is a
real limitation of the two locally-hosted models, not something a
system prompt alone fully solves; flagged for follow-up (e.g. a
verification pass or deterministic checks for high-stakes decisions
like auto-apply).

Also fixed Persona/Pillar keyword detection using naive substring
matching (e.g. "team" matching inside "esteemed", "lead" matching
inside "leadership") - added a word-boundary-aware contains_word()
helper and applied it to all keyword classifiers in this file.
2026-07-03 04:05:14 +05:30
Ashwin Kumar Sivakumar
64089e4da3 Replace Razorpay payment integration with PayU hosted checkout
The frontend (lib/payu.ts, payu-return.tsx) and admin config UI had
already switched to PayU, but the payments service was still calling
Razorpay's order API and verifying Razorpay HMAC signatures -
payments were broken end to end. Rewrites apps/payments to PayU's
hash-based hosted-checkout flow (SHA-512 request/response hash,
key+salt from admin config or PAYU_MERCHANT_KEY/PAYU_SALT), for both
the tracecoin wallet purchase flow and the AI credits flow. The AI
credits frontend checkout was also fabricating a fake payment_id and
signature client-side instead of ever opening a real PayU checkout -
fixed to use the same real flow as tracecoin purchases.

Also fixes the ai_create_ticket endpoint on the users service, which
never validated the X-AI-Service-Key header despite the client
sending one - anyone could create tickets under an arbitrary user_id.
2026-07-02 18:31:07 +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
c9d0e283ac Merge branch 'high-performance' of https://github.com/Traceworks2023/nxtgauge-backend-rust into high-performance 2026-07-02 06:51:14 +05:30
Ashwin Kumar Sivakumar
0b88294486 Update Dockerfile.simple 2026-07-02 06:51:03 +05:30
Tracewebstudio Dev
5082427279 Wire admin Razorpay gateway config 2026-06-26 21:07:36 +02:00
Tracewebstudio Dev
cd3fbfe7ca Integrate Razorpay checkout payments 2026-06-26 20:48:41 +02:00
Ashwin Kumar Sivakumar
4bfb5b4418 Update Forgejo backend publish workflow 2026-06-17 03:28:46 +05:30
Ashwin Kumar Sivakumar
a38a2fd185 fix(ci): isolate gitops checkout dir 2026-06-16 03:29:01 +05:30
Ashwin Kumar Sivakumar
d2e7aee81b fix(ci): retry gitops sync pushes 2026-06-16 01:26:33 +05:30
Ashwin Kumar Sivakumar
46a0758335 fix(ci): run backend deploys on self-hosted runners 2026-06-16 00:50:01 +05:30
Ashwin Kumar Sivakumar
c1c9d246eb feat(ai): improve ask ash direct responses 2026-06-15 16:59:56 +05:30
Ashwin Kumar Sivakumar
06e73eebb5 fix(ai): align backend plans and clean warnings 2026-06-15 09:23:44 +05:30
Ashwin Kumar Sivakumar
09465824ad fix(ai): improve ask ash chat responses 2026-06-15 06:50:08 +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