Commit graph

503 commits

Author SHA1 Message Date
Ashwin Kumar Sivakumar
4f1f4f733d chore: rebuild all — force build all services
All checks were successful
build-and-release / build (developers) (push) Successful in 6m23s
build-and-release / build (employees) (push) Successful in 6m28s
build-and-release / build (catering-services) (push) Successful in 6m55s
build-and-release / build (cron) (push) Successful in 7m5s
build-and-release / build (companies) (push) Successful in 7m29s
build-and-release / build (customers) (push) Successful in 7m59s
build-and-release / build (gateway) (push) Successful in 1m41s
build-and-release / build (fitness-trainers) (push) Successful in 2m1s
build-and-release / build (jobs) (push) Successful in 1m17s
build-and-release / build (graphic-designers) (push) Successful in 2m33s
build-and-release / build (makeup-artists) (push) Successful in 2m50s
build-and-release / build (payments) (push) Successful in 3m49s
build-and-release / build (tutors) (push) Successful in 2m49s
build-and-release / build (social-media-managers) (push) Successful in 4m40s
build-and-release / build (ugc-content-creators) (push) Successful in 2m50s
build-and-release / build (job-seekers) (push) Successful in 7m36s
backend-integration-tests / ai-credits (push) Successful in 4s
build-and-release / build (video-editors) (push) Successful in 2m55s
build-and-release / build (photographers) (push) Successful in 7m45s
build-and-release / build-db-migrate (push) Successful in 3m10s
build-and-release / build (users) (push) Successful in 8m30s
Registry retention (keep-last-3, every 10min) pruned the SHA-tagged
images that several nxtgauge-gitops image-automation commits had
already bumped deployments to, before those images were ever
successfully pulled by the cluster. Result: 14 services stuck in
ImagePullBackOff on 'manifest unknown' (catering-services, companies,
cron, developers, employees, fitness-trainers, gateway,
graphic-designers, job-seekers, jobs, makeup-artists,
social-media-managers, tutors, ugc-content-creators) - old replicas
kept serving traffic so nothing was actually down, but rollouts were
stuck.

This empty commit forces build.yaml to rebuild+push every service in
one batch so gitops automation bumps them all to freshly-pushed,
currently-retained digests together.
2026-08-15 22:39:45 +05:30
Ashwin Kumar Sivakumar
8f0505c36c chore(compose): pin service images to build SHA, add MOCK_STORAGE, drop exposed db/redis ports
All checks were successful
build-and-release / build (catering-services) (push) Successful in 15s
build-and-release / build (employees) (push) Successful in 9s
build-and-release / build (companies) (push) Successful in 18s
build-and-release / build (customers) (push) Successful in 15s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 6s
build-and-release / build (cron) (push) Successful in 21s
build-and-release / build (developers) (push) Successful in 21s
build-and-release / build (graphic-designers) (push) Successful in 7s
build-and-release / build (job-seekers) (push) Successful in 6s
build-and-release / build (jobs) (push) Successful in 6s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (social-media-managers) (push) Successful in 9s
build-and-release / build (makeup-artists) (push) Successful in 13s
build-and-release / build (ugc-content-creators) (push) Successful in 8s
build-and-release / build (tutors) (push) Successful in 10s
build-and-release / build (photographers) (push) Successful in 14s
build-and-release / build (users) (push) Successful in 7s
build-and-release / build (video-editors) (push) Successful in 6s
backend-integration-tests / ai-credits (push) Successful in 6s
build-and-release / build-db-migrate (push) Successful in 3m36s
- close direct host exposure of postgres:5432 and redis:6379 in dev compose
- pin all service images to a specific build SHA instead of floating :high-performance-latest
- enable MOCK_STORAGE for local dev across services
2026-08-15 22:32:06 +05:30
Ashwin Kumar Sivakumar
f9718f85d0 ci: build and push nxtgauge-db-migrate image on every push
All checks were successful
build-and-release / build (developers) (push) Successful in 3m6s
build-and-release / build (jobs) (push) Successful in 1m54s
build-and-release / build-db-migrate (push) Successful in 2m42s
build-and-release / build (companies) (push) Successful in 1m50s
build-and-release / build (photographers) (push) Successful in 2m59s
build-and-release / build (makeup-artists) (push) Successful in 1m34s
build-and-release / build (gateway) (push) Successful in 1m34s
build-and-release / build (ugc-content-creators) (push) Successful in 3m13s
build-and-release / build (job-seekers) (push) Successful in 3m0s
build-and-release / build (tutors) (push) Successful in 2m48s
build-and-release / build (users) (push) Successful in 4m55s
build-and-release / build (customers) (push) Successful in 1m50s
build-and-release / build (graphic-designers) (push) Successful in 1m53s
build-and-release / build (social-media-managers) (push) Successful in 1m51s
build-and-release / build (video-editors) (push) Successful in 2m52s
build-and-release / build (catering-services) (push) Successful in 2m28s
build-and-release / build (fitness-trainers) (push) Successful in 2m49s
build-and-release / build (payments) (push) Successful in 2m44s
build-and-release / build (cron) (push) Successful in 1m6s
build-and-release / build (employees) (push) Successful in 2m28s
backend-integration-tests / ai-credits (push) Successful in 52s
The migrate image (Dockerfile.migrate) was never part of the CI build
matrix - it's a separate crate, not an apps/* service, and the running
K8s Job pulls a static <branch>-latest tag rather than a pinned digest.
Without this, a stale image silently no-ops new migrations: the Job
reports success but applies nothing, which is exactly what happened
with the ai_guard_violations migration on 2026-08-15.
2026-08-15 20:20:26 +05:30
Ashwin Kumar Sivakumar
605f3bdaaa Move ai_guard_violations migration to migrations/ dir picked up by db-migrate
Some checks failed
build-and-release / build (graphic-designers) (push) Successful in 1m52s
build-and-release / build (cron) (push) Successful in 2m34s
build-and-release / build (makeup-artists) (push) Successful in 1m32s
build-and-release / build (video-editors) (push) Waiting to run
backend-integration-tests / ai-credits (push) Waiting to run
build-and-release / build (jobs) (push) Successful in 1m54s
build-and-release / build (customers) (push) Successful in 1m42s
build-and-release / build (companies) (push) Successful in 2m39s
build-and-release / build (gateway) (push) Successful in 1m7s
build-and-release / build (job-seekers) (push) Successful in 3m0s
build-and-release / build (tutors) (push) Has been cancelled
build-and-release / build (photographers) (push) Has been cancelled
build-and-release / build (developers) (push) Successful in 1m44s
build-and-release / build (payments) (push) Has been cancelled
build-and-release / build (fitness-trainers) (push) Successful in 1m51s
build-and-release / build (ugc-content-creators) (push) Has been cancelled
build-and-release / build (social-media-managers) (push) Has been cancelled
build-and-release / build (employees) (push) Successful in 2m6s
build-and-release / build (catering-services) (push) Successful in 2m17s
build-and-release / build (users) (push) Has been cancelled
migrations_new/ is not read by db-migrate (it only honors MIGRATIONS_DIR,
which defaults to /migrations, i.e. crates/db/migrations). The file was
misplaced and would never have run.
2026-08-15 20:15:05 +05:30
Tracewebstudio Dev
d9b3bb4d94 feat(ai-guard): add semantic moderation layer + guard violations DB logging
All checks were successful
build-and-release / build (tutors) (push) Successful in 2m36s
build-and-release / build (users) (push) Successful in 4m52s
build-and-release / build (jobs) (push) Successful in 41s
backend-integration-tests / ai-credits (push) Successful in 45s
build-and-release / build (fitness-trainers) (push) Successful in 1m52s
build-and-release / build (catering-services) (push) Successful in 1m59s
build-and-release / build (social-media-managers) (push) Successful in 3m3s
build-and-release / build (employees) (push) Successful in 1m50s
build-and-release / build (graphic-designers) (push) Successful in 1m54s
build-and-release / build (ugc-content-creators) (push) Successful in 2m46s
build-and-release / build (companies) (push) Successful in 2m6s
build-and-release / build (payments) (push) Successful in 1m55s
build-and-release / build (makeup-artists) (push) Successful in 2m38s
build-and-release / build (cron) (push) Successful in 2m22s
build-and-release / build (job-seekers) (push) Successful in 3m9s
build-and-release / build (customers) (push) Successful in 2m38s
build-and-release / build (developers) (push) Successful in 2m23s
build-and-release / build (photographers) (push) Successful in 2m51s
build-and-release / build (video-editors) (push) Successful in 2m45s
build-and-release / build (gateway) (push) Successful in 44s
- Add llm_moderation_check() — async call to LiteLLM /moderations endpoint
  (routes to OpenAI Moderation API, free) for hate/sexual/violence detection.
  Fails open: if LiteLLM is unreachable, message is allowed through with a
  warning log so core chat is never broken by a network hiccup.
- Add spawn_guard_log() — fire-and-forget tokio task that persists every
  guard rejection (keyword AND moderation) to ai_guard_violations table.
- Wire both guards into ai_chat_message, ai_chat_ask, and ai_chat_stream.
- Add migration: ai_guard_violations(id, user_id, message_excerpt,
  guard_type, reason, categories JSONB, created_at).
- Add GET /api/admin/ai/guard-events with filter by guard_type, pagination.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-15 14:20:44 +02:00
Tracewebstudio Dev
4da502ded8 feat(voice): implement Whisper STT via LiteLLM audio/transcriptions
All checks were successful
build-and-release / build (cron) (push) Successful in 13s
build-and-release / build (users) (push) Successful in 3m41s
build-and-release / build (employees) (push) Successful in 13s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 6s
build-and-release / build (job-seekers) (push) Successful in 6s
build-and-release / build (makeup-artists) (push) Successful in 8s
build-and-release / build (payments) (push) Successful in 5s
build-and-release / build (graphic-designers) (push) Successful in 12s
build-and-release / build (jobs) (push) Successful in 13s
build-and-release / build (photographers) (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 9s
build-and-release / build (tutors) (push) Successful in 11s
build-and-release / build (catering-services) (push) Successful in 5s
build-and-release / build (video-editors) (push) Successful in 5s
backend-integration-tests / ai-credits (push) Successful in 10s
build-and-release / build (companies) (push) Successful in 8s
build-and-release / build (customers) (push) Successful in 7s
build-and-release / build (developers) (push) Successful in 9s
Replaces the Ollama stub (always 501) with a real call to LiteLLM's
OpenAI-compatible audio/transcriptions endpoint:

  POST {LITELLM_BASE_URL}/audio/transcriptions
  Authorization: Bearer {LITELLM_API_KEY}
  multipart: model=whisper-1, file=<audio.webm>

- LITELLM_WHISPER_MODEL env var selects the model (default: whisper-1)
- Reuses the existing LITELLM_BASE_URL / LITELLM_API_KEY vars
- Empty audio body returns 400 (not 501) with a helpful message
- LiteLLM error returns 502 with the upstream detail logged
- Network error returns 503 with a clear message

Response shape unchanged (TranscribeResponse with transcript, language,
confidence, duration_ms, stub=false).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-15 14:08:00 +02:00
Tracewebstudio Dev
b039ed7342 feat(kb): POST /api/admin/kb/articles/ai-draft endpoint
All checks were successful
build-and-release / build (tutors) (push) Successful in 9s
build-and-release / build (jobs) (push) Successful in 14s
build-and-release / build (catering-services) (push) Successful in 14s
build-and-release / build (ugc-content-creators) (push) Successful in 7s
build-and-release / build (video-editors) (push) Successful in 8s
backend-integration-tests / ai-credits (push) Successful in 7s
build-and-release / build (customers) (push) Successful in 14s
build-and-release / build (payments) (push) Successful in 13s
build-and-release / build (companies) (push) Successful in 17s
build-and-release / build (developers) (push) Successful in 16s
build-and-release / build (cron) (push) Successful in 22s
build-and-release / build (employees) (push) Successful in 21s
build-and-release / build (gateway) (push) Successful in 8s
build-and-release / build (graphic-designers) (push) Successful in 8s
build-and-release / build (users) (push) Successful in 2m55s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (job-seekers) (push) Successful in 8s
build-and-release / build (makeup-artists) (push) Successful in 6s
build-and-release / build (social-media-managers) (push) Successful in 10s
build-and-release / build (photographers) (push) Successful in 10s
Generates a full KB article (content + summary) via LiteLLM given a
title, optional category name, and optional topic hints.

- Prompt instructs the LLM to produce markdown-formatted body (300-500
  words) followed by ===SUMMARY=== delimiter and a ≤200-char summary
- Falls back gracefully if LLM omits the delimiter: derives summary from
  the first non-heading sentence
- Charges kb_article_draft feature credits against the admin's account
- Route is /api/admin/kb/articles/ai-draft (POST) — must be registered
  BEFORE /api/admin/kb/articles/{id} so the literal segment wins

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-15 14:03:45 +02:00
Tracewebstudio Dev
ad4ab0477a feat(ai): cover letter inline generation + draft_content field on AskAshResponse
All checks were successful
build-and-release / build (photographers) (push) Successful in 7s
build-and-release / build (makeup-artists) (push) Successful in 12s
build-and-release / build (social-media-managers) (push) Successful in 8s
build-and-release / build (tutors) (push) Successful in 8s
build-and-release / build (ugc-content-creators) (push) Successful in 8s
build-and-release / build (video-editors) (push) Successful in 8s
backend-integration-tests / ai-credits (push) Successful in 13s
build-and-release / build (users) (push) Successful in 3m55s
build-and-release / build (developers) (push) Successful in 13s
build-and-release / build (customers) (push) Successful in 18s
build-and-release / build (employees) (push) Successful in 17s
build-and-release / build (companies) (push) Successful in 21s
build-and-release / build (cron) (push) Successful in 20s
build-and-release / build (catering-services) (push) Successful in 24s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 7s
build-and-release / build (job-seekers) (push) Successful in 7s
build-and-release / build (graphic-designers) (push) Successful in 7s
build-and-release / build (payments) (push) Successful in 8s
build-and-release / build (jobs) (push) Successful in 11s
AskAshResponse now carries draft_content: Option<String> — a clean raw
generated text separate from the prose wrapper in message. Used by:
  - profile_draft: the improved summary text (for Save to Profile)
  - cover_letter_draft: the letter body (for clipboard copy)

When Intent::CoverLetter is detected in ask_ash:
  - Fetches job_seeker_profiles (full_name, summary, experience, skills)
  - Calls LLM with cover_letter_generate feature key (charges credits)
  - Returns action_type: 'cover_letter_draft', suggested_action: 'open_cover_letter'
  - draft_content holds the raw letter body; message wraps it in --- delimiters
  - If no profile found: returns navigation response to open_cover_letter
  - LLM failure falls through to generic path

Profile draft updated to populate draft_content: Some(improved) so the
frontend no longer needs regex parsing to extract the clean text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-15 13:16:20 +02:00
Tracewebstudio Dev
cd7e5bdc05 feat(ai): profile improvement draft + save_profile confirm action
Some checks failed
build-and-release / build (companies) (push) Failing after 10s
build-and-release / build (developers) (push) Failing after 8s
build-and-release / build (cron) (push) Successful in 12s
build-and-release / build (customers) (push) Successful in 17s
build-and-release / build (catering-services) (push) Successful in 21s
build-and-release / build (gateway) (push) Successful in 5s
build-and-release / build (employees) (push) Successful in 16s
build-and-release / build (fitness-trainers) (push) Successful in 16s
build-and-release / build (job-seekers) (push) Successful in 9s
build-and-release / build (graphic-designers) (push) Successful in 12s
build-and-release / build (jobs) (push) Successful in 12s
build-and-release / build (makeup-artists) (push) Successful in 7s
build-and-release / build (payments) (push) Successful in 8s
build-and-release / build (photographers) (push) Successful in 7s
build-and-release / build (ugc-content-creators) (push) Successful in 5s
build-and-release / build (social-media-managers) (push) Successful in 10s
build-and-release / build (video-editors) (push) Successful in 8s
build-and-release / build (tutors) (push) Successful in 12s
backend-integration-tests / ai-credits (push) Successful in 6s
build-and-release / build (users) (push) Successful in 2m59s
When a job seeker asks Ask Ash to improve their resume/profile/summary:
- Fetches current job_seeker_profiles.summary from DB
- Calls LLM (via orchestrator, charges profile_improve feature credits)
- Returns action_type: 'profile_draft' with the improved text
- If no summary exists yet, returns a navigation response to profile page

ai_chat_confirm now handles action='save_profile':
- Takes draft_text from fields
- UPDATEs job_seeker_profiles.summary for the authenticated user
- Returns 404 if no profile row found (not yet onboarded)
- Returns helpful error messages on failure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-14 18:43:24 +02:00
Tracewebstudio Dev
38981ffe70 feat(ai): add action_type to AskAshResponse + POST /api/ai/chat/confirm
All checks were successful
build-and-release / build (catering-services) (push) Successful in 6s
build-and-release / build (companies) (push) Successful in 9s
build-and-release / build (developers) (push) Successful in 5s
build-and-release / build (cron) (push) Successful in 12s
build-and-release / build (customers) (push) Successful in 11s
build-and-release / build (gateway) (push) Successful in 7s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (graphic-designers) (push) Successful in 5s
build-and-release / build (employees) (push) Successful in 10s
build-and-release / build (job-seekers) (push) Successful in 5s
build-and-release / build (makeup-artists) (push) Successful in 6s
build-and-release / build (jobs) (push) Successful in 9s
build-and-release / build (payments) (push) Successful in 5s
build-and-release / build (photographers) (push) Successful in 10s
build-and-release / build (social-media-managers) (push) Successful in 6s
build-and-release / build (ugc-content-creators) (push) Successful in 6s
build-and-release / build (tutors) (push) Successful in 10s
build-and-release / build (video-editors) (push) Successful in 9s
backend-integration-tests / ai-credits (push) Successful in 9s
build-and-release / build (users) (push) Successful in 3m14s
AskAshResponse gains action_type: Option<String> so the frontend knows
what kind of UI to render for each response:
  ticket_created  — ticket was auto-created inline
  ticket_pending  — user wants a ticket but none was created (show confirm button)
  kb_results      — KB articles found
  usage_info      — usage/credits summary
  navigation      — navigate to the relevant feature page

POST /api/ai/chat/confirm (new): executes AI-suggested actions the user
confirms in the chat widget. action = 'create_ticket' creates a support
ticket from the conversation text and returns the ticket id + subject.
Additional actions (profile save, contact request) can be added here.

Wired into ai_router() at /chat/confirm.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-14 18:06:33 +02:00
Ashwin Kumar Sivakumar
cc2dab112b fix(db): 4 fresh-bootstrap migration chain bugs found + verified today
All checks were successful
build-and-release / build (cron) (push) Successful in 58s
build-and-release / build (companies) (push) Successful in 1m59s
build-and-release / build (customers) (push) Successful in 2m9s
build-and-release / build (employees) (push) Successful in 2m17s
build-and-release / build (developers) (push) Successful in 2m29s
build-and-release / build (catering-services) (push) Successful in 2m45s
build-and-release / build (gateway) (push) Successful in 49s
build-and-release / build (jobs) (push) Successful in 42s
build-and-release / build (fitness-trainers) (push) Successful in 2m38s
build-and-release / build (graphic-designers) (push) Successful in 1m57s
build-and-release / build (payments) (push) Successful in 1m54s
build-and-release / build (job-seekers) (push) Successful in 2m57s
build-and-release / build (makeup-artists) (push) Successful in 2m47s
build-and-release / build (photographers) (push) Successful in 2m48s
build-and-release / build (social-media-managers) (push) Successful in 2m59s
backend-integration-tests / ai-credits (push) Successful in 50s
build-and-release / build (tutors) (push) Successful in 2m45s
build-and-release / build (ugc-content-creators) (push) Successful in 2m50s
build-and-release / build (video-editors) (push) Successful in 2m40s
build-and-release / build (users) (push) Successful in 4m47s
Reconciling the local dev DB (63 migrations behind) surfaced 4 genuine
bugs in the migration chain itself -- not just this DB's legacy
scripts/init-db.sql seeding -- confirmed by replaying the full chain
against a brand new, completely empty database from scratch:

- 20260318235959: customer_profiles.status is UPDATEd by
  20260319090000's backfill 4 months before it's ever ADDed
  (20260721020000). Adds it early (IF NOT EXISTS).
- 20260401235959: 20260317190000 creates the old users-linked
  `employees` shape; 20260402030000's CREATE TABLE IF NOT EXISTS no-ops
  against it and fails creating an index on a column that was never
  added. Conditionally drops the old shape first (only if it's still
  pre-transition -- gated on the missing `email` column), restoring
  20260402030000's own documented original intent.
- 20260419235959: the schema `20260420000003_external_role_modules`
  needs (persona_types, modules, role_module_access, ...) was only ever
  defined in a disabled .up.sql.skip (its version slot was taken by
  ...seed.sql); the seed data that depends on it was never skipped.
  Creates that schema early -- verbatim content, purely additive.
- 20260421235959: same disabled-migration pattern for the
  role_permissions -> role_admin_permissions / dashboard_configs ->
  role_sidebar_configs / runtime_configs -> role_runtime_configs /
  user_roles -> user_role_assignments renames that 20260422000000's
  widget seed needs. Conditionally renames each pair (only if old name
  exists and new name doesn't), verified against live Rust code that
  already queries the new names exclusively.

payments/invoices were NOT chain bugs -- confirmed clean on the fresh
bootstrap test -- so no fix needed for those; they only conflicted on
this one DB because of its scripts/init-db.sql legacy seed, which is
already a documented, known gap.

Verified twice: applied cleanly as no-ops against the now-fully-migrated
local dev DB, and applied successfully end-to-end (0 manual steps)
against a brand new empty database created from scratch.

Runbook updated with the full pending-migration list and today's
findings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 18:30:42 +05:30
Ashwin Kumar Sivakumar
c394d9fc07 feat(ai-credits): real coupon validation endpoint; restore invoice FK integrity
All checks were successful
build-and-release / build (employees) (push) Successful in 1m46s
build-and-release / build (customers) (push) Successful in 2m0s
build-and-release / build (cron) (push) Successful in 2m13s
build-and-release / build (companies) (push) Successful in 2m20s
build-and-release / build (catering-services) (push) Successful in 2m36s
build-and-release / build (developers) (push) Successful in 2m52s
build-and-release / build (gateway) (push) Successful in 53s
build-and-release / build (jobs) (push) Successful in 44s
build-and-release / build (fitness-trainers) (push) Successful in 1m39s
build-and-release / build (job-seekers) (push) Successful in 2m14s
build-and-release / build (payments) (push) Successful in 1m52s
build-and-release / build (graphic-designers) (push) Successful in 2m37s
build-and-release / build (makeup-artists) (push) Successful in 3m3s
build-and-release / build (photographers) (push) Successful in 2m48s
build-and-release / build (social-media-managers) (push) Successful in 2m40s
backend-integration-tests / ai-credits (push) Successful in 45s
build-and-release / build (tutors) (push) Successful in 2m44s
build-and-release / build (ugc-content-creators) (push) Successful in 2m44s
build-and-release / build (video-editors) (push) Successful in 2m45s
build-and-release / build (users) (push) Successful in 4m49s
- Add POST /api/ai-credits/coupons/validate: a dry-run of the same
  validate_coupon() check create_order applies, so the checkout UI can
  show a real discount/error before Pay instead of only finding out at
  order-creation time. Never inserts anything.
- Add migration 20260814050000: restores integrity on invoices.payment_id
  after 20260814030000 dropped the hard FK to support polymorphic
  invoice_type (TRACECOIN_PURCHASE -> payments, AI_CREDIT_PURCHASE ->
  ai_credit_orders). A BEFORE INSERT/UPDATE trigger now validates
  payment_id against the right table per invoice_type instead of leaving
  it fully unchecked. Verified against a live Postgres in a scratch
  schema (valid/invalid payment_id, valid/bogus invoice_type).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 15:26:47 +05:30
Tracewebstudio Dev
4e0e6af3e1 fix(payments): compare global coupon redemptions against max_redemptions not max_redemptions_per_user
All checks were successful
build-and-release / build (employees) (push) Successful in 11s
build-and-release / build (cron) (push) Successful in 14s
build-and-release / build (customers) (push) Successful in 16s
build-and-release / build (catering-services) (push) Successful in 19s
build-and-release / build (companies) (push) Successful in 21s
build-and-release / build (developers) (push) Successful in 20s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 9s
build-and-release / build (graphic-designers) (push) Successful in 8s
build-and-release / build (job-seekers) (push) Successful in 8s
build-and-release / build (jobs) (push) Successful in 10s
build-and-release / build (social-media-managers) (push) Successful in 8s
build-and-release / build (makeup-artists) (push) Successful in 12s
build-and-release / build (photographers) (push) Successful in 8s
build-and-release / build (tutors) (push) Successful in 7s
build-and-release / build (users) (push) Successful in 6s
backend-integration-tests / ai-credits (push) Successful in 9s
build-and-release / build (ugc-content-creators) (push) Successful in 11s
build-and-release / build (video-editors) (push) Successful in 11s
build-and-release / build (payments) (push) Successful in 1m0s
validate_coupon was checking:
  total_redemptions (= redemptions_used, global count) >= max_per_user (per-user limit)

which means a coupon with max_redemptions=1000 and max_redemptions_per_user=1
would be marked exhausted after the first person ever used it.

Fix: also SELECT max_redemptions and compare global count against it.
The per-user check on line 192 (user_redemptions >= max_per_user) was
already correct and is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-14 11:19:00 +02:00
Ashwin Kumar Sivakumar
86e1fd47d2 feat(waitlist): admin listing endpoint (GET /api/admin/waitlist)
All checks were successful
build-and-release / build (developers) (push) Successful in 11s
build-and-release / build (companies) (push) Successful in 13s
build-and-release / build (cron) (push) Successful in 19s
build-and-release / build (employees) (push) Successful in 17s
build-and-release / build (customers) (push) Successful in 18s
build-and-release / build (catering-services) (push) Successful in 22s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (job-seekers) (push) Successful in 8s
build-and-release / build (makeup-artists) (push) Successful in 8s
build-and-release / build (payments) (push) Successful in 9s
build-and-release / build (graphic-designers) (push) Successful in 13s
build-and-release / build (jobs) (push) Successful in 13s
build-and-release / build (photographers) (push) Successful in 5s
build-and-release / build (social-media-managers) (push) Successful in 5s
build-and-release / build (tutors) (push) Successful in 6s
build-and-release / build (ugc-content-creators) (push) Successful in 10s
backend-integration-tests / ai-credits (push) Successful in 6s
build-and-release / build (video-editors) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 31s
build-and-release / build (users) (push) Successful in 3m49s
Paginated, admin-only list of waitlist_signups (email + created_at,
newest first) for the upcoming admin-solid waitlist page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 04:05:17 +05:30
Ashwin Kumar Sivakumar
77c8330b11 feat(waitlist): POST /api/waitlist for the nxtgauge.com coming-soon form
All checks were successful
build-and-release / build (catering-services) (push) Successful in 1m28s
build-and-release / build (cron) (push) Successful in 1m51s
build-and-release / build (companies) (push) Successful in 2m7s
build-and-release / build (customers) (push) Successful in 2m54s
build-and-release / build (developers) (push) Successful in 1m39s
build-and-release / build (fitness-trainers) (push) Successful in 1m39s
build-and-release / build (gateway) (push) Successful in 1m31s
build-and-release / build (jobs) (push) Successful in 42s
build-and-release / build (employees) (push) Successful in 2m22s
build-and-release / build (graphic-designers) (push) Successful in 2m8s
build-and-release / build (makeup-artists) (push) Successful in 1m58s
build-and-release / build (payments) (push) Successful in 1m48s
build-and-release / build (job-seekers) (push) Successful in 3m4s
build-and-release / build (social-media-managers) (push) Successful in 2m39s
build-and-release / build (photographers) (push) Successful in 2m42s
backend-integration-tests / ai-credits (push) Successful in 50s
build-and-release / build (tutors) (push) Successful in 3m4s
build-and-release / build (ugc-content-creators) (push) Successful in 2m44s
build-and-release / build (video-editors) (push) Successful in 2m43s
build-and-release / build (users) (push) Successful in 4m38s
The coming-soon page's 'Notify Me' form (nxtgauge-gitops/coming-soon/
index.html) only console.logged the email - nothing was actually
captured. Adds a public (no auth, same trust model as a newsletter
signup) endpoint on the users service:

- New waitlist_signups table (email unique, created_at) - no user_id/
  FK since these are anonymous pre-launch signups, not necessarily
  existing accounts.
- apps/users/src/handlers/waitlist.rs: POST / -> INSERT ... ON
  CONFLICT DO NOTHING (repeat signups from the same email are a no-op,
  not an error), loose email validation (has @ and a dotted domain -
  this is a marketing signup, not an account, so overly strict
  validation just loses real signups to minor typos).
- Routed /api/waitlist through the gateway to the users service,
  alongside the other public routes (packages, kb, etc.)

Applied migration to nxtgauge_test and prod.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 03:46:28 +05:30
Ashwin Kumar Sivakumar
c2fb7d61f7 feat(invoices): generate GST invoices for AI credit purchases
All checks were successful
build-and-release / build (developers) (push) Successful in 1m41s
build-and-release / build (catering-services) (push) Successful in 1m58s
build-and-release / build (companies) (push) Successful in 2m0s
build-and-release / build (cron) (push) Successful in 2m8s
build-and-release / build (customers) (push) Successful in 2m42s
build-and-release / build (gateway) (push) Successful in 1m2s
build-and-release / build (fitness-trainers) (push) Successful in 1m34s
build-and-release / build (jobs) (push) Successful in 44s
build-and-release / build (employees) (push) Successful in 1m50s
build-and-release / build (graphic-designers) (push) Successful in 2m41s
build-and-release / build (makeup-artists) (push) Successful in 1m49s
build-and-release / build (job-seekers) (push) Successful in 3m2s
build-and-release / build (photographers) (push) Successful in 2m40s
build-and-release / build (payments) (push) Successful in 2m50s
build-and-release / build (social-media-managers) (push) Successful in 2m55s
backend-integration-tests / ai-credits (push) Successful in 52s
build-and-release / build (ugc-content-creators) (push) Successful in 2m37s
build-and-release / build (tutors) (push) Successful in 2m56s
build-and-release / build (video-editors) (push) Successful in 2m41s
build-and-release / build (users) (push) Successful in 4m44s
AI credit purchases (money -> credits via PayU) never generated an
invoice, even though the exact same infrastructure already works for
TraceCoin purchases in main.rs's generate_purchase_invoice. Spending
credits (try_reserve_credits/capture) correctly does NOT get an
invoice - only real-money purchases do, matching existing TraceCoin
behavior.

- invoices.payment_id had a hard FK to payments(id) only, which blocks
  using it for ai_credit_orders(id) rows. Postgres has no polymorphic
  FK; dropped the constraint (invoice_type already says which table
  payment_id points into) via a new migration rather than editing the
  original invoices migration.
- Added generate_ai_credit_invoice in ai_credits.rs, called from
  verify_order after a successful PayU payment - mirrors main.rs's
  pattern exactly (same non-blocking failure handling, same seller
  details via the now pub(crate) seller_details(), invoice_type
  'AI_CREDIT_PURCHASE').
- Caught a real bug while writing this: order.amount_inr is the
  POST-discount final price, but NewInvoice.discount_amount is
  subtracted again inside compute_totals (subtotal - discount) - using
  amount_inr directly as unit_price_paise would have double-subtracted
  the discount. Reconstructed the pre-discount price
  (amount_inr + discount_applied) for the line item instead.

Applied the FK-drop migration to nxtgauge_test and prod; verified the
constraint is gone and user_id's FK is untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 03:17:17 +05:30
Tracewebstudio Dev
65262e842c fix(db): add missing ai_credit_orders columns + ai_coupons tables
All checks were successful
build-and-release / build (cron) (push) Successful in 1m0s
build-and-release / build (catering-services) (push) Successful in 1m53s
build-and-release / build (companies) (push) Successful in 2m2s
build-and-release / build (employees) (push) Successful in 2m17s
build-and-release / build (developers) (push) Successful in 2m32s
build-and-release / build (customers) (push) Successful in 2m39s
build-and-release / build (gateway) (push) Successful in 1m4s
build-and-release / build (fitness-trainers) (push) Successful in 2m38s
build-and-release / build (graphic-designers) (push) Successful in 1m49s
build-and-release / build (makeup-artists) (push) Successful in 1m37s
build-and-release / build (jobs) (push) Successful in 1m44s
build-and-release / build (job-seekers) (push) Successful in 2m57s
build-and-release / build (social-media-managers) (push) Successful in 1m43s
build-and-release / build (payments) (push) Successful in 2m47s
backend-integration-tests / ai-credits (push) Successful in 52s
build-and-release / build (photographers) (push) Successful in 2m57s
build-and-release / build (ugc-content-creators) (push) Successful in 2m31s
build-and-release / build (tutors) (push) Successful in 2m53s
build-and-release / build (video-editors) (push) Successful in 2m33s
build-and-release / build (users) (push) Successful in 4m52s
20260814000000: add coupon_code + discount_applied to ai_credit_orders
CREATE TABLE — create_order inserts both columns but the original
migration omitted them.

20260814020000 (new): create ai_coupons + ai_coupon_redemptions, the
tables referenced by create_order/verify_order in ai_credits.rs.
Extracted from the skipped 20260706300000 migration which couldn't be
enabled because it referenced ai_credit_orders before that table existed.

Runbook updated with the 3 pending prod migrations and redeploy step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 23:10:40 +02:00
Ashwin Kumar Sivakumar
41b17baa14 feat(ai-credits): role-scoped purchasable credit packages
All checks were successful
build-and-release / build (catering-services) (push) Successful in 1m25s
build-and-release / build (cron) (push) Successful in 1m50s
build-and-release / build (customers) (push) Successful in 1m55s
build-and-release / build (companies) (push) Successful in 2m0s
build-and-release / build (developers) (push) Successful in 2m22s
build-and-release / build (employees) (push) Successful in 2m34s
build-and-release / build (fitness-trainers) (push) Successful in 1m41s
build-and-release / build (gateway) (push) Successful in 1m32s
build-and-release / build (graphic-designers) (push) Successful in 2m3s
build-and-release / build (job-seekers) (push) Successful in 2m4s
build-and-release / build (jobs) (push) Successful in 2m7s
build-and-release / build (payments) (push) Successful in 1m45s
build-and-release / build (makeup-artists) (push) Successful in 2m42s
build-and-release / build (tutors) (push) Successful in 1m42s
build-and-release / build (photographers) (push) Successful in 2m45s
backend-integration-tests / ai-credits (push) Successful in 50s
build-and-release / build (social-media-managers) (push) Successful in 2m39s
build-and-release / build (ugc-content-creators) (push) Successful in 2m40s
build-and-release / build (video-editors) (push) Successful in 2m42s
build-and-release / build (users) (push) Successful in 4m38s
Adds applicable_roles TEXT[] to ai_credit_packages (empty = visible to
every role, matching today's behavior for the 4 existing packages -
nothing changes for them until an admin opts them into specific
roles). Mirrors pricing_packages' existing role_key convention, as an
array since one AI package can reasonably apply to several roles at
once.

- GET /api/ai-credits (list_packages) now accepts optional auth (via a
  local MaybeAuthUser wrapper, since AuthUser doesn't implement axum's
  optional-extraction trait) and filters out packages not applicable
  to the viewer's roles. Anonymous viewers only see role-unrestricted
  packages.
- POST /api/ai-credits/order (create_order) re-validates role
  eligibility server-side too, not just in the listing - closes off
  a logged-in user buying a package never shown to them.
- Admin CRUD (GET/POST /api/admin/ai-credits/packages,
  PATCH .../{id}) now reads/writes applicable_roles.

Applied to nxtgauge_test and prod; verified column + index created,
existing 4 packages default to empty (all roles).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 01:46:03 +05:30
Ashwin Kumar Sivakumar
57146b2e19 Merge remote-tracking branch 'origin/high-performance' into high-performance
Some checks failed
build-and-release / build (cron) (push) Successful in 59s
build-and-release / build (catering-services) (push) Successful in 1m34s
build-and-release / build (companies) (push) Successful in 2m15s
build-and-release / build (employees) (push) Successful in 2m15s
build-and-release / build (customers) (push) Successful in 2m18s
build-and-release / build (gateway) (push) Successful in 1m1s
build-and-release / build (developers) (push) Successful in 2m49s
build-and-release / build (jobs) (push) Successful in 41s
build-and-release / build (fitness-trainers) (push) Successful in 2m38s
build-and-release / build (graphic-designers) (push) Successful in 1m56s
build-and-release / build (makeup-artists) (push) Successful in 1m41s
build-and-release / build (job-seekers) (push) Successful in 3m5s
build-and-release / build (photographers) (push) Successful in 2m33s
build-and-release / build (payments) (push) Successful in 2m46s
build-and-release / build (video-editors) (push) Has been cancelled
build-and-release / build (users) (push) Has been cancelled
build-and-release / build (ugc-content-creators) (push) Has been cancelled
build-and-release / build (social-media-managers) (push) Has been cancelled
build-and-release / build (tutors) (push) Has been cancelled
backend-integration-tests / ai-credits (push) Has been cancelled
2026-08-14 01:39:43 +05:30
Ashwin Kumar Sivakumar
8e4d64d33b fix(db): correct ai_credit_packages pricing (paise not rupees), add missing ai_credit_orders table
Discovered while wiring up role-scoped AI credit packages: the active
seed migration (20260615060600) stored price_inr as 99/349/999/2499 -
values that read like whole rupees, but every consumer (PayU's
paise_to_rupee_string, matching pricing_packages' existing paise
convention) treats price_inr as paise, meaning a real purchase would
have charged ~1% of the intended price.

The actual fix already existed as 20260705110000_ai_credit_packages
.up.sql.skip (correct paise values + the ai_credit_orders table
create_order inserts into) but got disabled in the same bulk skip
pass as everything else this session has been un-tangling - its
CREATE TABLE ai_credit_packages (no IF NOT EXISTS) hit 'relation
already exists' since 20260615060600 had already created it, aborting
before ai_credit_orders was ever created.

Net effect before this fix: buying AI credits was completely broken
(create_order would 500 - no ai_credit_orders table to insert into).
Confirmed zero rows anywhere in ai_credit_orders (the table simply
didn't exist) - nothing to reconcile, this is a pre-launch fix.

New migration (not resurrecting the old .skip file, to keep a clean
linear history matching this session's other fixes): UPDATE the 4
known-wrong rows by name to their correct paise values, CREATE TABLE
IF NOT EXISTS ai_credit_orders. Applied to both nxtgauge_test and
prod; verified.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 01:38:59 +05:30
Tracewebstudio Dev
0e2bbd34eb docs: mark DB migrations as completed in runbook
All checks were successful
build-and-release / build (cron) (push) Successful in 4s
build-and-release / build (employees) (push) Successful in 4s
build-and-release / build (fitness-trainers) (push) Successful in 5s
build-and-release / build (gateway) (push) Successful in 7s
build-and-release / build (developers) (push) Successful in 17s
build-and-release / build (companies) (push) Successful in 19s
build-and-release / build (catering-services) (push) Successful in 21s
build-and-release / build (customers) (push) Successful in 20s
build-and-release / build (graphic-designers) (push) Successful in 7s
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 7s
build-and-release / build (photographers) (push) Successful in 6s
build-and-release / build (payments) (push) Successful in 11s
build-and-release / build (tutors) (push) Successful in 7s
build-and-release / build (social-media-managers) (push) Successful in 11s
build-and-release / build (ugc-content-creators) (push) Successful in 7s
build-and-release / build (users) (push) Successful in 7s
build-and-release / build (video-editors) (push) Successful in 7s
backend-integration-tests / ai-credits (push) Successful in 10s
All four DB tasks confirmed applied to production (2026-08-13):
- wallet_full migration re-enabled
- ai_credits_wallet migration rewritten as idempotent and applied
- TIMESTAMP → TIMESTAMPTZ fix for 9 AI table columns
- nxtgauge_test DB + Forgejo CI secret wired

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 21:32:48 +02:00
Ashwin Kumar Sivakumar
eefc0457be fix(test): use a fresh random user per ai_credits_reaper.rs run
All checks were successful
build-and-release / build (catering-services) (push) Successful in 1m31s
build-and-release / build (cron) (push) Successful in 1m54s
build-and-release / build (companies) (push) Successful in 2m7s
build-and-release / build (customers) (push) Successful in 2m53s
build-and-release / build (fitness-trainers) (push) Successful in 1m29s
build-and-release / build (developers) (push) Successful in 1m43s
build-and-release / build (gateway) (push) Successful in 1m35s
build-and-release / build (employees) (push) Successful in 2m15s
build-and-release / build (jobs) (push) Successful in 1m10s
build-and-release / build (graphic-designers) (push) Successful in 2m9s
build-and-release / build (makeup-artists) (push) Successful in 1m35s
build-and-release / build (photographers) (push) Successful in 1m44s
build-and-release / build (job-seekers) (push) Successful in 3m8s
build-and-release / build (payments) (push) Successful in 2m45s
build-and-release / build (social-media-managers) (push) Successful in 2m35s
backend-integration-tests / ai-credits (push) Successful in 50s
build-and-release / build (tutors) (push) Successful in 3m10s
build-and-release / build (ugc-content-creators) (push) Successful in 2m49s
build-and-release / build (video-editors) (push) Successful in 2m48s
build-and-release / build (users) (push) Successful in 4m38s
The fixed UUID (33333333-...) meant every re-run against the same
persistent test database reused the same wallet - any earlier partial
run that panicked before its own capture/release step left
reserved_credits permanently stuck above zero, so this run's fresh
reserve (expected to bring it to exactly 4) actually reads 8, 12, etc.
depending on how many times the suite had previously failed midway.
Matches ai_credits.rs's make_user() pattern (Uuid::new_v4()) instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 22:09:33 +05:30
Ashwin Kumar Sivakumar
85690b3002 fix(test): make ai_credits_reaper.rs resilient to accumulated stale holds
Some checks failed
build-and-release / build (catering-services) (push) Successful in 1m30s
build-and-release / build (employees) (push) Successful in 1m42s
build-and-release / build (cron) (push) Successful in 2m11s
build-and-release / build (companies) (push) Successful in 2m16s
build-and-release / build (gateway) (push) Successful in 39s
build-and-release / build (developers) (push) Successful in 2m49s
build-and-release / build (customers) (push) Successful in 3m0s
build-and-release / build (graphic-designers) (push) Successful in 1m36s
build-and-release / build (jobs) (push) Successful in 1m46s
build-and-release / build (fitness-trainers) (push) Successful in 2m54s
build-and-release / build (job-seekers) (push) Successful in 2m17s
build-and-release / build (photographers) (push) Successful in 1m43s
build-and-release / build (payments) (push) Successful in 2m45s
build-and-release / build (makeup-artists) (push) Successful in 3m6s
build-and-release / build (social-media-managers) (push) Successful in 2m34s
backend-integration-tests / ai-credits (push) Failing after 1m7s
build-and-release / build (tutors) (push) Successful in 2m46s
build-and-release / build (ugc-content-creators) (push) Successful in 3m1s
build-and-release / build (users) (push) Has been cancelled
build-and-release / build (video-editors) (push) Has been cancelled
The sweep query is intentionally global (matches the real cron
reaper), but against a persistent, never-reset test database re-run
many times over a debugging session, other tests' un-captured/
un-released reservations eventually go stale and get picked up
alongside this test's own hold, breaking the exact-match assertion
(observed: 6 expired holds instead of 1). Clear pre-existing stale
'held' rows first, matching the clean slate a continuously-running
production reaper would actually maintain.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 22:01:24 +05:30
Ashwin Kumar Sivakumar
b48a1dd204 fix(test): self-provision the fixture user in ai_credits_reaper.rs
Some checks failed
build-and-release / build (cron) (push) Successful in 1m0s
build-and-release / build (catering-services) (push) Successful in 1m29s
build-and-release / build (companies) (push) Successful in 1m52s
build-and-release / build (customers) (push) Successful in 2m13s
build-and-release / build (employees) (push) Successful in 2m20s
build-and-release / build (gateway) (push) Successful in 1m1s
build-and-release / build (developers) (push) Successful in 3m9s
build-and-release / build (fitness-trainers) (push) Successful in 2m50s
build-and-release / build (job-seekers) (push) Successful in 1m54s
build-and-release / build (jobs) (push) Successful in 1m55s
build-and-release / build (graphic-designers) (push) Successful in 2m38s
build-and-release / build (makeup-artists) (push) Successful in 2m59s
build-and-release / build (photographers) (push) Successful in 1m52s
build-and-release / build (payments) (push) Successful in 2m45s
backend-integration-tests / ai-credits (push) Failing after 51s
build-and-release / build (social-media-managers) (push) Successful in 2m40s
build-and-release / build (tutors) (push) Successful in 2m51s
build-and-release / build (ugc-content-creators) (push) Successful in 2m53s
build-and-release / build (video-editors) (push) Has been cancelled
build-and-release / build (users) (push) Has been cancelled
expired_hold_is_swept_and_credits_return_to_available used a hardcoded
UUID assuming a matching users row already existed in whatever
database it ran against, but user_ai_subscriptions.user_id has a FK to
users(id) - against a fresh database (like CI's nxtgauge_test) this
failed with a foreign key violation before the actual sweep/release
logic under test ever ran. Provision it inline instead, matching
ai_credits.rs's make_user() pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 21:52:54 +05:30
Ashwin Kumar Sivakumar
1af10420ce fix(db): convert ai_credits timestamp columns to TIMESTAMPTZ
Some checks failed
build-and-release / build (cron) (push) Successful in 57s
build-and-release / build (customers) (push) Successful in 1m54s
build-and-release / build (employees) (push) Successful in 2m11s
build-and-release / build (companies) (push) Successful in 2m27s
build-and-release / build (catering-services) (push) Successful in 2m28s
build-and-release / build (gateway) (push) Successful in 48s
build-and-release / build (developers) (push) Successful in 3m3s
build-and-release / build (jobs) (push) Successful in 43s
build-and-release / build (fitness-trainers) (push) Successful in 2m36s
build-and-release / build (makeup-artists) (push) Successful in 1m45s
build-and-release / build (graphic-designers) (push) Successful in 2m38s
build-and-release / build (job-seekers) (push) Successful in 2m28s
build-and-release / build (photographers) (push) Successful in 2m34s
build-and-release / build (social-media-managers) (push) Successful in 2m34s
build-and-release / build (payments) (push) Successful in 3m20s
backend-integration-tests / ai-credits (push) Failing after 44s
build-and-release / build (tutors) (push) Successful in 2m41s
build-and-release / build (video-editors) (push) Has been cancelled
build-and-release / build (users) (push) Has been cancelled
build-and-release / build (ugc-content-creators) (push) Successful in 2m41s
9 columns across ai_plans/user_ai_subscriptions/ai_feature_costs/
ai_usage_logs were TIMESTAMP (no timezone), left over from whatever
pre-20260703210000 mechanism originally created these 4 tables, but
crates/db/src/models/ai_credits.rs maps all of them to DateTime<Utc>,
which sqlx requires TIMESTAMPTZ for. This is a live bug, not just a
test-setup gap - discovered via crates/db/tests/ai_credits.rs failing
with ColumnDecode errors, but any production code path selecting
these columns (e.g. current_period_start/end on every wallet read)
would hit the same failure.

ALTER COLUMN ... USING col AT TIME ZONE 'UTC' is lossless here since
every write path uses NOW()/DEFAULT NOW() with no other timezone
handling anywhere in the codebase. Applied to both nxtgauge_test and
the live nxtgauge database directly; verified all 9 columns converted
and the 3 existing user_ai_subscriptions + 4 ai_plans rows' values are
intact and correctly interpreted as UTC afterward.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 21:44:30 +05:30
Ashwin Kumar Sivakumar
675a5a12c5 chore: trigger ai-credits CI re-run with seeded test data
Some checks failed
build-and-release / build (catering-services) (push) Successful in 13s
build-and-release / build (cron) (push) Successful in 13s
build-and-release / build (companies) (push) Successful in 16s
build-and-release / build (customers) (push) Successful in 28s
build-and-release / build (fitness-trainers) (push) Successful in 19s
build-and-release / build (graphic-designers) (push) Successful in 18s
build-and-release / build (gateway) (push) Successful in 27s
build-and-release / build (jobs) (push) Successful in 15s
build-and-release / build (makeup-artists) (push) Successful in 13s
build-and-release / build (job-seekers) (push) Successful in 29s
build-and-release / build (payments) (push) Successful in 20s
build-and-release / build (social-media-managers) (push) Successful in 13s
build-and-release / build (photographers) (push) Successful in 26s
build-and-release / build (ugc-content-creators) (push) Successful in 14s
build-and-release / build (users) (push) Successful in 14s
build-and-release / build (video-editors) (push) Successful in 14s
build-and-release / build (tutors) (push) Successful in 36s
build-and-release / build (employees) (push) Failing after 1m34s
build-and-release / build (developers) (push) Failing after 1m45s
backend-integration-tests / ai-credits (push) Failing after 54s
2026-08-13 20:24:00 +05:30
Ashwin Kumar Sivakumar
9605636c7f chore: re-trigger ai-credits CI now that nxtgauge_test has the free plan seeded
Some checks failed
backend-integration-tests / ai-credits (push) Waiting to run
build-and-release / build (companies) (push) Successful in 5s
build-and-release / build (developers) (push) Successful in 7s
build-and-release / build (cron) (push) Successful in 8s
build-and-release / build (employees) (push) Successful in 9s
build-and-release / build (fitness-trainers) (push) Has been cancelled
build-and-release / build (catering-services) (push) Successful in 12s
build-and-release / build (customers) (push) Successful in 13s
build-and-release / build (graphic-designers) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 7s
build-and-release / build (jobs) (push) Successful in 6s
build-and-release / build (job-seekers) (push) Successful in 9s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (photographers) (push) Successful in 7s
build-and-release / build (makeup-artists) (push) Successful in 11s
build-and-release / build (social-media-managers) (push) Successful in 6s
build-and-release / build (ugc-content-creators) (push) Successful in 7s
build-and-release / build (users) (push) Successful in 7s
build-and-release / build (tutors) (push) Successful in 12s
build-and-release / build (video-editors) (push) Successful in 11s
pg_dump --schema-only (used to create nxtgauge_test) only copies
structure, not data - the 'free' plan row that 20260703210000's own
INSERT seeds only existed in prod. Applied that migration to
nxtgauge_test directly to seed it there too.
2026-08-13 20:23:50 +05:30
Ashwin Kumar Sivakumar
1106b0cb8c fix: remove invalid trailing line from Dockerfile.test
Some checks failed
build-and-release / build (customers) (push) Successful in 23s
build-and-release / build (catering-services) (push) Successful in 29s
build-and-release / build (developers) (push) Successful in 34s
build-and-release / build (companies) (push) Successful in 41s
build-and-release / build (gateway) (push) Successful in 13s
build-and-release / build (fitness-trainers) (push) Successful in 28s
build-and-release / build (jobs) (push) Successful in 13s
build-and-release / build (job-seekers) (push) Successful in 23s
build-and-release / build (makeup-artists) (push) Successful in 15s
build-and-release / build (graphic-designers) (push) Successful in 40s
build-and-release / build (social-media-managers) (push) Successful in 12s
build-and-release / build (photographers) (push) Successful in 22s
build-and-release / build (tutors) (push) Successful in 21s
build-and-release / build (employees) (push) Failing after 1m40s
build-and-release / build (cron) (push) Failing after 1m42s
build-and-release / build (users) (push) Successful in 20s
build-and-release / build (payments) (push) Successful in 57s
build-and-release / build (video-editors) (push) Successful in 20s
backend-integration-tests / ai-credits (push) Failing after 41s
build-and-release / build (ugc-content-creators) (push) Successful in 1m10s
My own previous trivial-touch commit appended a bare '-- ...' line
without a # prefix, which isn't valid Dockerfile syntax and broke the
buildx parse ('unknown instruction: --') - explains why the last CI
run died immediately again despite the actual fix (corrected password)
being in place.
2026-08-13 20:19:59 +05:30
Ashwin Kumar Sivakumar
f2ee346a37 chore: trivial touch to Dockerfile.test to trigger a real ai-credits CI run
Some checks failed
build-and-release / build (cron) (push) Successful in 27s
build-and-release / build (employees) (push) Successful in 33s
build-and-release / build (companies) (push) Successful in 43s
build-and-release / build (developers) (push) Successful in 52s
build-and-release / build (fitness-trainers) (push) Successful in 29s
build-and-release / build (gateway) (push) Successful in 27s
build-and-release / build (graphic-designers) (push) Successful in 35s
build-and-release / build (jobs) (push) Successful in 28s
build-and-release / build (makeup-artists) (push) Successful in 28s
build-and-release / build (job-seekers) (push) Successful in 46s
build-and-release / build (photographers) (push) Successful in 24s
build-and-release / build (payments) (push) Successful in 37s
build-and-release / build (customers) (push) Failing after 2m0s
build-and-release / build (catering-services) (push) Failing after 2m3s
build-and-release / build (social-media-managers) (push) Successful in 33s
build-and-release / build (ugc-content-creators) (push) Successful in 23s
backend-integration-tests / ai-credits (push) Failing after 9s
build-and-release / build (tutors) (push) Successful in 44s
build-and-release / build (users) (push) Successful in 38s
build-and-release / build (video-editors) (push) Successful in 34s
2026-08-13 20:16:26 +05:30
Ashwin Kumar Sivakumar
786ad41bd8 chore: re-trigger ai-credits CI with corrected TEST_DATABASE_URL password
All checks were successful
build-and-release / build (developers) (push) Successful in 9s
build-and-release / build (companies) (push) Successful in 12s
build-and-release / build (cron) (push) Successful in 16s
build-and-release / build (catering-services) (push) Successful in 19s
build-and-release / build (employees) (push) Successful in 16s
build-and-release / build (fitness-trainers) (push) Successful in 8s
build-and-release / build (gateway) (push) Successful in 7s
build-and-release / build (customers) (push) Successful in 20s
build-and-release / build (graphic-designers) (push) Successful in 6s
build-and-release / build (jobs) (push) Successful in 5s
build-and-release / build (makeup-artists) (push) Successful in 6s
build-and-release / build (job-seekers) (push) Successful in 11s
build-and-release / build (photographers) (push) Successful in 5s
build-and-release / build (payments) (push) Successful in 11s
build-and-release / build (social-media-managers) (push) Successful in 5s
build-and-release / build (ugc-content-creators) (push) Successful in 5s
build-and-release / build (video-editors) (push) Successful in 6s
build-and-release / build (tutors) (push) Successful in 11s
build-and-release / build (users) (push) Successful in 11s
backend-integration-tests / ai-credits (push) Successful in 5s
Discovered POSTGRES_PASSWORD env var on the postgres pod itself is
stale/unused for network auth - pg_hba.conf only trusts it for local
socket connections (no password check at all there). The real
scram-sha-256 password the live app pods actually use over the network
lives in the nxtgauge-backend-rust-secrets K8s secret's DATABASE_URL
key. Used that instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 20:14:04 +05:30
Ashwin Kumar Sivakumar
c307ef1ba4 fix(ci): run ai_credits tests via buildx build, not runtime apt-get/docker run -v
Some checks failed
build-and-release / build (catering-services) (push) Successful in 17s
build-and-release / build (companies) (push) Successful in 30s
build-and-release / build (cron) (push) Successful in 37s
build-and-release / build (developers) (push) Successful in 27s
build-and-release / build (fitness-trainers) (push) Successful in 31s
build-and-release / build (graphic-designers) (push) Successful in 15s
build-and-release / build (job-seekers) (push) Successful in 11s
build-and-release / build (makeup-artists) (push) Successful in 9s
build-and-release / build (payments) (push) Successful in 10s
build-and-release / build (gateway) (push) Successful in 42s
build-and-release / build (photographers) (push) Successful in 14s
build-and-release / build (social-media-managers) (push) Successful in 13s
build-and-release / build (tutors) (push) Successful in 15s
build-and-release / build (ugc-content-creators) (push) Successful in 15s
build-and-release / build (customers) (push) Failing after 1m46s
build-and-release / build (employees) (push) Successful in 2m0s
backend-integration-tests / ai-credits (push) Failing after 58s
build-and-release / build (jobs) (push) Successful in 1m56s
build-and-release / build (video-editors) (push) Successful in 1m34s
build-and-release / build (users) (push) Successful in 2m53s
The bare bookworm runner image has no apt-get/package manager at all
(the earlier build-essential install attempt failed with 'apt-get:
command not found'), and a plain 'docker run -v $PWD:/workspace'
wouldn't work either - DOCKER_HOST points at the sibling dind engine
(same nested-container setup build.yaml's own comments describe), so a
bind mount would look for the path on the wrong filesystem.

Matches build.yaml's actual working pattern instead: docker buildx
build with context transfer (not a volume mount), using a Dockerfile
(Dockerfile.test) whose RUN step runs the test suite and fails the
build on a non-zero exit. TEST_DATABASE_URL passed via buildx --secret
(not --build-arg) so it never lands in image layer history.

Isolated this by testing each piece of the original workflow
independently (env/secrets, id+GITHUB_OUTPUT, if: conditionals all
checked out fine one at a time) until apt-get was confirmed as the
actual failure point.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 18:08:31 +05:30
Ashwin Kumar Sivakumar
a0a4259d50 debug: test apt-get network access in isolation
Some checks failed
build-and-release / build (cron) (push) Successful in 8s
build-and-release / build (companies) (push) Successful in 16s
build-and-release / build (customers) (push) Successful in 17s
build-and-release / build (developers) (push) Successful in 14s
build-and-release / build (employees) (push) Successful in 10s
build-and-release / build (fitness-trainers) (push) Successful in 12s
build-and-release / build (gateway) (push) Successful in 24s
build-and-release / build (graphic-designers) (push) Successful in 32s
build-and-release / build (job-seekers) (push) Successful in 34s
build-and-release / build (jobs) (push) Successful in 25s
build-and-release / build (photographers) (push) Successful in 11s
build-and-release / build (social-media-managers) (push) Successful in 10s
build-and-release / build (makeup-artists) (push) Successful in 33s
build-and-release / build (tutors) (push) Successful in 12s
build-and-release / build (ugc-content-creators) (push) Successful in 11s
build-and-release / build (catering-services) (push) Successful in 1m42s
backend-integration-tests / ai-credits (push) Failing after 4s
build-and-release / build (users) (push) Successful in 1m58s
build-and-release / build (payments) (push) Has been cancelled
build-and-release / build (video-editors) (push) Has been cancelled
2026-08-13 18:04:31 +05:30
Ashwin Kumar Sivakumar
24e85db097 debug: add back a conditional step to isolate the failure further
Some checks failed
build-and-release / build (catering-services) (push) Successful in 20s
build-and-release / build (cron) (push) Successful in 29s
build-and-release / build (companies) (push) Successful in 48s
build-and-release / build (customers) (push) Successful in 1m0s
build-and-release / build (fitness-trainers) (push) Successful in 36s
build-and-release / build (employees) (push) Successful in 58s
build-and-release / build (graphic-designers) (push) Successful in 40s
build-and-release / build (gateway) (push) Successful in 56s
build-and-release / build (jobs) (push) Successful in 35s
build-and-release / build (makeup-artists) (push) Successful in 27s
build-and-release / build (developers) (push) Failing after 1m56s
build-and-release / build (payments) (push) Successful in 30s
build-and-release / build (social-media-managers) (push) Successful in 19s
build-and-release / build (tutors) (push) Successful in 19s
build-and-release / build (ugc-content-creators) (push) Successful in 14s
backend-integration-tests / ai-credits (push) Successful in 5s
build-and-release / build (video-editors) (push) Successful in 12s
build-and-release / build (job-seekers) (push) Successful in 1m38s
build-and-release / build (photographers) (push) Successful in 2m8s
build-and-release / build (users) (push) Successful in 4m15s
2026-08-13 18:01:39 +05:30
Ashwin Kumar Sivakumar
c0a961c8ef debug: add back the check step to isolate the failure further
Some checks failed
build-and-release / build (companies) (push) Successful in 9s
build-and-release / build (cron) (push) Successful in 15s
build-and-release / build (catering-services) (push) Successful in 21s
build-and-release / build (developers) (push) Successful in 14s
build-and-release / build (employees) (push) Successful in 15s
build-and-release / build (fitness-trainers) (push) Successful in 12s
build-and-release / build (gateway) (push) Successful in 14s
build-and-release / build (graphic-designers) (push) Successful in 12s
build-and-release / build (job-seekers) (push) Successful in 10s
build-and-release / build (jobs) (push) Successful in 9s
build-and-release / build (makeup-artists) (push) Successful in 12s
build-and-release / build (photographers) (push) Successful in 10s
build-and-release / build (social-media-managers) (push) Successful in 10s
build-and-release / build (tutors) (push) Successful in 9s
build-and-release / build (customers) (push) Successful in 1m44s
build-and-release / build (video-editors) (push) Successful in 21s
backend-integration-tests / ai-credits (push) Successful in 4s
build-and-release / build (ugc-content-creators) (push) Has been cancelled
build-and-release / build (users) (push) Has been cancelled
build-and-release / build (payments) (push) Has been cancelled
2026-08-13 17:59:04 +05:30
Ashwin Kumar Sivakumar
22cbd3e285 debug: add back job-level env secret reference to isolate the failure
All checks were successful
build-and-release / build (catering-services) (push) Successful in 9s
build-and-release / build (companies) (push) Successful in 8s
build-and-release / build (cron) (push) Successful in 9s
build-and-release / build (customers) (push) Successful in 8s
build-and-release / build (developers) (push) Successful in 9s
build-and-release / build (employees) (push) Successful in 9s
build-and-release / build (fitness-trainers) (push) Successful in 8s
build-and-release / build (gateway) (push) Successful in 9s
build-and-release / build (job-seekers) (push) Successful in 8s
build-and-release / build (jobs) (push) Successful in 9s
build-and-release / build (makeup-artists) (push) Successful in 8s
build-and-release / build (payments) (push) Successful in 9s
build-and-release / build (photographers) (push) Successful in 8s
build-and-release / build (tutors) (push) Successful in 8s
build-and-release / build (ugc-content-creators) (push) Successful in 8s
build-and-release / build (users) (push) Successful in 11s
build-and-release / build (video-editors) (push) Successful in 9s
backend-integration-tests / ai-credits (push) Successful in 4s
build-and-release / build (social-media-managers) (push) Successful in 52s
build-and-release / build (graphic-designers) (push) Successful in 2m33s
2026-08-13 17:55:30 +05:30
Ashwin Kumar Sivakumar
e80c58641f debug: strip test.yaml to bare minimum to isolate why the job dies mid-run
Some checks failed
build-and-release / build (catering-services) (push) Successful in 25s
build-and-release / build (cron) (push) Successful in 33s
build-and-release / build (companies) (push) Successful in 39s
build-and-release / build (developers) (push) Successful in 45s
build-and-release / build (fitness-trainers) (push) Successful in 28s
build-and-release / build (gateway) (push) Successful in 26s
build-and-release / build (graphic-designers) (push) Successful in 31s
build-and-release / build (makeup-artists) (push) Successful in 12s
build-and-release / build (jobs) (push) Successful in 24s
build-and-release / build (photographers) (push) Successful in 9s
build-and-release / build (payments) (push) Successful in 19s
build-and-release / build (social-media-managers) (push) Successful in 14s
build-and-release / build (employees) (push) Failing after 1m46s
build-and-release / build (customers) (push) Failing after 1m48s
backend-integration-tests / ai-credits (push) Successful in 5s
build-and-release / build (tutors) (push) Successful in 1m33s
build-and-release / build (video-editors) (push) Successful in 2m26s
build-and-release / build (users) (push) Successful in 2m52s
build-and-release / build (job-seekers) (push) Successful in 6m30s
build-and-release / build (ugc-content-creators) (push) Successful in 7m36s
2026-08-13 17:53:14 +05:30
Ashwin Kumar Sivakumar
3740bb81c5 fix(ci): fetch full git history in ai-credits job for diff-based change detection
Some checks failed
build-and-release / build (employees) (push) Successful in 18s
build-and-release / build (cron) (push) Successful in 23s
build-and-release / build (gateway) (push) Successful in 9s
build-and-release / build (graphic-designers) (push) Successful in 8s
build-and-release / build (catering-services) (push) Successful in 1m38s
build-and-release / build (jobs) (push) Successful in 9s
build-and-release / build (fitness-trainers) (push) Successful in 1m29s
build-and-release / build (payments) (push) Successful in 9s
build-and-release / build (photographers) (push) Successful in 11s
build-and-release / build (companies) (push) Successful in 2m15s
build-and-release / build (customers) (push) Successful in 2m26s
build-and-release / build (tutors) (push) Successful in 18s
build-and-release / build (developers) (push) Successful in 2m48s
build-and-release / build (video-editors) (push) Successful in 18s
backend-integration-tests / ai-credits (push) Failing after 10s
build-and-release / build (job-seekers) (push) Successful in 2m48s
build-and-release / build (makeup-artists) (push) Successful in 2m0s
build-and-release / build (users) (push) Has been cancelled
build-and-release / build (social-media-managers) (push) Has been cancelled
build-and-release / build (ugc-content-creators) (push) Has been cancelled
Previous job died silently right after checkout with no logs at all
from the 'Check for relevant changes' step onward - shallow clone
(default fetch-depth:1, unlike build.yaml which sets fetch-depth:0)
may have been the cause. Matching build.yaml's checkout config.

Also re-set TEST_DATABASE_URL with a properly percent-encoded password
(the raw '@' in it made the postgresql:// URI ambiguous to parse).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 17:48:43 +05:30
Ashwin Kumar Sivakumar
8893eaa230 chore: re-trigger ai-credits CI job (previous run died mid-checkout, likely runner contention)
Some checks failed
build-and-release / build (companies) (push) Successful in 6s
build-and-release / build (developers) (push) Successful in 10s
build-and-release / build (cron) (push) Successful in 10s
build-and-release / build (catering-services) (push) Successful in 14s
build-and-release / build (employees) (push) Successful in 11s
build-and-release / build (customers) (push) Successful in 14s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 8s
build-and-release / build (graphic-designers) (push) Successful in 8s
build-and-release / build (jobs) (push) Successful in 9s
build-and-release / build (job-seekers) (push) Successful in 12s
build-and-release / build (makeup-artists) (push) Successful in 11s
build-and-release / build (social-media-managers) (push) Successful in 7s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (photographers) (push) Successful in 8s
build-and-release / build (tutors) (push) Successful in 8s
build-and-release / build (ugc-content-creators) (push) Successful in 5s
backend-integration-tests / ai-credits (push) Failing after 6s
build-and-release / build (users) (push) Successful in 11s
build-and-release / build (video-editors) (push) Successful in 10s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 17:45:19 +05:30
Ashwin Kumar Sivakumar
3b4a4eac3f fix(ci): install build-essential before cargo test in ai-credits job
Some checks failed
build-and-release / build (catering-services) (push) Successful in 28s
build-and-release / build (customers) (push) Successful in 30s
build-and-release / build (cron) (push) Successful in 55s
build-and-release / build (companies) (push) Successful in 1m54s
build-and-release / build (job-seekers) (push) Successful in 8s
build-and-release / build (employees) (push) Successful in 2m11s
build-and-release / build (fitness-trainers) (push) Successful in 1m48s
build-and-release / build (developers) (push) Successful in 2m26s
build-and-release / build (gateway) (push) Successful in 2m2s
build-and-release / build (jobs) (push) Successful in 54s
build-and-release / build (graphic-designers) (push) Successful in 2m32s
build-and-release / build (ugc-content-creators) (push) Successful in 8s
build-and-release / build (payments) (push) Successful in 1m50s
build-and-release / build (photographers) (push) Successful in 1m51s
backend-integration-tests / ai-credits (push) Failing after 4s
build-and-release / build (makeup-artists) (push) Successful in 2m32s
build-and-release / build (social-media-managers) (push) Successful in 2m55s
build-and-release / build (tutors) (push) Successful in 2m45s
build-and-release / build (users) (push) Has been cancelled
build-and-release / build (video-editors) (push) Has been cancelled
The bare bookworm runner image has no C toolchain at all, unlike
build.yaml's jobs which build inside a Dockerfile-based image with one
already present. proc-macro2/libc/etc build scripts need `cc` to link
and failed immediately (error: linker `cc` not found) before any real
test code ran.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 17:39:12 +05:30
Ashwin Kumar Sivakumar
da9be7f6a3 feat(db,ci): fix missing ai_credits tables, wire integration tests to CI
Some checks failed
build-and-release / build (cron) (push) Successful in 1m10s
build-and-release / build (developers) (push) Successful in 1m40s
build-and-release / build (catering-services) (push) Successful in 1m58s
build-and-release / build (employees) (push) Successful in 2m19s
build-and-release / build (companies) (push) Successful in 2m36s
build-and-release / build (customers) (push) Successful in 2m45s
build-and-release / build (gateway) (push) Successful in 1m11s
build-and-release / build (jobs) (push) Successful in 40s
build-and-release / build (fitness-trainers) (push) Successful in 2m28s
build-and-release / build (graphic-designers) (push) Successful in 2m14s
build-and-release / build (payments) (push) Successful in 1m48s
build-and-release / build (job-seekers) (push) Successful in 2m57s
build-and-release / build (makeup-artists) (push) Successful in 2m49s
build-and-release / build (photographers) (push) Successful in 2m43s
backend-integration-tests / ai-credits (push) Failing after 31s
build-and-release / build (social-media-managers) (push) Successful in 2m58s
build-and-release / build (tutors) (push) Successful in 2m47s
build-and-release / build (ugc-content-creators) (push) Successful in 2m39s
build-and-release / build (users) (push) Has been cancelled
build-and-release / build (video-editors) (push) Has been cancelled
Re-enables and corrects 20260703210000_ai_credits_wallet, which had been
disabled (.up.sql.skip) in commit 0163349 because 'relation already
exists' aborted the original CREATE TABLE script on its very first
table (ai_plans) - silently leaving ai_credit_ledger and
ai_reservation_holds never created, despite the wallet system being
actively wired into apps/users/handlers/ai_credits.rs, apps/payments,
apps/cron with real subscription rows already in prod.

Rewrote the migration to be idempotent: ADD COLUMN IF NOT EXISTS to
bring ai_plans/user_ai_subscriptions/ai_feature_costs/ai_usage_logs up
to the full column set crates/db/src/models/ai_credits.rs expects
(safe zero/default backfills, no data loss - verified against the 3
existing subscription rows), and CREATE TABLE IF NOT EXISTS for the 2
genuinely-missing tables. down.sql updated to only reverse what this
corrected version actually adds, not drop tables that predate it.

Applied directly to the live database (verified schema + existing rows
intact afterward).

Also wires crates/db/tests/ai_credits.rs + ai_credits_reaper.rs to
Forgejo Actions CI (docs/LIVE_SERVER_RUNBOOK.md step 6):
- New TEST_DATABASE_URL repo secret, pointing at a dedicated
  nxtgauge_test database (created fresh, schema mirrored from live prod
  via pg_dump --schema-only - never runs against the real nxtgauge DB).
- .forgejo/workflows/test.yaml: runs on push to main/high-performance,
  skips when crates/db/ isn't touched, cargo test -p db --test
  ai_credits --test ai_credits_reaper -- --test-threads=1.

Also commits docs/openapi.wallet-holds.json (hand-written minimal
OpenAPI spec used for schemathesis fuzzing in step 4) and gitignores
the local .schemathesis/ cache directory from that run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 17:31:22 +05:30
Ashwin Kumar Sivakumar
6e1041a1f6 chore(deps): document rkyv CVE exemption, restore + expand audit.toml comments
All checks were successful
build-and-release / build (companies) (push) Successful in 5s
build-and-release / build (cron) (push) Successful in 5s
build-and-release / build (developers) (push) Successful in 6s
build-and-release / build (employees) (push) Successful in 6s
build-and-release / build (fitness-trainers) (push) Successful in 6s
build-and-release / build (gateway) (push) Successful in 7s
build-and-release / build (graphic-designers) (push) Successful in 8s
build-and-release / build (job-seekers) (push) Successful in 10s
build-and-release / build (customers) (push) Successful in 20s
build-and-release / build (catering-services) (push) Successful in 21s
build-and-release / build (makeup-artists) (push) Successful in 7s
build-and-release / build (jobs) (push) Successful in 6s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (photographers) (push) Successful in 7s
build-and-release / build (ugc-content-creators) (push) Successful in 7s
build-and-release / build (tutors) (push) Successful in 8s
build-and-release / build (social-media-managers) (push) Successful in 11s
build-and-release / build (users) (push) Successful in 5s
build-and-release / build (video-editors) (push) Successful in 6s
cargo audit flagged RUSTSEC-2026-0235 (rkyv, out-of-bounds read) via
rust_decimal's optional rkyv feature, which apps/payments never enables
(features = ["db-tokio-postgres"] only) - confirmed absent from the
actual feature-resolved graph via cargo tree, and cargo-deny (which is
feature-aware) already doesn't flag it. Added to both deny.toml and
.cargo/audit.toml so cargo audit also exits 0.

Also re-documented the 4 pre-existing crate-name-collision ignores in
.cargo/audit.toml (RUSTSEC-2020-0128/2021-0006/2023-0040/2023-0059 -
our own workspace crates crates/cache and apps/users happen to share
name+version with unrelated abandoned crates.io packages) with fuller
explanation, and mirrored them into deny.toml for a single source of
truth even though cargo-deny's real graph resolution never matched
them in the first place.

Verified: cargo audit and cargo deny check advisories bans both now
exit 0 against the live server runbook's requirement.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 23:30:30 +05:30
Ashwin Kumar Sivakumar
f007ca0999 fix(db): re-enable wallet_full migration (tracecoin_holds/buckets)
All checks were successful
build-and-release / build (gateway) (push) Successful in 49s
build-and-release / build (employees) (push) Successful in 1m46s
build-and-release / build (ugc-content-creators) (push) Successful in 2m36s
build-and-release / build (companies) (push) Successful in 1m55s
build-and-release / build (catering-services) (push) Successful in 2m48s
build-and-release / build (fitness-trainers) (push) Successful in 1m45s
build-and-release / build (makeup-artists) (push) Successful in 1m43s
build-and-release / build (payments) (push) Successful in 2m52s
build-and-release / build (tutors) (push) Successful in 2m54s
build-and-release / build (job-seekers) (push) Successful in 7m28s
build-and-release / build (developers) (push) Successful in 2m28s
build-and-release / build (photographers) (push) Successful in 2m37s
build-and-release / build (video-editors) (push) Successful in 2m32s
build-and-release / build (users) (push) Successful in 4m55s
build-and-release / build (social-media-managers) (push) Successful in 7m32s
build-and-release / build (customers) (push) Successful in 2m11s
build-and-release / build (cron) (push) Successful in 2m14s
build-and-release / build (jobs) (push) Successful in 39s
build-and-release / build (graphic-designers) (push) Successful in 2m0s
20260627030000_wallet_full.up.sql was disabled in 0163349 as part of a
bulk cleanup of migrations referencing the dropped professionals
table, but this one doesn't touch that table at all - it only
references tracecoin_wallets, tracecoin_ledger and users, all of
which already exist in prod. It was swept up by mistake.

Without it, tracecoin_holds/tracecoin_buckets never got created, so
the new GET /wallet/me/holds route (crates/contracts/src/profession_shared.rs)
500s with 'relation "tracecoin_holds" does not exist'.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 23:18:51 +05:30
Ashwin Kumar Sivakumar
b30629411a fix(ci): diff/scan full pushed commit range, not just HEAD^..HEAD
All checks were successful
build-and-release / build (customers) (push) Successful in 2m42s
build-and-release / build (developers) (push) Successful in 1m46s
build-and-release / build (graphic-designers) (push) Successful in 2m43s
build-and-release / build (tutors) (push) Successful in 2m44s
build-and-release / build (catering-services) (push) Successful in 1m49s
build-and-release / build (fitness-trainers) (push) Successful in 1m48s
build-and-release / build (photographers) (push) Successful in 2m55s
build-and-release / build (users) (push) Successful in 4m57s
build-and-release / build (gateway) (push) Successful in 1m22s
build-and-release / build (payments) (push) Successful in 2m12s
build-and-release / build (ugc-content-creators) (push) Successful in 2m44s
build-and-release / build (companies) (push) Successful in 1m59s
build-and-release / build (social-media-managers) (push) Successful in 2m42s
build-and-release / build (job-seekers) (push) Successful in 7m6s
build-and-release / build (video-editors) (push) Successful in 2m42s
build-and-release / build (cron) (push) Successful in 2m9s
build-and-release / build (employees) (push) Successful in 2m30s
build-and-release / build (makeup-artists) (push) Successful in 2m40s
build-and-release / build (jobs) (push) Successful in 6m53s
Multi-commit pushes (e.g. this repo's mirror sync from GitHub) were
silently skipping every service's build: the 'does this service need
building' check only looked at the last commit vs its immediate
parent. A push landing 3 commits where only the final one was a no-op
(docs/.gitignore) meant the actual code commit's changes were never
seen, so all 19 services reported 'no changes relevant - skipping'
even though real backend code had changed.

Use github.event.before (the pre-push SHA) to diff/scan the whole
pushed range when available, falling back to HEAD^..HEAD only when
that ref is unavailable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 22:18:37 +05:30
Tracewebstudio Dev
7b4a23cee6 chore: gitignore *.pid runtime files
All checks were successful
build-and-release / build (companies) (push) Successful in 14s
build-and-release / build (developers) (push) Successful in 13s
build-and-release / build (customers) (push) Successful in 15s
build-and-release / build (employees) (push) Successful in 15s
build-and-release / build (catering-services) (push) Successful in 19s
build-and-release / build (cron) (push) Successful in 18s
build-and-release / build (fitness-trainers) (push) Successful in 6s
build-and-release / build (graphic-designers) (push) Successful in 6s
build-and-release / build (gateway) (push) Successful in 7s
build-and-release / build (job-seekers) (push) Successful in 8s
build-and-release / build (makeup-artists) (push) Successful in 8s
build-and-release / build (jobs) (push) Successful in 8s
build-and-release / build (payments) (push) Successful in 6s
build-and-release / build (social-media-managers) (push) Successful in 6s
build-and-release / build (photographers) (push) Successful in 7s
build-and-release / build (tutors) (push) Successful in 8s
build-and-release / build (ugc-content-creators) (push) Successful in 8s
build-and-release / build (users) (push) Successful in 7s
build-and-release / build (video-editors) (push) Successful in 7s
PID files are created by running services locally and should never
be tracked in version control.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-12 18:25:40 +02:00
Tracewebstudio Dev
9e37060737 docs: add live server runbook
All checks were successful
build-and-release / build (cron) (push) Successful in 12s
build-and-release / build (customers) (push) Successful in 16s
build-and-release / build (employees) (push) Successful in 15s
build-and-release / build (companies) (push) Successful in 18s
build-and-release / build (developers) (push) Successful in 17s
build-and-release / build (catering-services) (push) Successful in 19s
build-and-release / build (fitness-trainers) (push) Successful in 5s
build-and-release / build (graphic-designers) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 6s
build-and-release / build (job-seekers) (push) Successful in 6s
build-and-release / build (makeup-artists) (push) Successful in 8s
build-and-release / build (jobs) (push) Successful in 9s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (photographers) (push) Successful in 6s
build-and-release / build (social-media-managers) (push) Successful in 7s
build-and-release / build (ugc-content-creators) (push) Successful in 7s
build-and-release / build (tutors) (push) Successful in 8s
build-and-release / build (video-editors) (push) Successful in 7s
build-and-release / build (users) (push) Successful in 9s
Covers everything that needs a running DB/server:
- Deploy the backend changes (wallet holds, printpdf upgrade)
- Verify /wallet/me/holds endpoint with curl
- cargo audit + cargo deny check
- Schemathesis API fuzzing setup
- Playwright e2e tests
- CI integration tests with TEST_DATABASE_URL
- npm run lint and tsc --noEmit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-12 13:39:36 +02:00
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
ddb2110e86 fix: return JSON errors from create_job and add admin job-slot grant endpoint
All checks were successful
build-and-release / build (customers) (push) Successful in 8s
build-and-release / build (catering-services) (push) Successful in 11s
build-and-release / build (fitness-trainers) (push) Successful in 7s
build-and-release / build (developers) (push) Successful in 12s
build-and-release / build (cron) (push) Successful in 18s
build-and-release / build (employees) (push) Successful in 16s
build-and-release / build (gateway) (push) Successful in 8s
build-and-release / build (job-seekers) (push) Successful in 5s
build-and-release / build (graphic-designers) (push) Successful in 7s
build-and-release / build (jobs) (push) Successful in 7s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (makeup-artists) (push) Successful in 6s
build-and-release / build (photographers) (push) Successful in 5s
build-and-release / build (tutors) (push) Successful in 5s
build-and-release / build (social-media-managers) (push) Successful in 5s
build-and-release / build (ugc-content-creators) (push) Successful in 6s
build-and-release / build (users) (push) Successful in 5s
build-and-release / build (video-editors) (push) Successful in 4s
build-and-release / build (companies) (push) Successful in 1m21s
create_job returned plain-text bodies on every failure branch except
quota-exhausted, so the frontend's res.json() silently failed and always
showed a generic "Failed to create job" message regardless of the real
cause (company not approved, quota exhausted, DB error).

Also adds PATCH /api/admin/companies/{id}/job-slots as a manual top-up
for purchased_job_slots, since no self-serve purchase flow exists yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 17:04:00 +05:30
Ashwin Kumar Sivakumar
b281eb5278 fix: profile approval 500 — users table has no role column
All checks were successful
build-and-release / build (employees) (push) Successful in 11s
build-and-release / build (cron) (push) Successful in 13s
build-and-release / build (catering-services) (push) Successful in 17s
build-and-release / build (companies) (push) Successful in 17s
build-and-release / build (customers) (push) Successful in 17s
build-and-release / build (developers) (push) Successful in 16s
build-and-release / build (fitness-trainers) (push) Successful in 5s
build-and-release / build (graphic-designers) (push) Successful in 7s
build-and-release / build (gateway) (push) Successful in 7s
build-and-release / build (job-seekers) (push) Successful in 7s
build-and-release / build (jobs) (push) Successful in 8s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (makeup-artists) (push) Successful in 10s
build-and-release / build (photographers) (push) Successful in 7s
build-and-release / build (social-media-managers) (push) Successful in 8s
build-and-release / build (tutors) (push) Successful in 8s
build-and-release / build (ugc-content-creators) (push) Successful in 7s
build-and-release / build (video-editors) (push) Successful in 8s
build-and-release / build (users) (push) Successful in 2m45s
activate_profile_after_final_approval ran UPDATE users SET role = $1,
but users only has role_id (FK into roles), never a plain role column.
Resolve the role's id via RoleRepository::get_by_key first and update
role_id instead, matching how role is tracked everywhere else.
2026-07-31 16:52:33 +05:30
Tracewebstudio Dev
2f47308498 fix: verification submission no longer blocks login or misreports status
All checks were successful
build-and-release / build (customers) (push) Successful in 12s
build-and-release / build (catering-services) (push) Successful in 15s
build-and-release / build (developers) (push) Successful in 13s
build-and-release / build (cron) (push) Successful in 17s
build-and-release / build (employees) (push) Successful in 5s
build-and-release / build (gateway) (push) Successful in 5s
build-and-release / build (fitness-trainers) (push) Successful in 6s
build-and-release / build (graphic-designers) (push) Successful in 7s
build-and-release / build (makeup-artists) (push) Successful in 5s
build-and-release / build (jobs) (push) Successful in 8s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (photographers) (push) Successful in 7s
build-and-release / build (social-media-managers) (push) Successful in 5s
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 4s
build-and-release / build (companies) (push) Successful in 1m10s
build-and-release / build (job-seekers) (push) Successful in 1m8s
build-and-release / build (users) (push) Successful in 3m7s
- submit_for_verification: stop downgrading user_role_assignments.status
  to PENDING. This was locking users out of login while their verification
  was under review. Verification progress is tracked in the verifications
  table; role assignment stays APPROVED throughout.

- verification_status: remove role_assignment_approved from the status
  calculation. Because the assignment now stays APPROVED, using it as a
  proxy was incorrectly overriding PENDING verification status to APPROVED
  immediately after submission.

- companies submit_with_documents: encode document_type from filename
  prefix before '|' separator (set by frontend) rather than file stem;
  add duplicate-verification guard to match users service.

- job_seekers: add get_or_create_job_seeker_profile helper to ensure
  profile row exists before upsert operations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-30 15:36:12 +02:00
Tracewebstudio Dev
5f1b48d27b fix: sync profile approval unlock state
All checks were successful
build-and-release / build (developers) (push) Successful in 9s
build-and-release / build (customers) (push) Successful in 13s
build-and-release / build (companies) (push) Successful in 12s
build-and-release / build (cron) (push) Successful in 15s
build-and-release / build (catering-services) (push) Successful in 14s
build-and-release / build (fitness-trainers) (push) Successful in 6s
build-and-release / build (employees) (push) Successful in 15s
build-and-release / build (gateway) (push) Successful in 6s
build-and-release / build (graphic-designers) (push) Successful in 7s
build-and-release / build (job-seekers) (push) Successful in 6s
build-and-release / build (payments) (push) Successful in 7s
build-and-release / build (jobs) (push) Successful in 8s
build-and-release / build (makeup-artists) (push) Successful in 9s
build-and-release / build (photographers) (push) Successful in 6s
build-and-release / build (social-media-managers) (push) Successful in 7s
build-and-release / build (ugc-content-creators) (push) Successful in 6s
build-and-release / build (tutors) (push) Successful in 8s
build-and-release / build (video-editors) (push) Successful in 9s
build-and-release / build (users) (push) Successful in 6m14s
2026-07-29 15:14:37 +02:00