factcircuit
FactCircuit는 불변 출처와 단계별 검증, 제한된 검색, 재현 가능한 평가를 제공하는 감사 가능한 주장·증거 검증 루프입니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Collaborative platform for defining, versioning, and exporting business metrics and data rules.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
LogicGate is a collaborative platform for defining, versioning, and exporting business metrics and data rules. Engineers build definitions visually; stakeholders review changes; every publish creates an immutable version snapshot with a commit-style message. Built with Next.js 16, Supabase Auth, PostgreSQL (Prisma), and React Query. [README 설치·사용 부분 발췌] Getting started • Node.js 20+ • npm 10+ • A Supabase project (PostgreSQL + Auth + Storage) • GitREADME 전문 보기 ↗
LogicGate is a collaborative platform for defining, versioning, and exporting business metrics and data rules. Engineers build definitions visually; stakeholders review changes; every publish creates an immutable version snapshot with a commit-style message.
Built with Next.js 16, Supabase Auth, PostgreSQL (Prisma), and React Query.
| Area | Capabilities |
|---|---|
| Definitions | Visual builder for metrics, rules, filters, and flags with conditions, aggregation, and source mapping |
| Version control | Git-style publish flow — drafts autosave silently; versions are recorded only on publish with a message |
| Change requests | Stakeholders propose changes; approvers review before publishing |
| Pseudocode export | Auto-compiled output in Generic, SQL, Python, and dbt formats |
| Collaboration | Per-definition comments, multi-owner support, approver assignment |
| Workspaces | Multi-tenant organizations with role-based access (Owner / Editor / Viewer) |
| Theming | Slack-inspired theme presets, font selection, and language preferences |
| Integrations | Webhook and dbt project URL configuration per workspace |
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| UI | React 19, Tailwind CSS 4, shadcn/ui + Base UI |
| State | TanStack Query (server state), Zustand (client state) |
| Auth | Supabase Auth (SSR cookie sessions) |
| Database | PostgreSQL via Prisma 7 |
| Storage | Supabase Storage (avatars, workspace logos) |
| Validation | Zod 4 |
| Testing | Jest, Playwright |
| Deployment | Vercel-ready (vercel.json included) |
High-level view: browser client, Next.js server, and Supabase backend.
flowchart TB
subgraph Client["Browser"]
UI["Next.js App<br/>(React + TanStack Query)"]
ZS["Zustand Stores<br/>(appearance, workspace, overlay)"]
end
subgraph NextServer["Next.js Server"]
MW["Middleware<br/>(session refresh + route guard)"]
RSC["App Router<br/>(RSC + Client Components)"]
API["API Routes<br/>(/api/*)"]
MW --> RSC
MW --> API
end
subgraph Supabase["Supabase"]
Auth["Auth<br/>(JWT / cookies)"]
Storage["Storage<br/>(avatars bucket)"]
PG["PostgreSQL<br/>(pooled + direct)"]
end
UI --> RSC
UI --> API
ZS --> UI
API --> Auth
API --> Storage
API --> PG
RSC --> Auth
Request path (authenticated API call):
sequenceDiagram
participant B as Browser
participant M as Middleware
participant A as API Route
participant S as Supabase Auth
participant P as Prisma / PostgreSQL
B->>M: GET /api/definitions?workspaceId=…
M->>S: getUser() from cookies
alt No session
M-->>B: 401 Unauthorized
else Valid session
M->>A: Forward request
A->>S: requireSessionUser()
A->>P: requireWorkspaceMember()
A->>P: prisma.definition.findMany()
P-->>A: rows
A-->>B: { data, error, meta }
end
flowchart LR
subgraph Presentation
Pages["app/app/* pages"]
Components["components/*"]
Layouts["layouts + AppShell"]
end
subgraph ClientLogic
Hooks["hooks/"]
Stores["stores/"]
RQ["TanStack Query cache"]
end
subgraph ServerLogic
Routes["app/api/*"]
Lib["lib/ (permissions, compiler, versioning)"]
Validators["validators (Zod)"]
end
subgraph Data
Prisma["Prisma Client"]
DB[(PostgreSQL)]
end
Pages --> Components
Components --> Hooks
Components --> Stores
Components --> RQ
RQ --> Routes
Routes --> Lib
Routes --> Validators
Lib --> Prisma
Prisma --> DB
| Store | Purpose |
|---|---|
useWorkspaceStore | Current workspace / organization context |
useAppearanceStore | Theme preset, font, language (persisted) |
useActionOverlay | Global loading overlay for long-running mutations |
| Module | Purpose |
|---|---|
lib/api.ts | Standard API response shape, auth helpers, workspace membership checks |
lib/permissions.ts | Role-based edit / approve / delete gates |
lib/versioning.ts | Immutable snapshot creation on publish |
lib/compiler/ | Pseudocode generation (generic, SQL, Python, dbt) |
lib/definitions.ts | Snapshot builder and Prisma include shapes |
erDiagram
User ||--o{ WorkspaceMember : "belongs to"
Workspace ||--o{ WorkspaceMember : "has"
Workspace ||--o{ DefinitionGroup : "organizes"
Workspace ||--o{ Definition : "contains"
DefinitionGroup ||--o{ Definition : "groups"
Definition ||--o{ Condition : "has"
Definition ||--o{ DefinitionVersion : "versioned by"
Definition ||--o{ DefinitionOwner : "owned by"
Definition ||--o{ ChangeRequest : "change requests"
Definition ||--o{ Comment : "discussions"
User ||--o{ DefinitionOwner : "co-owner"
User ||--o{ DefinitionVersion : "changed by"
User ||--o{ ChangeRequest : "requests / reviews"
User ||--o{ Comment : "authors"
Definition {
string id PK
string name
enum type "METRIC|RULE|FILTER|FLAG"
enum status "DRAFT|PUBLISHED|DEPRECATED|PENDING_REVIEW"
int currentVersion
string sourceTable
enum aggregationFn
}
DefinitionVersion {
string id PK
int version
json snapshot
string changeDescription
}
Condition {
int order
enum connector "IF|AND|OR"
enum operator
string field
string value
}
Supabase handles identity; LogicGate syncs the Supabase user into the local User table on first login.
flowchart TD
A[User visits /login] --> B[Supabase email/password or OAuth]
B --> C{Session cookie set?}
C -->|No| A
C -->|Yes| D[POST /api/auth/sync]
D --> E[Upsert User + WorkspaceMember in PostgreSQL]
E --> F[Redirect to /app]
F --> G[Middleware validates session on every request]
G --> H{Path protected?}
H -->|/app/*| I[Allow or redirect to /login]
H -->|/api/*| J[401 JSON or proceed]
Public routes: /, /login, /signup, /invite/[token].
Draft edits autosave to the working definition without creating versions. Publishing is the only action that writes to version history.
stateDiagram-v2
[*] --> DRAFT: Create definition
DRAFT --> DRAFT: Autosave fields / conditions / ownership
DRAFT --> PENDING_REVIEW: Stakeholder submits change request
PENDING_REVIEW --> DRAFT: Rejected
PENDING_REVIEW --> PUBLISHED: Approved + published
DRAFT --> PUBLISHED: Engineer publishes (with message)
PUBLISHED --> PUBLISHED: Edit draft + publish again (new version)
PUBLISHED --> DEPRECATED: Soft delete
DEPRECATED --> [*]
Publish flow (creates version snapshot):
sequenceDiagram
participant U as User
participant UI as PublishDialog
participant API as POST /api/definitions/:id/publish
participant V as createVersionSnapshot()
participant DB as PostgreSQL
U->>UI: Click Publish + enter message
UI->>API: { message: "Added trial exclusion" }
API->>DB: Update status → PUBLISHED
API->>V: Build JSON snapshot (definition + conditions + owners)
V->>DB: Increment currentVersion, insert DefinitionVersion
API-->>UI: Updated definition
UI-->>U: Toast + refresh version list
Compare / restore: Any two versions can be diffed client-side via snapshot JSON. Restore replays a snapshot into the live definition and optionally records a new version.
The compiler (src/lib/compiler/) transforms a definition + conditions into executable-style pseudocode.
flowchart LR
D[Definition record] --> B[buildSnapshot]
C[Conditions] --> B
B --> I[CompilerInput]
I --> G[compileGeneric]
I --> S[compileSQL]
I --> P[compilePython]
I --> T[compileDbt]
G & S & P & T --> O[Formatted code string]
O --> UI[PseudocodeSidebar / Export]
Supported operators: EQUALS, NOT_EQUALS, IN, NOT_IN, comparisons, IS_NULL, CONTAINS, STARTS_WITH, etc.
All API routes return { data, error, meta }.
| Method | Route | Description |
|---|---|---|
GET | /api/auth/me | Current user profile |
POST | /api/auth/sync | Sync Supabase user to DB |
GET/POST | /api/workspaces | List / create workspaces |
PATCH | /api/workspaces/[id] | Update workspace settings |
POST | /api/workspaces/logo | Upload organization logo |
GET/POST | /api/definitions | List / create definitions |
GET/PATCH/DELETE | /api/definitions/[id] | Read / update / deprecate |
POST | /api/definitions/[id]/publish | Publish + version snapshot |
PUT | /api/definitions/[id]/conditions | Replace condition rows |
PUT | /api/definitions/[id]/owners | Set owners + approver |
GET | /api/definitions/[id]/versions | Version list (no snapshot payload) |
GET | /api/definitions/[id]/versions/[v] | Single version + snapshot |
POST | /api/definitions/[id]/versions/[v]/restore | Restore from snapshot |
GET | /api/definitions/[id]/pseudocode?format= | Compile pseudocode |
GET/POST | /api/definitions/[id]/comments | Discussion threads |
GET/POST | /api/change-requests | Change request workflow |
GET/PATCH | /api/users/me | Profile settings |
logicgate/
├── prisma/
│ └── schema.prisma # Database schema
├── scripts/
│ ├── db-push.mjs # Direct-connection schema push (Supabase)
│ ├── setup-db.mjs # Full DB bootstrap
│ └── apply-rls.mjs # Row-level security policies
├── src/
│ ├── app/
│ │ ├── (auth)/ # Login, signup
│ │ ├── api/ # REST API routes
│ │ └── app/ # Authenticated application shell
│ │ ├── definitions/ # Three-panel definition editor
│ │ ├── history/ # Workspace version feed
│ │ ├── export/ # Bulk pseudocode ZIP export
│ │ └── settings/ # Workspace + integrations
│ ├── components/
│ │ ├── definitions/ # VisualBuilder, Changelog, Compare, etc.
│ │ ├── layout/ # AppShell, Sidebar, OrganizationRail
│ │ └── providers/ # Query, Appearance providers
│ ├── lib/
│ │ ├── compiler/ # Pseudocode compilers
│ │ ├── supabase/ # SSR client, middleware helpers
│ │ ├── api.ts # Auth + response utilities
│ │ ├── permissions.ts # RBAC helpers
│ │ └── versioning.ts # Snapshot creation
│ └── stores/ # Zustand client stores
├── tests/e2e/ # Playwright end-to-end tests
├── docs/ # Setup and deployment guides
├── middleware.ts # Auth gate for /app and /api
└── vercel.json # Deployment config
git clone https://github.com/azzammasood/logicgate.git
cd logicgate
npm install
Copy the example below into .env.local (never commit this file):
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# Prisma — use pooler (6543) for runtime, direct (5432) for migrations
DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-region.pooler.supabase.com:6543/postgres?pgbouncer=true
DIRECT_URL=postgresql://postgres.[ref]:[password]@aws-0-region.pooler.supabase.com:5432/postgres
See docs/SETUP_LOGICGATE.md for Supabase-specific setup (RLS, storage bucket, auth URLs).
npm run db:push # Push schema (uses DIRECT_URL)
npm run db:rls # Apply row-level security
npm run test:db # Smoke test
npm run dev
Open http://localhost:3000.
Note:
npm run devrunsprisma generateautomatically so the client stays in sync with the schema.
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | Yes | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Yes | Public anon key (browser + middleware) |
SUPABASE_SERVICE_ROLE_KEY | Yes | Server-side admin operations |
DATABASE_URL | Yes | Pooled Postgres connection (port 6543) |
DIRECT_URL | Yes | Direct Postgres connection for migrations (port 5432) |
| Command | Description |
|---|---|
npm run dev | Start dev server (Prisma generate + Next.js) |
npm run build | Production build |
npm run start | Start production server |
npm run lint | ESLint |
npm run type-check | TypeScript check |
npm run db:push | Push Prisma schema via direct connection |
npm run db:studio | Open Prisma Studio |
npm run test | Jest unit tests |
npm run test:e2e | Playwright E2E tests |
npm run test:qa | Full QA spec (single worker) |
# Unit tests
npm run test
# End-to-end (requires running dev server + seeded DB)
npm run test:e2e
# Full QA checklist automation
npm run test:qa
See docs/QA_CHECKLIST.md for manual QA steps.
LogicGate is configured for Vercel. Set all environment variables in the Vercel project dashboard.
npm run build # verify locally first
See docs/DEPLOY.md for production deployment notes.
Supabase Auth redirect URLs: add your production domain (e.g. https://your-app.vercel.app/**).
flowchart TB
subgraph DefinitionsPage["/app/definitions/[id]"]
TB[DefinitionsTopBar<br/>Breadcrumbs · Publish · Compare]
subgraph Panels["Three-panel layout"]
LP[DefinitionsListPanel<br/>Search · Active/Deprecated filter]
MP[Main panel<br/>Visual Builder · Changelog · Discuss · Settings]
RP[PseudocodeSidebar<br/>Format tabs · Version history]
end
TB --> Panels
end
Each panel scrolls independently (min-h-0 + overflow-y-auto flex layout).
flowchart TD
U[User] --> WR[WorkspaceRole]
WR --> O[OWNER]
WR --> E[EDITOR]
WR --> V[VIEWER]
O --> CE[Can edit all definitions]
O --> CT[Can manage team]
E --> CE
V --> RO[Read-only]
U --> UR[UserRole: ENGINEER / STAKEHOLDER]
UR --> CD[Can create definitions]
UR --> CR[Can submit change requests]
Definition-level checks also consider whether the user is an owner or assigned approver (lib/permissions.ts).
git checkout -b feat/my-featurenpm run type-check && npm run lint && npm run testPrivate / all rights reserved unless otherwise specified by the repository owner.
docs/FIRST_RUN.md — Quick start for engineers and stakeholdersdocs/SETUP_LOGICGATE.md — Supabase project setupdocs/DEPLOY.md — Production deploymentdocs/QA_CHECKLIST.md — Manual QA checklist