Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
2dbb243
docs(cache): add research cache design
devonxjz Aug 26, 2026
7e16b16
docs(cache): split implementation into sprints
devonxjz Aug 26, 2026
f501aea
feat(cache): implement sprint 01 contracts and normalization
devonxjz Aug 26, 2026
762cca3
feat(storage): implement sprint 02 supabase schema and storage adapter
devonxjz Aug 26, 2026
40a1d2e
feat(cache): implement sprint 03 server read-through flow
devonxjz Aug 26, 2026
87efa4e
feat(ui): implement sprint 04 client suggestions and refresh ui
devonxjz Aug 26, 2026
ae0763a
fix(tests): fix ProfileDiff type in reducer unit test
devonxjz Aug 26, 2026
4f073d9
feat(telemetry): implement sprint 05 telemetry and release hardening
devonxjz Aug 26, 2026
760140e
refactor(ui): enhance accessibility semantics and unmount lifecycle s…
devonxjz Aug 26, 2026
ee4b9b8
feat(observability): add fingerprintCacheKey and updateResearchCacheO…
devonxjz Aug 26, 2026
d80e24f
feat(ui): add buildResearchRequest helper and test coverage
devonxjz Aug 26, 2026
e8709ee
fix(cache): enforce cache preflight, recoverable cache_invalid notice…
devonxjz Aug 26, 2026
4b3b4db
fix(observability): emit failed research scores on stream error
devonxjz Aug 26, 2026
edd30e0
fix(storage): fallback to SUPABASE_ANON_KEY and encapsulate preflight…
devonxjz Aug 26, 2026
fb66da8
fix(storage): add graceful fallback for unmigrated Supabase schemas
devonxjz Aug 26, 2026
d5990ea
feat(ui): add interactive evidence verification links to all profile …
devonxjz Aug 26, 2026
a28ddda
docs: rewrite README with light theme architecture diagram, LangChain…
devonxjz Aug 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ VIETQR_ENABLED=true
# Storage
STORAGE_PROVIDER=supabase # supabase | memory
SUPABASE_URL=https://xyz.supabase.co
SUPABASE_ANON_KEY=...
SUPABASE_SERVICE_ROLE_KEY=server-only-secret

# Rate limit guards (optional overrides)
MAX_CONCURRENT_RESEARCH=1
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,13 @@ jobs:
- name: Test
run: npm test

- name: Database integration tests
run: |
npx supabase start
eval "$(npx supabase status -o env)"
SUPABASE_TEST_URL="$API_URL" SUPABASE_TEST_SERVICE_ROLE_KEY="$SERVICE_ROLE_KEY" SUPABASE_TEST_ANON_KEY="$ANON_KEY" npm run test:db
npx supabase stop --no-backup

- name: Build
run: npm run build

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ next-env.d.ts
.worktrees/

# temp fixtures
/tmp/
/tmp/
supabase/.temp/
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Dockerfile — PartnerIQ (Google Cloud Run / Production)
# ═══════════════════════════════════════════════════════

FROM node:20-alpine AS base
FROM node:22-alpine AS base

# Step 1: Install dependencies
FROM base AS deps
Expand Down
630 changes: 136 additions & 494 deletions README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Supabase Research Cache Sprint Roadmap

**Spec:** [`../../specs/2026-08-26-supabase-research-cache-design.md`](../../specs/2026-08-26-supabase-research-cache-design.md)

This roadmap splits the approved cache design into dependency-ordered,
independently reviewable deliverables. A sprint is a technical delivery slice,
not a calendar estimate. Execute and review one sprint before starting its
successor.

## Sprint sequence

| Sprint | Deliverable | Depends on | Completion gate |
|---|---|---|---|
| [01 — Contracts and normalization](./sprint-01-contracts-and-normalization.md) | Typed request/SSE/snapshot contracts, safe identity normalization, pure lookup decisions | Approved spec | Focused unit tests, typecheck, Node 22 build |
| [02 — Supabase schema and storage](./sprint-02-supabase-schema-and-storage.md) | Identity schema, transactional RPCs, complete-snapshot storage adapter | Sprint 01 | Local database reset, adapter tests, two-client concurrency test |
| [03 — Server read-through flow](./sprint-03-server-read-through-flow.md) | Cache-first route, lazy paid providers, canonical workflow identity, atomic persist | Sprint 02 | Route/workflow tests prove hit/miss/conflict/error behavior |
| [04 — Client suggestions and refresh](./sprint-04-client-suggestions-and-refresh.md) | Safe company confirmation, cache metadata, manual refresh UI | Sprint 03 | State-transition tests plus visual before/after verification |
| [05 — Telemetry and release hardening](./sprint-05-telemetry-and-release-hardening.md) | HMAC telemetry, remaining negative-path coverage, advisors and release checks | Sprint 04 | Full test/lint/typecheck/build and database advisor pass |

## Dependency flow

```text
contracts → database/storage → server/workflow → client/UI → hardening/release
```

## Cross-sprint constraints

- Supabase remains the only shared persistent cache. Do not add localStorage,
Redis, or an in-process LRU.
- Cache entries do not expire. Only explicit refresh creates a new version.
- Tax ID may auto-match; a unique domain may auto-match; a normalized name
only produces suggestions.
- Never trust a client-provided company ID without rebinding it to the current
normalized input.
- Never auto-merge identities.
- A cache hit, invalid selection, identity conflict, or unavailable cache must
not construct or call LLM, Serper, or scraper adapters.
- Every started SSE stream ends with `done`, including fatal failures.
- Runtime-validate cached JSONB before returning it.
- Use `pg_advisory_xact_lock`, never a session advisory lock.
- Use HMAC-SHA256 for telemetry fingerprints; never emit raw tax IDs/domains.
- No refresh rate limiter is added in these sprints. The spec records it as a
later security/cost control.

## Execution rule

Each sprint document is a standalone implementation plan. The executor reads
the approved spec and the selected sprint only, performs its test-first tasks,
and stops at that sprint's review gate. Do not batch multiple sprint commits
without review.
Loading
Loading