Skip to content

0xanshu/project#93

Open
0xanshu wants to merge 12 commits into
ScrawnDotDev:devfrom
0xanshu:0xanshu/project
Open

0xanshu/project#93
0xanshu wants to merge 12 commits into
ScrawnDotDev:devfrom
0xanshu:0xanshu/project

Conversation

@0xanshu

@0xanshu 0xanshu commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@greptile-apps

greptile-apps Bot commented Jun 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces multi-project (multi-tenant) support across the entire Scrawn backend, propagating a projectId through auth context, database schemas, ClickHouse event storage, payment provider client caching, and all HTTP/gRPC handlers.

  • Auth & onboarding: Replaces the single-dashboard-key gate on onboarding with a master API key (HMAC-verified), creates a projectsTable, inserts project + metadata + dashboard key atomically, and returns the raw dashboard key in the response. The payment provider client cache is keyed by (projectId, mode) instead of global singletons.
  • Data isolation: Every query — Postgres, ClickHouse, gRPC data queries — now scopes to auth.projectId; revoke/list/create endpoints enforce dashboard-role checks and project-scoped WHERE clauses. Webhook delivery, forwarding, and checkout session handling all carry projectId through to DB writes.
  • ClickHouse migration gaps: The DDL change uses CREATE TABLE IF NOT EXISTS (won't alter existing tables), the ORDER BY key omits project_id (enabling cross-project deduplication by ReplacingMergeTree), and the fetchLastBilled helper queries users without a project filter, risking a wrong billing-window timestamp.

Confidence Score: 3/5

Not safe to merge without addressing the ClickHouse migration and billing-window bugs.

Three distinct defects in the ClickHouse layer: the DDL approach silently leaves existing tables without project_id (breaking inserts and all queries on existing deployments), the ORDER BY key does not include project_id (so ReplacingMergeTree can deduplicate events across project boundaries), and fetchLastBilled queries users by ID alone and can pick up a timestamp from a different project's user, corrupting the billing-window calculation.

src/storage/adapter/clickhouse/schema.ts and src/storage/adapter/clickhouse/utils.ts need the most attention before merging.

Important Files Changed

Filename Overview
src/storage/adapter/clickhouse/schema.ts Adds project_id String to both ClickHouse tables, but CREATE TABLE IF NOT EXISTS won't migrate existing tables; queries now filter on project_id which will fail on existing deployments. ORDER BY also excludes project_id, enabling cross-project deduplication by ReplacingMergeTree.
src/storage/adapter/clickhouse/utils.ts fetchLastBilled queries usersTable by userId only, without projectId filter; in multi-project setup this can return a timestamp from another project's user, corrupting the price-calculation billing window.
src/routes/http/api/onboarding.ts Refactored to use master-API-key auth, create projects atomically in a transaction, register DodoPayments webhooks with projectId in the URL, and return the new dashboard key. Webhook rollback on DB failure is present.
src/storage/db/postgres/schema.ts Adds projectsTable and projectId foreign keys across all tables; metadataTable gains per-project uniqueIndex; apiKeysTable adds per-project active-name unique index. Global idempotencyKey uniqueness on usage event tables flagged in prior comments.
src/interceptors/auth.ts Propagates projectId through auth cache and context; fixes expiry parsing from fromSQL to fromISO to match ISO-format timestamps written by handlers. Both cache and DB lookup paths now include projectId.
src/routes/gRPC/payment/paymentProvider.ts Replaces two module-level client singletons with a per-(projectId, mode) cache Map; adds removeClient for targeted invalidation after onboarding. Logic is clean and correct.
src/routes/http/api/apiKeys.ts Adds dashboard-role enforcement for all key-management endpoints; scopes list and revoke queries to the caller's project; cache-busts on revoke via apiKeyCache.delete. Webhook endpoint creation moved into the create-key transaction.
src/utils/authenticateMasterApiKey.ts New utility for HMAC-SHA256 timing-safe comparison of the master API key used to gate project creation during onboarding. Implementation is correct.

Reviews (2): Last reviewed commit: "fix(generateInitialAPIKey): idempotency ..." | Re-trigger Greptile

Comment thread src/zod/internals.ts
Comment thread src/utils/generateInitialAPIKey.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants