[integrations] open-brain-rest — Cloudflare Worker REST gateway for the Next.js dashboard#239
Open
tswicegood wants to merge 7 commits intoNateBJones-Projects:mainfrom
Conversation
Adds the directory layout and Hono application shell for a Cloudflare
Worker REST gateway that backs dashboards/open-brain-dashboard-next.
Includes:
- package.json + tsconfig + wrangler.toml.example + .gitignore
- src/index.ts with Hono app, CORS middleware, /health pre-auth, and
a requireApiKey gate for everything else
- src/lib/{auth,types,supabase,embedding,responses}.ts utilities
- src/routes/health.ts
Auth pattern (x-brain-key / Authorization: Bearer / ?key=) matches
existing Open Brain integrations. No endpoints implemented yet beyond
/health — subsequent commits add thoughts CRUD, search, stats, and
capture.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements the four endpoints the dashboard's lib/api.ts uses to render
the Browse, Detail, and Audit pages:
GET /thoughts — paginated list (page, per_page, type,
source_type, importance_min,
quality_score_max, sort, order, status,
exclude_restricted)
GET /thought/:id — single row, 404 on miss
PUT /thought/:id — partial update of {content, type,
importance, status}; updates
status_updated_at when status changes
DELETE /thought/:id — hard delete, 204 on success, 404 on miss
Sort column is whitelisted (created_at, updated_at, importance,
quality_score, type, source_type, status) to keep arbitrary client
input out of the ORDER BY clause. exclude_restricted defaults true and
filters sensitivity_tier='restricted', matching the convention used by
the brain_stats_aggregate RPC in schemas/enhanced-thoughts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds two endpoints used by the dashboard's Search and Dashboard pages:
POST /search { query, mode, limit, page, exclude_restricted }
- mode=semantic: embed the query via OpenRouter
(text-embedding-3-small, same model as open-brain-mcp), call the
core match_thoughts RPC for candidate IDs + similarity, then
re-fetch full Thought rows and stitch similarity back. Over-fetches
3x to absorb sensitivity_tier='restricted' filtering.
- mode=text: call search_thoughts_text RPC (from
schemas/enhanced-thoughts), post-filter restricted in JS, slice to
limit. Uses the RPC's denormalized total_count for pagination.
GET /stats?days=&exclude_restricted=
- calls brain_stats_aggregate RPC and reshapes the payload from
{ total, top_types, top_topics } into the dashboard's
StatsResponse shape ({ total_thoughts, window_days, types,
top_topics }). days=0 reports window_days='all'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the /capture endpoint that backs the dashboard's "Add to Brain"
single-thought flow, plus stubs for the smart-ingest endpoints:
POST /capture { content }
- Runs metadata extraction (gpt-4o-mini JSON mode) and embedding
(text-embedding-3-small) in parallel via OpenRouter
- Calls the existing upsert_thought RPC (defined in
docs/01-getting-started.md Step 2.6) for dedup-aware insertion
- Backfills embedding + type + source_type='rest-gateway' on the
returned row
- Responds with the dashboard's CaptureResult shape:
{ thought_id, action, type, sensitivity_tier,
content_fingerprint, message }
GET /ingestion-jobs → { jobs: [], count: 0 }
GET /ingestion-jobs/:id → 404
POST /ingestion-jobs/:id/execute → 501
POST /ingest → 501
The dashboard's Ingest page renders cleanly against an empty list.
The dashboard's Add to Brain extract-mode + execute flows surface 501
errors — documented in the integration README as out-of-scope-for-v1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the integration's README (architecture, prerequisites, 5-step setup, dashboard wiring, Cloudflare Pages instructions for the Next.js frontend, known limitations, troubleshooting) and a one-paragraph pointer in dashboards/open-brain-dashboard-next/README.md so anyone who lands there can find the missing backend. Known limitations are documented honestly: Thought.id is UUID (not number), importance scale mismatch (3 vs 80+), no reflections table, no smart-ingest. These are upstream concerns out of scope for this PR; the four core dashboard pages still work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author
|
Claude got a little ambitious here and opened this draft PR before I've finished it. Was planning on opening it at some point, but will come back to this once I've verified everything. I'm testing it against the dashboard and decided to deploy to Cloudflare since I'm running #238 in production already. |
text-embedding-3-small produces cosine similarities in the ~0.2-0.5 range for clearly related content; only near-paraphrases climb above 0.5. The previous 0.5 default starved semantic search of real results — verified end-to-end against the dashboard, where every query returned zero rows even though match_thoughts at threshold 0 returned candidates with similarity 0.31-0.37 to the query. Drops the constant to 0.2 and exposes it as an optional `threshold` field on the /search request body so callers with pickier needs can override. Also adds package-lock.json to .gitignore — wrangler bundles deps at deploy time, so the lockfile isn't needed for reproducibility and would just churn the diff. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nnextjs/cloudflare The previous instructions pointed at @cloudflare/next-on-pages, but that adapter caps at Next 15.5.x. The dashboards/open-brain-dashboard-next package ships Next 16, so the documented deploy path was unrunnable. Updates the "Deploying the Dashboard to Cloudflare" section to use the @opennextjs/cloudflare adapter (Cloudflare's current path for Next 15+), which deploys the app as a Worker with static assets, and notes that NEXT_PUBLIC_API_URL is build-time vs. SESSION_SECRET being runtime — catching that distinction was the difference between a working deploy and a half-configured one. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contribution Type
/integrations)Note
Companion PR: #248 — adds Cloudflare Workers deploy support to
open-brain-dashboard-next. Together these two PRs deliver the all-Cloudflare deploy story: this Worker as the REST gateway, the dashboard as another Worker, sharing the sameMCP_ACCESS_KEY. Either ships independently — this Worker can back a Vercel-hosted dashboard, and #248 works with anyopen-brain-rest-shaped backend.What does this do?
Adds
integrations/cloudflare-rest-worker/— a Cloudflare Worker that implements theopen-brain-restREST API the Next.js dashboard expects.The dashboard's README references
open-brain-restas a prerequisite, but no implementation ships in the repo. This PR fills that gap so the four core dashboard pages (Dashboard, Browse, Detail, Search) work end-to-end against any Open Brain Supabase project.Endpoint surface
The Worker reverse-engineers its contract from the dashboard's
lib/api.tsandapp/api/*/route.tsconsumer code — no contract was invented:GET/healthGET/thoughtsGET/thought/:idPUT/thought/:id{content, type, importance, status}DELETE/thought/:idPOST/search(semantic)match_thoughtsRPC → re-fetch withsensitivity_tierfilterPOST/search(text)search_thoughts_textRPC fromenhanced-thoughtsGET/statsbrain_stats_aggregateRPC into the dashboard'sStatsResponseshapePOST/captureupsert_thoughtRPCGET/ingestion-jobsPOST/ingest,/ingestion-jobs/:id/executeGET/ingestion-jobs/:idTotal: 10 functional endpoints + 4 deliberate stubs.
Architecture
Auth uses the same
MCP_ACCESS_KEYalready set foropen-brain-mcp— no new shared secret. The browser never sees the key (encrypted in iron-session cookie, decrypted server-side in the dashboard's API routes).Requirements
Existing:
thoughtstable +match_thoughts/upsert_thoughtRPCs from getting-started)schemas/enhanced-thoughts/applied (providessearch_thoughts_text,brain_stats_aggregate, and thetype/sensitivity_tier/importance/quality_score/source_typecolumns)New:
wranglerCLIKnown limitations (documented in the integration README)
These are real impedance mismatches between the dashboard's expectations and the upstream schema. The Worker is correct as-built; resolving them is out of scope for this PR:
Thought.id: numbervsthoughts.id UUID. The dashboard doesparseInt(id, 10)on URL params (app/thoughts/[id]/page.tsx:29). UUIDs parse to NaN. The Worker returns UUIDs as strings — Browse and stats render fine; Detail navigation needs the dashboard'sidtype widened. A follow-up PR can patch the dashboard types.importancescale. Dashboard'sPRIORITY_LEVELSexpects 0–100 (Critical = 80+).enhanced-thoughtsschema defaultsimportanceto 3. Existing data renders as "Low" priority. Not a Worker bug.No
reflectionstable. Detail page calls/thought/:id/reflection. No schema creates this table; the Worker doesn't implement the endpoint.No smart-ingest integration.
/ingest,/ingestion-jobs/:id,/ingestion-jobs/:id/executereturn 501. Single-thought capture via/captureworks.These don't block the four core pages.
Out of scope (future PRs)
workflow-statusschema activeChecklist
README.mdwith prerequisites, step-by-step instructions, and expected outcomemetadata.jsonhas all required fieldswrangler.tomlis gitignored; onlywrangler.toml.exampleships)Test plan
wrangler deploysucceeds against a fresh Cloudflare accountcurl ${WORKER_URL}/health→{"status":"ok",…}without authcurl ${WORKER_URL}/thoughtswithoutx-brain-key→ 401curl ${WORKER_URL}/thoughts -H 'x-brain-key: …'→ paginated rowsPOST /searchsemantic mode returns ranked results with similarity scoresPOST /searchtext mode returns rows withrankscoresGET /stats?days=7returns{total_thoughts, window_days, types, top_topics}POST /capturecreates a row + writes the embedding (verify via SQL Editor)npm run devwithNEXT_PUBLIC_API_URLpointing at the Worker — login + Browse + Search render real data🤖 Generated with Claude Code