Skip to content

Add CORS middleware and Yellow Network stub endpoints#4

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/implement-stub-backend
Draft

Add CORS middleware and Yellow Network stub endpoints#4
Copilot wants to merge 2 commits intomainfrom
copilot/implement-stub-backend

Conversation

Copy link
Contributor

Copilot AI commented Mar 3, 2026

Implements a production-ready stub backend for Railway deployment, adding CORS support, a proper receipt verification endpoint, and Yellow Network session/order management routes.

CORS (main.py)

  • Added CORSMiddleware with allow_origins=["*"], allow_credentials=False — wildcard + credentials is a browser security violation per CORS spec

Receipt verification (routes/receipt.py, models/receipt.py)

  • Replaced untyped dict input with ReceiptVerifyRequest Pydantic model (payload: dict, signature: str)
  • Response corrected to {"valid": true} (was {"verified": true})

Yellow Network (routes/yellow.py, models/yellow.py)

Three new endpoints registered under /v1/yellow:

POST /v1/yellow/session/preflight   → { valid, expires_at, allowance_remaining }
POST /v1/yellow/order/submit        → { order_id, status: "SUBMITTED" }
GET  /v1/yellow/order/{id}/status   → { status, details }  (404 on unknown)

Orders stored in an in-memory dict; no DB required for this stub. All inputs/outputs are validated via Pydantic models.

Original prompt

Objective

Implement a production-ready stub backend for Railway deployment that integrates with the Yellow Network protocol. The implementation includes CORS middleware, health check endpoint, intent evaluation with signed receipts, receipt verification, and Yellow Network session/order management.

Requirements

1. CORS Middleware

  • Enable CORS middleware in main.py
  • Temporarily allow all origins for MVP: allow_origins=["*"]

2. Health Endpoint

  • GET /health
  • Response: {"status": "ok"}
  • Already exists, ensure it's working

3. Intent Evaluation Endpoint

  • POST /v1/intent/evaluate
  • Ensure existing endpoint works
  • Returns signed receipt object:
{
  "payload": {
    "intent": {...},
    "decision": {
      "status": "PASS" or "FAIL",
      "reason": "string"
    }
  },
  "signature": "string"
}

4. Receipt Verification Endpoint

  • POST /v1/receipt/verify
  • Input:
{
  "payload": {...},
  "signature": "string"
}
  • Output: {"valid": true}
  • Stub implementation that always returns valid=true

5. Yellow Network Endpoints

Create new router routes/yellow.py with:

POST /v1/yellow/session/preflight

  • Input: {"session_key": "string", "wallet": "string"}
  • Output: {"valid": true, "expires_at": 1700000000, "allowance_remaining": 1000}

POST /v1/yellow/order/submit

  • Input: {"intent": {...}, "receipt": {...}}
  • Output: {"order_id": "order_123", "status": "SUBMITTED"}

GET /v1/yellow/order/{order_id}/status

  • Output: {"status": "SUBMITTED" | "MATCHED" | "ESCROW_LOCKED" | "SETTLED", "details": {}}

Implementation Details

  • Store orders in memory using a simple dictionary
  • Default order status: "SUBMITTED"
  • No database required
  • Use Pydantic models for request/response validation
  • Keep code clean and structured
  • Register yellow router in main.py with prefix="/v1/yellow"
  • Do not modify unrelated files

Project Structure

apps/api/app/
  main.py (updated with CORS and yellow router)
  routes/
    health.py (existing)
    intent.py (to be created or verified)
    receipt.py (update with proper Pydantic models)
    yellow.py (new)
  models/
    intent.py (create if needed)
    receipt.py (create if needed)
    yellow.py (new)

This pull request was created from Copilot chat.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Note

Adjust whitespace in stub backend files for Railway deployment to prepare WIP production-ready backend

Change only blank lines across affected files to modify whitespace formatting.

📍Where to Start

Start with the main backend entrypoint to view whitespace changes in server/main.go.

📊 Macroscope summarized e4dec87. 4 files reviewed, 1 issue evaluated, 0 issues filtered, 1 comment posted

🗂️ Filtered Issues

Co-authored-by: Mharris40 <150187165+Mharris40@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement production-ready stub backend for Railway deployment Add CORS middleware and Yellow Network stub endpoints Mar 3, 2026
Comment on lines +25 to +31
@router.post("/order/submit", response_model=OrderSubmitResponse)
def order_submit(request: OrderSubmitRequest):
global _order_counter
_order_counter += 1
order_id = f"order_{_order_counter}"
_orders[order_id] = {"status": "SUBMITTED", "details": {}}
return OrderSubmitResponse(order_id=order_id, status="SUBMITTED")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High routes/yellow.py:25

Concurrent requests read _order_counter before either has incremented it, so both threads compute the same order_id and the second order silently overwrites the first in _orders. This loses the first order's data without any error being raised. Consider using threading.Lock to serialize access to the counter and dictionary, or switch to an atomic counter (e.g., itertools.count with a lock, or UUIDs).

+import threading
+
+_order_lock = threading.Lock()
+
 @router.post("/order/submit", response_model=OrderSubmitResponse)
 def order_submit(request: OrderSubmitRequest):
     global _order_counter
-    _order_counter += 1
-    order_id = f"order_{_order_counter}"
-    _orders[order_id] = {"status": "SUBMITTED", "details": {}}
+    with _order_lock:
+        _order_counter += 1
+        order_id = f"order_{_order_counter}"
+        _orders[order_id] = {"status": "SUBMITTED", "details": {}}
     return OrderSubmitResponse(order_id=order_id, status="SUBMITTED")
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/api/app/routes/yellow.py around lines 25-31:

Concurrent requests read `_order_counter` before either has incremented it, so both threads compute the same `order_id` and the second order silently overwrites the first in `_orders`. This loses the first order's data without any error being raised. Consider using `threading.Lock` to serialize access to the counter and dictionary, or switch to an atomic counter (e.g., `itertools.count` with a lock, or UUIDs).

Evidence trail:
apps/api/app/routes/yellow.py lines 12-13 (global `_orders` dict and `_order_counter`), lines 25-30 (`order_submit` function with non-atomic `_order_counter += 1` and dict assignment). Python's `+=` operator is not atomic - it involves separate LOAD, ADD, STORE bytecode operations that can interleave between threads.

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