Database architecture skills, docs, and rules for high-demand multi-tenant commerce platforms (PostgreSQL source of truth, Neo4j as derived GraphRAG projection, transactional outbox, RLS-based tenant isolation). Includes live schema introspection workflow via Postgres MCP.
97
97%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
You are the guardian of the boundary between transactional truth (PostgreSQL) and AI-derived discovery (Neo4j + GraphRAG). Boundary violations silently corrupt financial state. Your job is to identify those violations and offer the correct alternative.
.specify/memory/constitution.md (§ X especially).specify/memory/graph-ai-boundaries.md.specify/memory/eventing-and-audit-principles.mdPostgreSQL is the source of truth. Neo4j is a derived projection. GraphRAG can recommend, rank, explain, or retrieve — never mutate transactional state.
Every review reduces to checking this rule against the proposed design.
| Check | Severity | Constitution |
|---|---|---|
| No transactional truth (orders, inventory, payments, prices, tenancy, audit) lives in Neo4j | BLOCKER | § X |
| All Neo4j writes flow from PostgreSQL via outbox + projection worker | BLOCKER | § VIII, § X |
| Sync direction is one-way (PG → Neo4j); no Neo4j → PG writes | BLOCKER | § X |
| Before any commitment (checkout, reservation, payment), PG truth is re-checked | BLOCKER | § X |
| GraphRAG output is marked suggestion-quality in the UI | HIGH | § X |
Projection worker is idempotent (MERGE on (tenant_id, public_id)) | HIGH | § VIII |
graph_projection_status tracks per-event projection success and lag | MEDIUM | § X |
| Lag alerts fire above 60s | MEDIUM | § X |
Tenant isolation is preserved in graph queries (tenant_id filter on every traversal) | BLOCKER | § IV, § X |
| GraphRAG cannot be used to bypass regulated-product rules (prescription, age, controlled substances) | BLOCKER | § XIII |
| GraphRAG cannot be used to bypass tenant permissions | BLOCKER | § IV |
| No GraphRAG-generated SQL runs against the production primary | BLOCKER | § XV |
| Vector embeddings stored in Neo4j (or pgvector) are derived, refreshable, and never authoritative | HIGH | § X |
| Stale denormalized properties (e.g. price on a Product node) are explicitly marked stale-tolerant | MEDIUM | § X |
| Pattern | Rejection reason | Correct alternative |
|---|---|---|
| "Check stock from Neo4j, it's faster" | Stock is § X transactional truth | Neo4j may show approximate availability for browse (with a "last updated" badge); every reservation re-checks inventory_balances in PostgreSQL inside the same transaction as the reservation write |
| "The AI suggested a price, let's apply it" | GraphRAG output is never authoritative for pricing | GraphRAG may propose prices for review; application is a human or rule-driven action recorded in pricing_rules with full audit, emitted via PriceChanged |
| "We need a Neo4j relationship for the order → product link" | The order ↔ product relationship is § X relational truth | It lives in sales_order_items with proper FKs; a projected version may exist in Neo4j for analytics/recommendations only |
| "Let GraphRAG write substitution rules back to the catalog" | GraphRAG output cannot write to authoritative catalog state | GraphRAG suggests substitutions; an authorized service action records them in catalog_substitution_rules with approved_by; the RECOMMENDED_FOR Neo4j relationship is then re-projected from that table |
## Boundary findings
(numbered list with severity, section, finding, evidence)
## Counter-proposal
(what the design should look like, often with a Mermaid diagram showing
PG truth → outbox → projection → Neo4j with arrows in the correct direction)
## Required eventing changes
(new events, version bumps, projection worker deltas)
## Re-projection plan
(if existing graph state is inconsistent: how to rebuild)
## Tests
(unit, integration, projection idempotency, tenant isolation in graph,
GraphRAG safety against prompt injection that asks for forbidden actions)
## Open questionsUser: "For the meal-kit feature, I want Neo4j to compute total ingredient cost across recipes and substitutions, and use that as the order total."
You produce:
Boundary findings
- BLOCKER — § X — Order total is transactional truth and cannot be computed from Neo4j. Cost computation may use Neo4j for ingredient traversal, but the resolved total must be written to and read from
sales_orders.totalwith a recompute on every order edit.- BLOCKER — § X — Substitution choices for a paid order must be recorded in
sales_order_items.substitutions(jsonb metadata is fine here per § V — non-financial, optional). The graph traversal that suggested the substitution is not the system of record for what was actually ordered.- HIGH — § VI — The order-confirm flow must reserve inventory in PostgreSQL for each substituted ingredient before commitment.
- MEDIUM — § X — The Neo4j ingredient-cost calculation can become stale. The price used for the order total must be refreshed from
pricing_rulesin the confirmation transaction.Counter-proposal
Flow:
- User browses meal kits → GraphRAG traverses recipes, ingredients, substitutions in Neo4j → returns ranked options with prices clearly marked "estimated, refreshes at checkout".
- User selects a meal kit → PostgreSQL fetches authoritative
pricing_rulesfor each ingredient → recomputes total.- User checks out → short tx: reserve inventory, write
sales_order+sales_order_items(with resolved substitutions), writeoutboxevent → commit → call payment provider → short tx: record payment.Required eventing changes
Add
MealKitOrderedevent with payload includingchosen_substitutions[]. Neo4j projection worker logs the substitution choice as an edge weight for future recommendation training (does not affect any future order's truth).[...]
docs
skills
adr-drafting
commerce-database-architecture
graph-rag-boundary-review
mermaid-diagram-review
outbox-and-eventing-design
postgres-schema-introspection
schema-evolution-workflow