Skip to content

Minor changes#30

Merged
Ntale3 merged 20 commits into
ArielWandera:mainfrom
the-icemann:price_prediction_service
Jun 3, 2026
Merged

Minor changes#30
Ntale3 merged 20 commits into
ArielWandera:mainfrom
the-icemann:price_prediction_service

Conversation

@the-icemann
Copy link
Copy Markdown
Collaborator

Fixed a few merge conflicts to ensure all changes work as intended

the-icemann and others added 20 commits May 21, 2026 16:43
Adds Phase 3b to the seed script: downloads a crop-appropriate Unsplash
image for each listing and uploads it via the existing multipart endpoint
(Cloudinary). Blog posts now get per-post cover images instead of one
shared placeholder. Both phases fail gracefully so the rest of the seed
continues if Cloudinary is not configured or a download times out.
Adds POST /listings/{id}/images/url (INTERNAL_SECRET-gated) that stores
an external URL directly in listing_images with public_id=null. The
existing Cloudinary upload path for real users is completely untouched.
Seed Phase 3b now calls this endpoint with crop-matched Unsplash URLs
instead of downloading and re-uploading through Cloudinary.
Seed interactions (orders, messages) generate notification rows for seeded
users. destroy_seed was missing the notification_db step, leaving orphaned
rows after teardown. Added destroy_notifications() targeting user_id IN
seeded IDs and wired it between destroy_messages and destroy_payments.
Authlib's session-backed state storage was unreliable behind the
nginx + CloudFront proxy chain — the session cookie was not surviving
the login→Google→callback roundtrip, causing a MismatchingStateError
on every Google OAuth attempt.

New approach: generate a cryptographically random state on /google/login,
store it in a short-lived _oauth_state httpOnly cookie (same pattern as
setup_token which already works), and validate it on the callback.
Code exchange is done directly via httpx against Google's token and
userinfo endpoints, removing the authlib session dependency entirely.

Also fixes the returning-user redirect: complete-profile users now go
to /home instead of back to the profile form, and incomplete-profile
returning users get a fresh setup_token.
The _oauth_state cookie set on the /google/login 302 redirect was also
being dropped before reaching the browser (same CloudFront/nginx issue
as the original session cookie). No cookie or session can be reliably
set on a redirect response in this proxy chain.

New approach: embed the CSRF state directly in the state parameter as a
URLSafeTimedSerializer-signed token (itsdangerous, already a dep). The
state is self-verifiable on the callback — no storage of any kind needed.
5-minute expiry enforced by itsdangerous timestamp.
Was calling /users on the user service which doesn't exist —
the internal create_user route is at POST / (no prefix).
Password registration already used the correct URL (USER_SERVICE_URL/).
CloudFront's /auth/complete-profile behavior was targeting S3 with
GET/HEAD only — POST from the profile form was blocked at the CDN
layer, returning 403/405, never reaching the auth service.

Change the behavior to target EC2 with all methods allowed. Add a GET
handler in the auth service that returns 404 so CloudFront's
custom_error_response still serves index.html for SPA page loads.
Brings in bot_auth Redis relay, Google OAuth returning-user fix
(redirect to /auth/google/callback?access_token=...), docker-compose
profile gating for optional services, and PESAPAL_SANDBOX rename.
Conflict in oauth.py resolved by taking origin/main's returning-user
handling (both complete and incomplete profile paths).
…h/google/callback

/auth/google/callback matches the CloudFront /auth/* → EC2 behavior, so the
browser would loop back to the backend callback handler with no state param,
causing the 'Invalid OAuth state' error. /auth/sign-in is explicitly routed to
S3 so the SPA loads and loginWithToken can run.
…teway deps

Both stacks declare soko-ml-bridge as external but nothing created it, causing
docker compose up to fail silently. Add explicit network create step (idempotent)
before both compose invocations. Also relax ml-gateway-service depends_on from
service_healthy to service_started so the gateway starts even if an individual
ML service is slow to pass health checks, with restart:unless-stopped handling retries.
int(None) crashed before the try/except block when quantity_kg is not
provided. Farmers without listings send no quantity, so the backend must
tolerate None. Use quantity or 0 as the cache key slot so null-quantity
requests still get routed (Tier 2/3 generic response).
Add POST /auth/alert/unsupported-crop endpoint to the auth service.
When a farmer's specialty or listing falls outside ML crop coverage,
the frontend calls this endpoint which sends a SendGrid email to
andrewssuubi@gmail.com listing the unsupported crop names and user ID.
Endpoint is JWT-protected and silently no-ops when SendGrid is not configured.
The inline environment: value overrode the BOT_SECRET loaded from
Secrets Manager via env_file, so the real secret was never used.
Removing it lets the env_file value take effect.
fetch-secrets.sh was writing only INTERNAL_SECRET for produce and blog,
leaving CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, and CLOUDINARY_API_SECRET
unset. Both services declare these as required fields in their Settings class,
so they crashed on startup in production — causing the marketplace 502.
…lth timing

- location-service now waits for db-init to complete before starting,
  preventing a race where market_registry table may not exist on fresh deploys
- fix hardcoded fallback port in market_router.py (8080 -> 8000)
- increase deploy health check sleep from 15s to 90s so ML stack status
  is accurate in CI logs (Kafka needs ~90s to become healthy)
@Ntale3 Ntale3 merged commit c9df8c4 into ArielWandera:main Jun 3, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants