# FastAPI Middleware Server Sync Fix

**Date:** 2026-02-08
**Issue:** Dashboard not updating after Trinity inference
**Root Cause:** FastAPI middleware only talked to daemon, never synced to server

---

## The Bug

The FastAPI middleware (`lockstock_fastapi/middleware.py`) was **incomplete**:

### Before Fix:
```python
async def dispatch(self, request: Request, call_next):
    # 1. Get chain state from daemon ✅
    chain_state = await self._get_chain_state(self.agent_id)

    # 2. Sign and advance via daemon ✅
    sign_result = await self._sign_and_advance(...)

    # 3. Call inference ✅
    response = await call_next(request)

    # 4. Add headers ✅
    response.headers["X-LockStock-Seq"] = str(sign_result["new_sequence"])

    return response
    # ❌ NO SERVER SYNC!
```

**Problem:** Chain advanced locally but server never knew about it.
**Impact:** Dashboard showed no activity, audit trail empty.

### Documentation Claimed:
> "Middleware automatically: 1. Advances chain before inference, 2. Adds X-LockStock-* headers, **3. Logs to audit trail**"

**The code did NOT do #3!**

---

## The Fix

Added server sync matching the OpenAI Guardrail implementation:

### Changes Made:

1. **Added httpx import** (line 23)
2. **Added server_url parameter** to `__init__`
3. **Added server_sync parameter** (default: `True`)
4. **Created HTTP client** in `__init__`
5. **Added `_verify_with_server()` method** (copied from OpenAI Guardrail)
6. **Called server sync** after daemon signing

### After Fix:
```python
async def dispatch(self, request: Request, call_next):
    async with _chain_lock:
        # 1. Get chain state from daemon ✅
        chain_state = await self._get_chain_state(self.agent_id)

        # 2. Sign and advance via daemon ✅
        sign_result = await self._sign_and_advance(...)

        # 3. Sync to server ✅ NEW!
        if self.server_sync:
            verify_result = await self._verify_with_server(
                task=self.task,
                signature=sign_result["signature"],
                parent_hash=parent_hash,
                state_matrix=sign_result["new_matrix"],
                timestamp=sign_result["timestamp"],
                sequence=sign_result["new_sequence"]
            )

    # 4. Call inference ✅
    response = await call_next(request)

    # 5. Add headers ✅
    response.headers["X-LockStock-Seq"] = str(sign_result["new_sequence"])

    return response
```

---

## New Configuration Options

### Constructor Parameters:
```python
app.add_middleware(
    LockStockMiddleware,
    agent_id="agent_abc123",
    guard_socket="/var/run/lockstock-guard/guard.sock",
    server_url="https://lockstock-api-i9kp.onrender.com",  # NEW
    server_sync=True  # NEW (default: True)
)
```

### Environment Variables:
```bash
export LOCKSTOCK_SERVER_URL=https://lockstock-api-i9kp.onrender.com
export LOCKSTOCK_SERVER_SYNC=true  # Set to "false" to disable
```

---

## Behavior

### Default (server_sync=True):
- Daemon signs locally ✅
- Server receives `/verify` call ✅
- Redis gets event published ✅
- guard-ingest writes to PostgreSQL ✅
- Dashboard updates ✅

### If server sync fails:
- Logs warning (doesn't block request)
- Chain still advanced locally
- Request continues to inference
- Offline-first behavior preserved

### Disabled (server_sync=False):
- Only daemon signing
- No server calls
- Offline-first mode
- Use case: air-gapped environments

---

## Testing

### Verify Server Sync is Working:

**Before request:**
```bash
# Check dashboard - note current sequence
curl -s https://lockstock-api-i9kp.onrender.com/api/guard/agents | \
  python3 -m json.tool | grep -A5 "agent_abc123"
```

**Send request:**
```bash
curl -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "Hello"}]}'
```

**After request:**
```bash
# Dashboard should show new sequence
curl -s https://lockstock-api-i9kp.onrender.com/api/guard/agents | \
  python3 -m json.tool | grep -A5 "agent_abc123"
```

**Check audit stream:**
```bash
# Visit dashboard: https://d3cipher.ai/dashboard.html
# Audit Stream should show new entry with task="network"
```

---

## Impact on Trinity

Trinity uses FastAPI middleware via the OpenAI adapter. With this fix:

1. ✅ Trinity inference advances daemon chain
2. ✅ Middleware calls `/verify` endpoint
3. ✅ Server receives and validates signature
4. ✅ Redis publishes to `guard_traffic` channel
5. ✅ guard-ingest worker writes to PostgreSQL
6. ✅ Dashboard shows Trinity activity

**No changes needed to Trinity code.** The middleware fix is transparent.

---

## Why This Happened

### Timeline:
1. **Feb 6, 2026**: FastAPI middleware added (`97e3970`)
2. Commit message claimed: "Closes gap in dashboard provisioning flow"
3. README documentation promised: "Logs to audit trail"
4. **But code only did daemon signing, not server sync**

### Why:
- OpenAI Guardrail was built first (complete with server sync)
- FastAPI middleware was built second (incomplete)
- Documentation was aspirational, not actual
- No one tested dashboard visibility

### Root Cause:
**Inconsistent implementation between integrations.**

- OpenAI Guardrail: daemon + server ✅
- FastAPI Middleware: daemon only ❌

---

## Next Steps

### Immediate:
- [x] Fix middleware to add server sync
- [ ] Test with Trinity
- [ ] Verify dashboard updates
- [ ] Release as v1.1.3

### Short-term:
- [ ] Add integration tests that verify server sync
- [ ] Update all examples to show server_sync parameter
- [ ] Add dashboard verification to deployment checklist

### Long-term:
- [ ] Rebuild Trinity as OpenAI Agent (proper solution)
- [ ] Use standard guardrail instead of custom middleware
- [ ] Single Docker image deployment

---

## Related Documentation

- `WHY_NOT_PLUG_AND_PLAY_YET.md` - Analysis of packaging gap
- `TRINITY_LOCKSTOCK_ROADMAP.md` - Long-term solution plan
- `TRINITY_RUNPOD_DEPLOYMENT_CHECKLIST.md` - Deployment guide

---

**Bottom Line:**

The technology worked. The middleware was just missing 20 lines of code.

Now FastAPI middleware matches OpenAI Guardrail behavior:
- **Daemon signing** for offline-first operation
- **Server sync** for dashboard visibility and audit trail

**This is what the documentation promised. Now the code delivers it.**

---

**Created:** 2026-02-08 05:15 UTC
**Author:** Claude Sonnet 4.5
**Status:** ✅ Fixed and ready for testing
