diff --git a/CLA.md b/CLA.md index e0b523414..a3890cf9c 100644 --- a/CLA.md +++ b/CLA.md @@ -1,12 +1,12 @@ -# Quackback Contributor License Agreement +# RitualChain Contributor License Agreement -Thank you for your interest in contributing to Quackback. This Contributor License Agreement ("Agreement") documents the rights granted by contributors to Quackback Ltd ("Company"). +Thank you for your interest in contributing to RitualChain. This Contributor License Agreement ("Agreement") documents the rights granted by contributors to RitualChain Ltd ("Company"). By submitting a Contribution (as defined below) to this project, you agree to the following terms and conditions. ## 1. Definitions -**"Contribution"** means any original work of authorship, including any modifications or additions to an existing work, that you submit to the Company for inclusion in the Quackback project. +**"Contribution"** means any original work of authorship, including any modifications or additions to an existing work, that you submit to the Company for inclusion in the RitualChain project. **"Submit"** means any form of electronic, verbal, or written communication sent to the Company, including but not limited to pull requests, issues, patches, and emails. @@ -48,4 +48,4 @@ You agree to notify the Company of any facts or circumstances of which you becom By submitting a pull request to this repository, you indicate your agreement to this CLA. A CLA assistant bot will verify your signature on each pull request. -If you have questions about this Agreement, please open an issue or contact legal@quackback.io. +If you have questions about this Agreement, please open an issue or contact legal@ritual.net. diff --git a/CLAUDE.md b/CLAUDE.md index 7b32ed1f8..b3f8cc4ed 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # CLAUDE.md -Quackback - open-source customer feedback platform. Bun monorepo, TanStack Start, PostgreSQL + Drizzle, Tailwind v4 + shadcn/ui. +RitualChain - open-source customer feedback platform. Bun monorepo, TanStack Start, PostgreSQL + Drizzle, Tailwind v4 + shadcn/ui. ## Commands @@ -13,7 +13,7 @@ bun run test && bun run test:e2e && bun run lint && bun run typecheck ## Rules -- Entity IDs are branded TypeIDs via `@quackback/ids` +- Entity IDs are branded TypeIDs via `@ritualchain/ids` - Never add co-author trailers to git commits - When cutting a release, bump `version` in `apps/web/package.json` to match the git tag — this is the source of truth for `__APP_VERSION__` (injected at build time via Vite) - Tier limits live in `settings.tier_limits` (JSON column) and are enforced via `getTierLimits()` + the helpers in `apps/web/src/lib/server/domains/settings/tier-enforce.ts`. The default (no row) is unlimited. The control-plane writes per-tenant limits via `/api/v1/internal/tier-limits` (scope-gated). The OSS code is unaware of "cloud" as a concept — limits and their writer are the same mechanism for self-hosters and cloud tenants. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6280dc0dd..3d9471faa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,13 @@ -# Contributing to Quackback +# Contributing to RitualChain -Thank you for your interest in contributing to Quackback! This guide will help you get started. +Thank you for your interest in contributing to RitualChain! This guide will help you get started. ## Quick Start ```bash # Clone the repository -git clone https://github.com/quackbackio/quackback.git -cd quackback +git clone https://github.com/ritualchain/ritualchain.git +cd ritualchain # Run setup (installs dependencies, starts Docker, runs migrations, seeds demo data) bun run setup @@ -21,7 +21,7 @@ Open http://localhost:3000 to see the app. ## Project Structure ``` -quackback/ +ritualchain/ ├── apps/web/ # TanStack Start application │ ├── src/ │ │ ├── routes/ # File-based routing (TanStack Router) @@ -38,7 +38,7 @@ quackback/ ## Architecture -Quackback uses **TanStack Start** with **TanStack Router** for file-based routing and server functions. +RitualChain uses **TanStack Start** with **TanStack Router** for file-based routing and server functions. ### Server Functions (`apps/web/src/lib/server-functions/`) @@ -73,7 +73,7 @@ export async function createPost(input: CreatePostInput, author: Author) { ### Database Access -Always import from `@/lib/db`, not `@quackback/db`: +Always import from `@/lib/db`, not `@ritualchain/db`: ```typescript import { db, posts, eq } from '@/lib/db' @@ -115,7 +115,7 @@ We require all contributors to sign our [Contributor License Agreement (CLA)](CL **Why a CLA?** -The CLA allows Quackback to: +The CLA allows RitualChain to: - Offer the software under dual licenses (AGPL-3.0 for open source, commercial for enterprise) - Defend the project against legal issues @@ -128,7 +128,7 @@ The CLA allows Quackback to: 3. If not, the bot will prompt you to sign by commenting on the PR 4. Once signed, your signature applies to all future contributions -The CLA is based on the Apache Individual Contributor License Agreement and grants Quackback the right to use your contributions under any license terms. +The CLA is based on the Apache Individual Contributor License Agreement and grants RitualChain the right to use your contributions under any license terms. ## Pull Request Process @@ -162,4 +162,4 @@ When reporting bugs, include: ## License -Quackback core is licensed under AGPL-3.0. See [LICENSE](LICENSE) for details. +RitualChain core is licensed under AGPL-3.0. See [LICENSE](LICENSE) for details. diff --git a/README.md b/README.md index 4de5ed224..277477799 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@

- - Quackback Logo + + RitualChain Logo

-

Quackback

+

RitualChain

Open source feedback for teams that ship. @@ -16,46 +16,46 @@

- Website · - Docs · + Website · + Docs · Get Started

- GitHub stars - License - CI - PRs Welcome + GitHub stars + License + CI + PRs Welcome

- Quackback feedback portal + RitualChain feedback portal

## Get Started -**Cloud** — start free at [app.quackback.io](https://app.quackback.io/signup). We host, scale, and maintain it for you. No setup required. +**Cloud** — start free at [app.ritual.net](https://app.ritual.net/signup). We host, scale, and maintain it for you. No setup required. **Self-hosted** anywhere with [Docker](#docker) or [one click on Railway](#one-click-deploy). -## Why Quackback? +## Why RitualChain? -Most feedback tools are expensive, closed-source, and lock you in. Quackback gives you a modern feedback system you actually own. +Most feedback tools are expensive, closed-source, and lock you in. RitualChain gives you a modern feedback system you actually own. - **Self-host for free.** Run on your own infrastructure. No per-seat pricing. - **Own your data.** Your feedback lives in your own database. No vendor lock-in. -- **AI-powered.** Automatic duplicate detection, AI summaries, feedback extraction from external sources, and an [MCP server](https://quackback.io/docs/mcp) that lets AI agents search, triage, and act on feedback directly. +- **AI-powered.** Automatic duplicate detection, AI summaries, feedback extraction from external sources, and an [MCP server](https://ritual.net/docs/mcp) that lets AI agents search, triage, and act on feedback directly. - **24 integrations.** Slack, Linear, Jira, GitHub, Intercom, Zendesk, and [more](#integrations) out of the box. ## Features - **Feedback boards.** Let users vote, comment, and track status on feature requests. Vote on behalf of customers and see a full activity timeline on every post. - **AI-powered.** Automatically detect duplicates, summarize key themes, and ingest feedback from Slack, email, and other sources so nothing slips through the cracks. -- **Embeddable widget.** Collect feedback right inside your app with a [drop-in widget](https://quackback.io/docs/widget/installation). Works on desktop and mobile, with native SDKs for [iOS](https://github.com/QuackbackIO/quackback-ios) and [Android](https://github.com/QuackbackIO/quackback-android). +- **Embeddable widget.** Collect feedback right inside your app with a [drop-in widget](https://ritual.net/docs/widget/installation). Works on desktop and mobile, with native SDKs for [iOS](https://github.com/RitualChain/ritualchain-ios) and [Android](https://github.com/RitualChain/ritualchain-android). - **Admin inbox.** Triage incoming feedback in one place. Filter, group, dismiss, and restore deleted posts. - **Roadmap & changelog.** Show users what's planned, in progress, and shipped. Publish updates and schedule posts for later. - **Integrations.** [24 integrations](#integrations) including Slack, Linear, Jira, GitHub, Intercom, Zendesk, and two-way issue tracker sync. -- **API, webhooks & MCP.** Automate workflows with the REST API, outbound webhooks, and a 23-tool [MCP server](https://quackback.io/docs/mcp) for AI agents. +- **API, webhooks & MCP.** Automate workflows with the REST API, outbound webhooks, and a 23-tool [MCP server](https://ritual.net/docs/mcp) for AI agents. - **Internationalization.** Portal and widget available in English, French, German, Spanish, and Arabic with full RTL support. Auto-detects browser language. - **Flexible auth.** Password, email OTP, Google, GitHub, and SSO with providers like Okta and Auth0. - **SEO-ready.** Auto-generated sitemap and social sharing previews on every portal page. @@ -68,16 +68,16 @@ Slack, Linear, Jira, GitHub, GitLab, Asana, ClickUp, Monday, Trello, Notion, Sho ### One-Click Deploy -[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/quackback?referralCode=ez8Slg&utm_source=github&utm_medium=readme&utm_campaign=deploy-button) +[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/ritualchain?referralCode=ez8Slg&utm_source=github&utm_medium=readme&utm_campaign=deploy-button) ### Docker ```bash -git clone https://github.com/QuackbackIO/quackback.git -cd quackback +git clone https://github.com/RitualChain/ritualchain.git +cd ritualchain cp .env.example .env # Edit with your configuration -docker build -t quackback -f apps/web/Dockerfile . -docker run -p 3000:3000 --env-file .env quackback +docker build -t ritualchain -f apps/web/Dockerfile . +docker run -p 3000:3000 --env-file .env ritualchain ``` Requires PostgreSQL and a Redis-compatible store. Set `DATABASE_URL` and `REDIS_URL` in `.env`. Migrations run automatically on startup. @@ -86,15 +86,15 @@ Requires PostgreSQL and a Redis-compatible store. Set `DATABASE_URL` and `REDIS_ See the [Contributing Guide](CONTRIBUTING.md) to get started. -- [GitHub Discussions](https://github.com/QuackbackIO/quackback/discussions) — ask questions, share ideas +- [GitHub Discussions](https://github.com/RitualChain/ritualchain/discussions) — ask questions, share ideas ### Local Development Prerequisites: [Bun](https://bun.sh/) v1.3.7+ and [Docker](https://docker.com/) ```bash -git clone https://github.com/QuackbackIO/quackback.git -cd quackback +git clone https://github.com/RitualChain/ritualchain.git +cd ritualchain bun run setup # Install deps, start Docker, run migrations bun run db:seed # Optional: seed demo data bun run dev # http://localhost:3000 @@ -111,8 +111,8 @@ Log in with `demo@example.com` / `password`. - [Tailwind CSS v4](https://tailwindcss.com/) + [shadcn/ui](https://ui.shadcn.com/) · Styling - [Bun](https://bun.sh/) · Runtime and package manager - - Contributors + + Contributors ## License diff --git a/apps/web/docker-entrypoint.sh b/apps/web/docker-entrypoint.sh index 3ef1a669c..ef390b97b 100644 --- a/apps/web/docker-entrypoint.sh +++ b/apps/web/docker-entrypoint.sh @@ -2,7 +2,7 @@ set -e echo "========================================" -echo " Quackback starting..." +echo " RitualChain starting..." echo "========================================" # Migrations: skipped in K8s where a pre-upgrade Helm hook Job runs them @@ -28,6 +28,6 @@ fi # Start the application echo "" -echo "Starting Quackback server on port ${PORT:-3000}..." +echo "Starting RitualChain server on port ${PORT:-3000}..." echo "========================================" exec bun .output/server/index.mjs diff --git a/apps/web/e2e/scripts/get-mention-target.ts b/apps/web/e2e/scripts/get-mention-target.ts index fc1c729be..88186da73 100644 --- a/apps/web/e2e/scripts/get-mention-target.ts +++ b/apps/web/e2e/scripts/get-mention-target.ts @@ -9,7 +9,7 @@ * Usage: bun get-mention-target.ts [excludeEmail] */ import postgres from 'postgres' -import { fromUuid } from '@quackback/ids' +import { fromUuid } from '@ritualchain/ids' const excludeEmail = process.argv[2] ?? 'demo@example.com' diff --git a/apps/web/e2e/scripts/seed-identity-provider.ts b/apps/web/e2e/scripts/seed-identity-provider.ts index c7b0c987c..8ed6dc2a1 100644 --- a/apps/web/e2e/scripts/seed-identity-provider.ts +++ b/apps/web/e2e/scripts/seed-identity-provider.ts @@ -5,7 +5,7 @@ * settings.* columns are JSON text; the provider model lives in the * `identity_provider`, `sso_verified_domain`, and `integration_platform_credentials` * tables. We write raw SQL (same style as the other e2e scripts) and generate - * TypeIDs via `@quackback/ids` (the column default is a JS-level drizzle default + * TypeIDs via `@ritualchain/ids` (the column default is a JS-level drizzle default * that a raw insert wouldn't trigger). * * The client secret is encrypted with the SAME AES-256-GCM + HKDF scheme as the @@ -31,7 +31,7 @@ */ import postgres from 'postgres' import { hkdfSync, randomBytes, createCipheriv, randomUUID } from 'crypto' -import { generateId, toUuid } from '@quackback/ids' +import { generateId, toUuid } from '@ritualchain/ids' const action = (process.argv[2] || '').toLowerCase() if (action !== 'seed' && action !== 'remove') { @@ -50,8 +50,8 @@ if (!connectionString) { function encryptPlatformCredentials(creds: Record): string { const secretKey = process.env.SECRET_KEY if (!secretKey) throw new Error('SECRET_KEY environment variable is required') - const info = 'quackback:v1:integration-platform-credentials' - const key = Buffer.from(hkdfSync('sha256', secretKey, 'quackback-encryption-salt-v1', info, 32)) + const info = 'ritualchain:v1:integration-platform-credentials' + const key = Buffer.from(hkdfSync('sha256', secretKey, 'ritualchain-encryption-salt-v1', info, 32)) const iv = randomBytes(12) const cipher = createCipheriv('aes-256-gcm', key, iv, { authTagLength: 16 }) const ct = Buffer.concat([cipher.update(JSON.stringify(creds), 'utf8'), cipher.final()]) diff --git a/apps/web/e2e/scripts/setup-access-fixtures.ts b/apps/web/e2e/scripts/setup-access-fixtures.ts index 277651499..ede25a140 100644 --- a/apps/web/e2e/scripts/setup-access-fixtures.ts +++ b/apps/web/e2e/scripts/setup-access-fixtures.ts @@ -17,7 +17,7 @@ */ import postgres from 'postgres' import { randomUUID } from 'crypto' -import { generateId, toUuid, fromUuid } from '@quackback/ids' +import { generateId, toUuid, fromUuid } from '@ritualchain/ids' const memberEmail = process.argv[2] if (!memberEmail) { diff --git a/apps/web/e2e/tests/admin/dashboard.spec.ts b/apps/web/e2e/tests/admin/dashboard.spec.ts index 727ca1858..f571aecd5 100644 --- a/apps/web/e2e/tests/admin/dashboard.spec.ts +++ b/apps/web/e2e/tests/admin/dashboard.spec.ts @@ -96,7 +96,7 @@ test.describe('Admin Sidebar Navigation', () => { }) test('logo links to feedback page', async ({ page }) => { - const logoLink = page.getByRole('link', { name: 'Quackback' }).first() + const logoLink = page.getByRole('link', { name: 'RitualChain' }).first() await expect(logoLink).toBeVisible({ timeout: 10000 }) await logoLink.click() await page.waitForLoadState('networkidle') diff --git a/apps/web/e2e/tests/admin/settings-mcp.spec.ts b/apps/web/e2e/tests/admin/settings-mcp.spec.ts index 6c33fc8c1..25b560954 100644 --- a/apps/web/e2e/tests/admin/settings-mcp.spec.ts +++ b/apps/web/e2e/tests/admin/settings-mcp.spec.ts @@ -198,7 +198,7 @@ test.describe('Admin MCP Settings', () => { await expect(referenceLink).toBeVisible({ timeout: 10000 }) const href = await referenceLink.getAttribute('href') - expect(href).toContain('quackback.io/docs/mcp') + expect(href).toContain('ritual.net/docs/mcp') }) test('Claude Code API Key variant shows Authorization Bearer config', async ({ page }) => { diff --git a/apps/web/e2e/tests/auth/unified-login.spec.ts b/apps/web/e2e/tests/auth/unified-login.spec.ts index 69091983e..244431cbf 100644 --- a/apps/web/e2e/tests/auth/unified-login.spec.ts +++ b/apps/web/e2e/tests/auth/unified-login.spec.ts @@ -198,7 +198,7 @@ test('(3) private portal gate: sign-in in the gate lands on /admin', async ({ pa // router.invalidate() ← re-runs the _portal loader with the now-set admin cookie // → access granted → router.navigate({ to: callbackUrl='/admin' }) await page.evaluate(() => { - const ch = new BroadcastChannel('quackback-auth') + const ch = new BroadcastChannel('ritualchain-auth') ch.postMessage({ type: 'auth-success', timestamp: Date.now() }) ch.close() }) diff --git a/apps/web/e2e/utils/access-helpers.ts b/apps/web/e2e/utils/access-helpers.ts index 6df935308..3769874d3 100644 --- a/apps/web/e2e/utils/access-helpers.ts +++ b/apps/web/e2e/utils/access-helpers.ts @@ -81,12 +81,12 @@ export function flushMagicLinkRateLimit(): void { // calls avoid a shell pipeline (no shell-interpolation risk). const scan = execFileSync( 'docker', - ['exec', 'quackback-dragonfly', 'redis-cli', '--scan', '--pattern', 'signin:magiclink:*'], + ['exec', 'ritualchain-dragonfly', 'redis-cli', '--scan', '--pattern', 'signin:magiclink:*'], { encoding: 'utf-8' } ) const keys = scan.split('\n').map((k) => k.trim()).filter(Boolean) for (const key of keys) { - execFileSync('docker', ['exec', 'quackback-dragonfly', 'redis-cli', 'del', key], { + execFileSync('docker', ['exec', 'ritualchain-dragonfly', 'redis-cli', 'del', key], { stdio: 'pipe', }) } @@ -111,7 +111,7 @@ export interface SeedIdpConfig { */ function invalidateAuthCaches(): void { for (const key of ['settings:tenant', 'platform-cred:configured-types']) { - execFileSync('docker', ['exec', 'quackback-dragonfly', 'redis-cli', 'del', key], { + execFileSync('docker', ['exec', 'ritualchain-dragonfly', 'redis-cli', 'del', key], { stdio: 'pipe', }) } @@ -145,7 +145,7 @@ export function setPortalVisibility(visibility: 'private' | 'public'): void { runScript('../scripts/set-portal-visibility.ts', [visibility]) // The portal-access decision is cached under 'settings:tenant'. Drop it so // the dev server evaluates the new visibility on the next request. - execFileSync('docker', ['exec', 'quackback-dragonfly', 'redis-cli', 'del', 'settings:tenant'], { + execFileSync('docker', ['exec', 'ritualchain-dragonfly', 'redis-cli', 'del', 'settings:tenant'], { stdio: 'pipe', }) } diff --git a/apps/web/package.json b/apps/web/package.json index abf698f77..ee352d4aa 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,5 +1,5 @@ { - "name": "@quackback/web", + "name": "@ritualchain/web", "version": "0.13.1", "private": true, "license": "AGPL-3.0", @@ -46,10 +46,10 @@ "@hookform/resolvers": "^5.2.2", "@modelcontextprotocol/sdk": "^1.29.0", "@opentelemetry/api": "^1.9.1", - "@quackback/db": "workspace:*", - "@quackback/email": "workspace:*", - "@quackback/ids": "workspace:*", - "@quackback/logger": "workspace:*", + "@ritualchain/db": "workspace:*", + "@ritualchain/email": "workspace:*", + "@ritualchain/ids": "workspace:*", + "@ritualchain/logger": "workspace:*", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-checkbox": "^1.3.3", diff --git a/apps/web/playwright.config.ts b/apps/web/playwright.config.ts index 603b1dfab..f0cd050b7 100644 --- a/apps/web/playwright.config.ts +++ b/apps/web/playwright.config.ts @@ -1,7 +1,7 @@ import { defineConfig, devices } from '@playwright/test' /** - * Playwright configuration for Quackback E2E tests + * Playwright configuration for RitualChain E2E tests * @see https://playwright.dev/docs/test-configuration */ export default defineConfig({ diff --git a/apps/web/scripts/backfill-ai.ts b/apps/web/scripts/backfill-ai.ts index 60aaf8593..e98376e6f 100644 --- a/apps/web/scripts/backfill-ai.ts +++ b/apps/web/scripts/backfill-ai.ts @@ -31,8 +31,8 @@ try { import { drizzle } from 'drizzle-orm/postgres-js' import postgres from 'postgres' import { eq, and, isNull, sql, count } from 'drizzle-orm' -import { posts, postSentiment, postTags, tags } from '@quackback/db/schema' -import { generateId, type PostId } from '@quackback/ids' +import { posts, postSentiment, postTags, tags } from '@ritualchain/db/schema' +import { generateId, type PostId } from '@ritualchain/ids' import { getOpenAI } from '../src/lib/server/domains/ai/config' import { getChatModel, getEmbeddingModel } from '../src/lib/server/domains/ai/models' @@ -462,7 +462,7 @@ async function backfillEmbeddings( // Main async function main() { - console.log('🦆 Quackback AI Backfill\n') + console.log('🦆 RitualChain AI Backfill\n') console.log('Configuration:') console.log(` Mode: ${dryRun ? 'DRY RUN (no changes)' : 'LIVE'}`) // A phase runs only when its model is configured (central config, #206) diff --git a/apps/web/scripts/backfill-feedback-pipeline.ts b/apps/web/scripts/backfill-feedback-pipeline.ts index 22134bf58..d19b8f470 100644 --- a/apps/web/scripts/backfill-feedback-pipeline.ts +++ b/apps/web/scripts/backfill-feedback-pipeline.ts @@ -23,9 +23,9 @@ try { } import postgres from 'postgres' -import { generateId, toUuid } from '@quackback/ids' +import { generateId, toUuid } from '@ritualchain/ids' -const DB_URL = process.env.DATABASE_URL ?? 'postgresql://postgres:password@localhost:5432/quackback' +const DB_URL = process.env.DATABASE_URL ?? 'postgresql://postgres:password@localhost:5432/ritualchain' const REDIS_URL = process.env.REDIS_URL ?? 'redis://localhost:6379' const sql = postgres(DB_URL) @@ -37,21 +37,21 @@ const LIMIT = limitIdx !== -1 ? parseInt(process.argv[limitIdx + 1], 10) : null async function main() { console.log(`\n=== Feedback Pipeline Backfill${DRY_RUN ? ' (DRY RUN)' : ''} ===\n`) - // 1. Ensure quackback feedback source exists + // 1. Ensure ritualchain feedback source exists let [source] = await sql` - SELECT id FROM feedback_sources WHERE source_type = 'quackback' LIMIT 1 + SELECT id FROM feedback_sources WHERE source_type = 'ritualchain' LIMIT 1 ` if (!source) { if (DRY_RUN) { - console.log(` Would create quackback feedback source`) + console.log(` Would create ritualchain feedback source`) } else { const id = toUuid(generateId('feedback_source')) await sql` INSERT INTO feedback_sources (id, source_type, delivery_mode, name, enabled) - VALUES (${id}, 'quackback', 'passive', 'Quackback', true) + VALUES (${id}, 'ritualchain', 'passive', 'RitualChain', true) ` source = { id } - console.log(` Created quackback feedback source: ${id}`) + console.log(` Created ritualchain feedback source: ${id}`) } } else { console.log(` Feedback source: ${source.id}`) @@ -62,7 +62,7 @@ async function main() { const [counts] = await sql` SELECT (SELECT count(*)::int FROM posts WHERE deleted_at IS NULL AND canonical_post_id IS NULL) AS total_active, - (SELECT count(*)::int FROM raw_feedback_items WHERE source_type = 'quackback') AS already_ingested + (SELECT count(*)::int FROM raw_feedback_items WHERE source_type = 'ritualchain') AS already_ingested ` console.log(` Total active posts: ${counts.total_active}`) console.log(` Already ingested: ${counts.already_ingested}`) @@ -107,7 +107,7 @@ async function main() { const [counts] = await sql` SELECT (SELECT count(*)::int FROM posts WHERE deleted_at IS NULL AND canonical_post_id IS NULL) AS total_active, - (SELECT count(*)::int FROM raw_feedback_items WHERE source_type = 'quackback') AS already_ingested + (SELECT count(*)::int FROM raw_feedback_items WHERE source_type = 'ritualchain') AS already_ingested ` console.log(` Total active posts: ${counts.total_active}`) @@ -121,7 +121,7 @@ async function main() { count(*) FILTER (WHERE processing_state = 'failed')::int AS failed, count(*) FILTER (WHERE processing_state = 'ready_for_extraction')::int AS ready FROM raw_feedback_items - WHERE source_type = 'quackback' + WHERE source_type = 'ritualchain' ` const retriable = stuckCounts.stuck + stuckCounts.failed + stuckCounts.ready if (retriable > 0) { @@ -167,9 +167,9 @@ async function main() { const values = batch.map((p) => ({ id: toUuid(generateId('raw_feedback')), source_id: sourceId, - source_type: 'quackback', + source_type: 'ritualchain', external_id: `post:${p.id}`, - dedupe_key: `quackback:post:${p.id}`, + dedupe_key: `ritualchain:post:${p.id}`, source_created_at: p.created_at, author: sql.json({ principalId: p.principal_id, @@ -222,14 +222,14 @@ async function main() { last_error = NULL, attempt_count = 0, updated_at = NOW() - WHERE source_type = 'quackback' + WHERE source_type = 'ritualchain' AND processing_state IN ('extracting', 'interpreting', 'failed') RETURNING id ` if (resetResult) { const [resetTotal] = await sql` SELECT count(*)::int as cnt FROM raw_feedback_items - WHERE source_type = 'quackback' + WHERE source_type = 'ritualchain' AND processing_state = 'ready_for_extraction' AND updated_at >= NOW() - interval '5 seconds' ` @@ -256,7 +256,7 @@ async function main() { const readyItems = await sql` SELECT id FROM raw_feedback_items WHERE processing_state = 'ready_for_extraction' - AND source_type = 'quackback' + AND source_type = 'ritualchain' ORDER BY source_created_at ASC ` diff --git a/apps/web/scripts/backfill-markdown.ts b/apps/web/scripts/backfill-markdown.ts index 18de48d7a..8f2b6cf25 100644 --- a/apps/web/scripts/backfill-markdown.ts +++ b/apps/web/scripts/backfill-markdown.ts @@ -27,7 +27,7 @@ try { import { drizzle } from 'drizzle-orm/postgres-js' import postgres from 'postgres' import { isNull } from 'drizzle-orm' -import { posts, changelogEntries } from '@quackback/db/schema' +import { posts, changelogEntries } from '@ritualchain/db/schema' import { markdownToTiptapJson } from '../src/lib/server/markdown-tiptap' const BATCH_SIZE = 50 diff --git a/apps/web/scripts/backfill-merge-suggestions.ts b/apps/web/scripts/backfill-merge-suggestions.ts index 5dcb45c98..1872a6527 100644 --- a/apps/web/scripts/backfill-merge-suggestions.ts +++ b/apps/web/scripts/backfill-merge-suggestions.ts @@ -29,8 +29,8 @@ try { import { drizzle } from 'drizzle-orm/postgres-js' import postgres from 'postgres' import { eq, and, or, isNull, desc, sql, count } from 'drizzle-orm' -import { posts, mergeSuggestions } from '@quackback/db/schema' -import { toUuid, type PostId } from '@quackback/ids' +import { posts, mergeSuggestions } from '@ritualchain/db/schema' +import { toUuid, type PostId } from '@ritualchain/ids' import { getOpenAI } from '../src/lib/server/domains/ai/config' import { getChatModel } from '../src/lib/server/domains/ai/models' @@ -354,7 +354,7 @@ function determineDirection( // ============================================ async function main() { - console.log('Quackback Merge Suggestion Backfill\n') + console.log('RitualChain Merge Suggestion Backfill\n') console.log('Configuration:') console.log(` Mode: ${dryRun ? 'DRY RUN (no changes)' : 'LIVE'}`) console.log(` Force re-check: ${force ? 'Yes' : 'No'}`) diff --git a/apps/web/scripts/generate-openapi.ts b/apps/web/scripts/generate-openapi.ts index ebdc6363b..5e72f5ef6 100644 --- a/apps/web/scripts/generate-openapi.ts +++ b/apps/web/scripts/generate-openapi.ts @@ -3,7 +3,7 @@ import { generateOpenAPISpec } from '../src/lib/server/domains/api/openapi' import '../src/lib/server/domains/api/schemas' const spec = generateOpenAPISpec() -// Avoid absolute path to website since that requires workspace access out of quackback context -// if bun is running in quackback workspace. We'll dump it locally then copy it over in bash. +// Avoid absolute path to website since that requires workspace access out of ritualchain context +// if bun is running in ritualchain workspace. We'll dump it locally then copy it over in bash. writeFileSync('./openapi.json', JSON.stringify(spec, null, 2)) console.log('OpenAPI spec generated successfully') diff --git a/apps/web/scripts/test-feedback-pipeline.ts b/apps/web/scripts/test-feedback-pipeline.ts index 70d5d2759..70363d847 100644 --- a/apps/web/scripts/test-feedback-pipeline.ts +++ b/apps/web/scripts/test-feedback-pipeline.ts @@ -27,9 +27,9 @@ try { } import postgres from 'postgres' -import { generateId, toUuid } from '@quackback/ids' +import { generateId, toUuid } from '@ritualchain/ids' -const DB_URL = process.env.DATABASE_URL ?? 'postgresql://postgres:password@localhost:5432/quackback' +const DB_URL = process.env.DATABASE_URL ?? 'postgresql://postgres:password@localhost:5432/ritualchain' const REDIS_URL = process.env.REDIS_URL ?? 'redis://localhost:6379' const sql = postgres(DB_URL) @@ -99,9 +99,9 @@ async function main() { // Get test fixtures const [source] = - await sql`SELECT id FROM feedback_sources WHERE source_type = 'quackback' LIMIT 1` + await sql`SELECT id FROM feedback_sources WHERE source_type = 'ritualchain' LIMIT 1` if (!source) { - console.log(` ERROR: No quackback feedback source. Run seed first.`) + console.log(` ERROR: No ritualchain feedback source. Run seed first.`) await sql.end() process.exit(1) } diff --git a/apps/web/src/components/admin/add-to-roadmap-dropdown.tsx b/apps/web/src/components/admin/add-to-roadmap-dropdown.tsx index da324b24f..7603018f5 100644 --- a/apps/web/src/components/admin/add-to-roadmap-dropdown.tsx +++ b/apps/web/src/components/admin/add-to-roadmap-dropdown.tsx @@ -10,7 +10,7 @@ import { import { Badge } from '@/components/ui/badge' import { useRoadmaps } from '@/lib/client/hooks/use-roadmaps-query' import { addPostToRoadmapFn, removePostFromRoadmapFn } from '@/lib/server/functions/roadmaps' -import type { PostId, RoadmapId } from '@quackback/ids' +import type { PostId, RoadmapId } from '@ritualchain/ids' interface AddToRoadmapDropdownProps { postId: PostId diff --git a/apps/web/src/components/admin/admin-sidebar.tsx b/apps/web/src/components/admin/admin-sidebar.tsx index da1f8b57c..d9c49b480 100644 --- a/apps/web/src/components/admin/admin-sidebar.tsx +++ b/apps/web/src/components/admin/admin-sidebar.tsx @@ -122,10 +122,10 @@ export function AdminSidebar({ initialUserData, latestVersion }: AdminSidebarPro | { helpCenter?: boolean; supportInbox?: boolean } | undefined // The org's own logo (resolved in brandingData by the root loader, same source - // PortalBrandMark uses); fall back to the Quackback mark when none is set. + // PortalBrandMark uses); fall back to the RitualChain mark when none is set. const branding = (settings as { brandingData?: SettingsBrandingData } | undefined)?.brandingData const orgLogo = branding?.logoUrl ?? branding?.headerLogoUrl ?? '/logo.png' - const orgName = branding?.name ?? 'Quackback' + const orgName = branding?.name ?? 'RitualChain' const filteredNavItems = navItems.filter((item) => { if (item.href === '/admin/help-center') return flags?.helpCenter ?? false @@ -248,7 +248,7 @@ export function AdminSidebar({ initialUserData, latestVersion }: AdminSidebarPro @@ -258,7 +258,7 @@ export function AdminSidebar({ initialUserData, latestVersion }: AdminSidebarPro @@ -354,7 +354,7 @@ export function AdminSidebar({ initialUserData, latestVersion }: AdminSidebarPro className="h-7 w-7 rounded object-contain" /> - Quackback + RitualChain