Skip to content

Remove dashboard#25

Merged
weroperking merged 3 commits intomainfrom
remove-dashboard
Mar 1, 2026
Merged

Remove dashboard#25
weroperking merged 3 commits intomainfrom
remove-dashboard

Conversation

@weroperking
Copy link
Copy Markdown
Owner

@weroperking weroperking commented Mar 1, 2026

Summary by CodeRabbit

  • New Features

    • CLI login/logout for credential management and device/browser auth
    • API key system with anon and service_role access, request-logging, and meta endpoints for projects, stats, logs, keys, and charts
    • New CLI commands for functions, RLS, storage, and webhooks
  • Documentation

    • Expanded README with architecture diagrams, CLI workflow, client SDK examples, and updated API reference
  • Refactor

    • Major public API reorganization across CLI, client SDK, core, templates, and providers for clearer modular imports and surfaces

The @betterbase/dashboard workspace has been removed along with all its dependencies including @radix-ui components, @tanstack/react-query, recharts, and tailwindcss. Additionally, login command scaffolding has been added to the CLI (commented out, awaiting app.betterbase.com).
Removes all dashboard-related documentation from CODEBASE_MAP.md and README.md to reflect the dashboard package removal from the monorepo. Simplifies architecture diagrams and removes the apps/dashboard section entirely.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 1, 2026

📝 Walkthrough

Walkthrough

This PR reorganizes the public API across CLI, Client SDK, Core, Templates and Providers, renaming and relocating many exported modules and command entry points. It also adds backend auth (device-code/browser login), API-key middleware, request-logging, a meta API, and supporting DB schema and CLI credential persistence.

Changes

Cohort / File(s) Summary
Documentation & Guides
CODEBASE_MAP.md, README.md, betterbase_backend_rebuild.md
Rewritten documentation and architecture guides reflecting new package/module boundaries, CLI surface, client SDK API, backend auth/meta API design, and architecture diagrams.
CLI — Commands & Entrypoints
packages/cli/src/index.ts, packages/cli/src/commands/..., packages/cli/src/commands/login.ts
Reorganized CLI command registrations and exports; new login/logout command and credential helpers (runLoginCommand, runLogoutCommand, getCredentials, requireCredentials, Credentials) implemented; many command entry names renamed (runInitCommand, runDevCommand, runMigrateCommand, etc.).
Client SDK Public Surface
packages/client/src/client.ts, packages/client/src/query-builder.ts, packages/client/src/realtime.ts, packages/client/src/storage.ts, packages/client/src/index.ts, packages/client/src/types.ts, packages/client/src/errors.ts
Introduces modular client entry points and typed exports (createClient, QueryBuilder, Realtime, Storage, client types/errors) replacing the prior monolithic index.
Core — Config/GraphQL/Migrations/Middleware/Providers/Storage/Webhooks
packages/core/src/config/..., packages/core/src/graphql/..., packages/core/src/migration/..., packages/core/src/middleware/..., packages/core/src/providers/..., packages/core/src/storage/..., packages/core/src/webhooks/...
New public modules and exports reorganized by concern (config, graphql, migration, middleware, providers, storage, webhooks), with renamed and relocated entry files and explicit exported symbols.
Templates / Base App
templates/base/src/..., templates/base/src/db/schema.ts, templates/base/src/middleware/api-key.ts, templates/base/src/middleware/logger.ts, templates/base/src/routes/meta.ts
Adds API-key middleware, request-logger middleware, meta API routes, system table schemas (betterbase_project/keys/logs), and wires middleware ordering into template bootstrap.
Key Generation & Security Utilities
packages/cli/src/utils/key-generator.ts
Adds key generation, hashing, and secure-random utilities and exports types for generated keys and prefixes.
Misc — Renames & Re-exports
src/..., packages/... (many files across repo)
Widespread renames and re-export adjustments to establish clearer public API boundaries; numerous file relocations and export signature renames across packages.

Sequence Diagram(s)

sequenceDiagram
    participant User as CLI User
    participant CLI as bb CLI
    participant Auth as Auth Server
    participant Browser as Browser
    participant FS as Local Filesystem

    User->>CLI: runLoginCommand()
    CLI->>Auth: POST /auth/device-code (request device code)
    Auth-->>CLI: { deviceCode, userCode, verificationUrl, interval }
    CLI->>Browser: open(verificationUrl?user_code=...)
    CLI->>CLI: pollToken(deviceCode, interval...)
    Browser->>Auth: User authenticates & approves (via verification URL)
    Auth-->>Auth: bind token to deviceCode
    CLI->>Auth: POST /auth/token (poll with deviceCode)
    Auth-->>CLI: { accessToken, refreshToken, user, expiresAt }
    CLI->>FS: save ~/.betterbase/credentials.json
    CLI-->>User: print success
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • TypeScript SDK Client  #9 — Overlapping client SDK rework: adds/renames client modules (client, query-builder, realtime) and createClient/QueryBuilder symbols.
  • Codex-generated pull request #4 — CLI entrypoint and command handler changes that intersect with this PR's CLI registration and command renames.
  • Codex-generated pull request #6 — Implements CLI command functions (runInitCommand, runMigrateCommand, etc.) that are renamed/exposed in this PR.

Suggested labels

codex

Poem

🐰
I hopped through folders, tidy and bright,
Renamed the paths, set exports to right.
A browser winked, a device code spun,
Keys tucked safe when the login was done.
Hooray — the repo's map now shines in the sun! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Remove dashboard' does not match the actual changes, which involve comprehensive API reorganization, backend authentication infrastructure, and CLI command restructuring—not dashboard removal. Update the title to accurately reflect the main changes, such as 'Refactor public API and add backend authentication infrastructure' or 'Reorganize CLI/Client/Core APIs and implement login/API key system'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch remove-dashboard

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (1)
packages/cli/src/index.ts (1)

12-12: Prefer feature-flagged wiring over commented command blocks.

Line 12 and Lines 309-321 keep login/logout integration as comments. This path is not type-checked and tends to drift from the actual command implementation. Prefer either:

  1. wiring behind a runtime feature flag, or
  2. removing the commented block and tracking activation in a dedicated issue/doc.

Also applies to: 309-322

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/index.ts` at line 12, The commented-out login/logout imports
and wiring (runLoginCommand, runLogoutCommand) should be replaced with
feature-flagged registration instead of leaving commented code: add a runtime
flag (e.g., ENABLE_LOGIN_COMMAND env/config) and conditionally import or call
runLoginCommand and runLogoutCommand where commands are wired (the command
registration section in packages/cli/src/index.ts), so TypeScript checks those
symbols and keeps them in sync; alternatively, if you don't want runtime gating,
delete the commented lines and create a tracking issue/doc referenced in the
repo. Ensure the conditional path uses dynamic import or gated calls so
type-checking and build step still validate the functions when the flag is
enabled.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@betterbase_backend_rebuild.md`:
- Around line 378-379: The doc is inconsistent: the key format is declared as
`bb_<type>_<projectId>` but the examples/generation use
`bb_<type>_<projectId>_<random>`; update the documentation so both match by
choosing one canonical format and applying it everywhere — either change the
format definition to `bb_<type>_<projectId>_<random>` (and explain the
purpose/length/character set of `<random>`) or remove the `<random>` suffix from
the generation examples (lines showing `bb_<type>_<projectId>_<random>`) so they
conform to `bb_<type>_<projectId>`, and ensure the same decision is applied to
the other occurrences mentioned (lines ~407-409).
- Around line 1-4: The document header conflicts with the PR objective: update
the top section (the title and first 4 lines) so the scope and intent match the
PR "Remove dashboard" rather than "Dashboard Readiness"; specifically replace or
rewrite the title, priority line, and purpose/Who-this-is-for lines to state
that this is for removing the dashboard, clarify that the listed backend changes
are for decommissioning or decoupling dashboard features, and remove any
ordering/instruction claims that imply rebuilding the dashboard to avoid
implementation ambiguity.
- Around line 801-809: The route handler metaRoute.delete("/users/:userId")
currently only deletes from authUser and does not remove related sessions;
update the handler to also delete session rows tied to the user (e.g., delete
from the sessions table where sessions.user_id or sessions.userId equals userId)
before/within the same transaction as the authUser deletion, or explicitly rely
on and document a DB cascade; ensure you reference the authUser deletion and the
sessions deletion together (or wrap both operations in a single transaction) so
the endpoint truly removes both the user and their sessions.
- Around line 818-829: The parsed filters method, statusMin, and statusMax are
parsed but never applied to the DB queries; update the query building for logs
(the
db.select().from(betterbaseLogs).orderBy(desc(betterbaseLogs.createdAt)).limit(limit).offset(offset)
call) to conditionally add .where(...) clauses: add a
where(betterbaseLogs.method, '=', method) if method is present, add
where(betterbaseLogs.status, '>=', statusMin) if statusMin is defined, and add
where(betterbaseLogs.status, '<=', statusMax) if statusMax is defined; apply the
same conditional filters to the total count query (db.select({ count: count()
}).from(betterbaseLogs).get()) so the total reflects the filtered set.

In `@CODEBASE_MAP.md`:
- Line 40: Two markdown lint rules are failing: the fenced code blocks
(currently ``` at the block starting around the first large code fence and the
one near the repeated section) need explicit language identifiers to satisfy
MD040, and the table near the bottom of the document needs proper blank-line
spacing to satisfy MD058; update the two fenced code blocks (the opening
backticks at the top-level code block and the similar fenced block around line
879) to include the appropriate language tag (e.g., ```json, ```bash, or
```text) and insert a single blank line before and after the Markdown table
around the region flagged for MD058 so the table is separated from surrounding
text, then re-run markdownlint to confirm MD040 and MD058 are resolved.
- Around line 220-223: The CLI map entries in CODEBASE_MAP.md are out of sync
with the actual registered commands; inspect the CLI registration in index.ts to
get the canonical command names and signatures (e.g., the registered handlers
for "bb rls", "bb storage", "bb webhook" and the staged login), then update the
CODEBASE_MAP.md entries (including the documented usage lines and the entry for
runLoginCommand) to match the real command wiring and exported function names;
remove or mark as staged any commands not currently registered and ensure
usages/signatures exactly match what index.ts registers so the map and CLI
remain consistent.

In `@packages/cli/src/commands/login.ts`:
- Around line 14-169: The file currently has the full auth implementation
commented out which removes exports for runLoginCommand, runLogoutCommand,
getCredentials, and requireCredentials; add minimal explicit stub
implementations for these functions (exported) so the module compiles and other
code paths can call them: create simple async stubs for runLoginCommand and
runLogoutCommand that log a clear "not yet available" or throw a specific
NotImplemented error, implement getCredentials to return null and
requireCredentials to call getCredentials then log the same message and exit or
throw; ensure the exported Credentials type/signature is preserved and the stub
functions use the same names (runLoginCommand, runLogoutCommand, getCredentials,
requireCredentials) so switching back to the real implementation is trivial.

In `@README.md`:
- Around line 193-196: The README CLI examples (LoginCmd, RLSCmd, StorageCmd,
WebhookCmd and the dev --generate example) do not match the actual command
registrations in packages/cli/src/index.ts, causing copy/paste failures; sync
them by either updating README examples to use the exact subcommand names and
flags implemented in packages/cli/src/index.ts or by re-introducing the missing
commands into the CLI; inspect the command registration code in
packages/cli/src/index.ts (look for where commands are registered/defined) and
ensure README entries for login, rls, storage, webhook and the dev --generate
usage reflect the exact command names, options, and invocation patterns present
in that file.

---

Nitpick comments:
In `@packages/cli/src/index.ts`:
- Line 12: The commented-out login/logout imports and wiring (runLoginCommand,
runLogoutCommand) should be replaced with feature-flagged registration instead
of leaving commented code: add a runtime flag (e.g., ENABLE_LOGIN_COMMAND
env/config) and conditionally import or call runLoginCommand and
runLogoutCommand where commands are wired (the command registration section in
packages/cli/src/index.ts), so TypeScript checks those symbols and keeps them in
sync; alternatively, if you don't want runtime gating, delete the commented
lines and create a tracking issue/doc referenced in the repo. Ensure the
conditional path uses dynamic import or gated calls so type-checking and build
step still validate the functions when the flag is enabled.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fee82b3 and 655e007.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • CODEBASE_MAP.md
  • README.md
  • betterbase_backend_rebuild.md
  • packages/cli/src/commands/login.ts
  • packages/cli/src/index.ts

Comment on lines +1 to +4
# BetterBase — Backend Rebuild for Dashboard Readiness
> **Priority:** CRITICAL. Complete this entire document before touching the BetterBaseDashboard repo.
> **Why:** The dashboard cannot display real data without these backend changes. Every section in this document is a prerequisite for a specific dashboard feature.
> **Who this is for:** An LLM agent (Cursor, Codex) that will implement these changes. Read the entire document before writing a single line of code. The order of implementation matters.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Document scope conflicts with the PR objective.

Lines 1-4 frame this work as “dashboard readiness,” but the PR objective is “Remove dashboard.” This creates implementation ambiguity and should be reconciled before further work proceeds.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@betterbase_backend_rebuild.md` around lines 1 - 4, The document header
conflicts with the PR objective: update the top section (the title and first 4
lines) so the scope and intent match the PR "Remove dashboard" rather than
"Dashboard Readiness"; specifically replace or rewrite the title, priority line,
and purpose/Who-this-is-for lines to state that this is for removing the
dashboard, clarify that the listed backend changes are for decommissioning or
decoupling dashboard features, and remove any ordering/instruction claims that
imply rebuilding the dashboard to avoid implementation ambiguity.

Comment on lines +378 to +379
Structure: `bb_<type>_<projectId>`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Key format definition conflicts with the generation example.

Line 378 defines bb_<type>_<projectId>, but Lines 407-408 generate bb_<type>_<projectId>_<random>. Implementers following the declared format will reject generated keys.

🛠️ Proposed doc fix
-Structure: `bb_<type>_<projectId>`
+Structure: `bb_<type>_<projectId>_<random>`

Also applies to: 407-409

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@betterbase_backend_rebuild.md` around lines 378 - 379, The doc is
inconsistent: the key format is declared as `bb_<type>_<projectId>` but the
examples/generation use `bb_<type>_<projectId>_<random>`; update the
documentation so both match by choosing one canonical format and applying it
everywhere — either change the format definition to
`bb_<type>_<projectId>_<random>` (and explain the purpose/length/character set
of `<random>`) or remove the `<random>` suffix from the generation examples
(lines showing `bb_<type>_<projectId>_<random>`) so they conform to
`bb_<type>_<projectId>`, and ensure the same decision is applied to the other
occurrences mentioned (lines ~407-409).

Comment on lines +801 to +809
// ── DELETE /api/meta/users/:userId ───────────────────────────────────────────
// Deletes a user and their sessions

metaRoute.delete("/users/:userId", async (c) => {
const userId = c.req.param("userId")

await db.delete(authUser).where(eq(authUser.id, userId))

return c.json({ data: { deleted: true }, error: null })
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

User deletion snippet does not match its stated behavior.

Line 802 says user and sessions are deleted, but Line 807 only deletes from authUser. This leaves session cleanup undefined unless cascade rules are guaranteed.

🛠️ Proposed snippet fix
 metaRoute.delete("/users/:userId", async (c) => {
   const userId = c.req.param("userId")
 
+  await db.delete(authSession).where(eq(authSession.userId, userId))
   await db.delete(authUser).where(eq(authUser.id, userId))
 
   return c.json({ data: { deleted: true }, error: null })
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// ── DELETE /api/meta/users/:userId ───────────────────────────────────────────
// Deletes a user and their sessions
metaRoute.delete("/users/:userId", async (c) => {
const userId = c.req.param("userId")
await db.delete(authUser).where(eq(authUser.id, userId))
return c.json({ data: { deleted: true }, error: null })
// ── DELETE /api/meta/users/:userId ───────────────────────────────────────────
// Deletes a user and their sessions
metaRoute.delete("/users/:userId", async (c) => {
const userId = c.req.param("userId")
await db.delete(authSession).where(eq(authSession.userId, userId))
await db.delete(authUser).where(eq(authUser.id, userId))
return c.json({ data: { deleted: true }, error: null })
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@betterbase_backend_rebuild.md` around lines 801 - 809, The route handler
metaRoute.delete("/users/:userId") currently only deletes from authUser and does
not remove related sessions; update the handler to also delete session rows tied
to the user (e.g., delete from the sessions table where sessions.user_id or
sessions.userId equals userId) before/within the same transaction as the
authUser deletion, or explicitly rely on and document a DB cascade; ensure you
reference the authUser deletion and the sessions deletion together (or wrap both
operations in a single transaction) so the endpoint truly removes both the user
and their sessions.

Comment on lines +818 to +829
const method = c.req.query("method")
const statusMin = c.req.query("statusMin") ? parseInt(c.req.query("statusMin")!) : undefined
const statusMax = c.req.query("statusMax") ? parseInt(c.req.query("statusMax")!) : undefined

const logs = await db
.select()
.from(betterbaseLogs)
.orderBy(desc(betterbaseLogs.createdAt))
.limit(limit)
.offset(offset)

const total = await db.select({ count: count() }).from(betterbaseLogs).get()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Parsed log filters are never applied in the query.

Lines 818-821 parse method, statusMin, and statusMax, but Lines 822-828 fetch all logs without filtering.

🛠️ Proposed snippet fix
+  const filters = []
+  if (method) filters.push(eq(betterbaseLogs.method, method))
+  if (statusMin !== undefined) filters.push(gte(betterbaseLogs.statusCode, statusMin))
+  if (statusMax !== undefined) filters.push(sql`${betterbaseLogs.statusCode} <= ${statusMax}`)
+
   const logs = await db
     .select()
     .from(betterbaseLogs)
+    .where(filters.length ? and(...filters) : undefined)
     .orderBy(desc(betterbaseLogs.createdAt))
     .limit(limit)
     .offset(offset)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const method = c.req.query("method")
const statusMin = c.req.query("statusMin") ? parseInt(c.req.query("statusMin")!) : undefined
const statusMax = c.req.query("statusMax") ? parseInt(c.req.query("statusMax")!) : undefined
const logs = await db
.select()
.from(betterbaseLogs)
.orderBy(desc(betterbaseLogs.createdAt))
.limit(limit)
.offset(offset)
const total = await db.select({ count: count() }).from(betterbaseLogs).get()
const method = c.req.query("method")
const statusMin = c.req.query("statusMin") ? parseInt(c.req.query("statusMin")!) : undefined
const statusMax = c.req.query("statusMax") ? parseInt(c.req.query("statusMax")!) : undefined
const filters = []
if (method) filters.push(eq(betterbaseLogs.method, method))
if (statusMin !== undefined) filters.push(gte(betterbaseLogs.statusCode, statusMin))
if (statusMax !== undefined) filters.push(sql`${betterbaseLogs.statusCode} <= ${statusMax}`)
const logs = await db
.select()
.from(betterbaseLogs)
.where(filters.length ? and(...filters) : undefined)
.orderBy(desc(betterbaseLogs.createdAt))
.limit(limit)
.offset(offset)
const total = await db.select({ count: count() }).from(betterbaseLogs).get()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@betterbase_backend_rebuild.md` around lines 818 - 829, The parsed filters
method, statusMin, and statusMax are parsed but never applied to the DB queries;
update the query building for logs (the
db.select().from(betterbaseLogs).orderBy(desc(betterbaseLogs.createdAt)).limit(limit).offset(offset)
call) to conditionally add .where(...) clauses: add a
where(betterbaseLogs.method, '=', method) if method is present, add
where(betterbaseLogs.status, '>=', statusMin) if statusMin is defined, and add
where(betterbaseLogs.status, '<=', statusMax) if statusMax is defined; apply the
same conditional filters to the total count query (db.select({ count: count()
}).from(betterbaseLogs).get()) so the total reflects the filtered set.

Comment thread CODEBASE_MAP.md
Root --> Auth
```

```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Markdown lint warnings remain in changed sections.

Line 40 and Line 879 use fenced code blocks without language identifiers (MD040), and Line 899 violates blank-line spacing around tables (MD058).

Also applies to: 879-879, 899-899

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CODEBASE_MAP.md` at line 40, Two markdown lint rules are failing: the fenced
code blocks (currently ``` at the block starting around the first large code
fence and the one near the repeated section) need explicit language identifiers
to satisfy MD040, and the table near the bottom of the document needs proper
blank-line spacing to satisfy MD058; update the two fenced code blocks (the
opening backticks at the top-level code block and the similar fenced block
around line 879) to include the appropriate language tag (e.g., ```json,
```bash, or ```text) and insert a single blank line before and after the
Markdown table around the region flagged for MD058 so the table is separated
from surrounding text, then re-run markdownlint to confirm MD040 and MD058 are
resolved.

Comment thread CODEBASE_MAP.md
Comment on lines +220 to +223
#### [`commands/login.ts`](packages/cli/src/commands/login.ts)
**Purpose:** `bb login` command - authenticate with BetterBase cloud.
- **Exports:** `runLoginCommand(options)` - main function
- **Internal Deps:** `../utils/logger`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

CLI map is out of sync with the implemented CLI surface.

Line 222 and Lines 758-770 document command signatures/usages that don’t match current CLI wiring in packages/cli/src/index.ts (e.g., bb rls, bb storage, bb webhook, and staged bb login). Please align this map with actual registered commands to avoid command-not-found UX.

Also applies to: 758-770

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CODEBASE_MAP.md` around lines 220 - 223, The CLI map entries in
CODEBASE_MAP.md are out of sync with the actual registered commands; inspect the
CLI registration in index.ts to get the canonical command names and signatures
(e.g., the registered handlers for "bb rls", "bb storage", "bb webhook" and the
staged login), then update the CODEBASE_MAP.md entries (including the documented
usage lines and the entry for runLoginCommand) to match the real command wiring
and exported function names; remove or mark as staged any commands not currently
registered and ensure usages/signatures exactly match what index.ts registers so
the map and CLI remain consistent.

Comment on lines +14 to +169
/*
// ── bb login — STAGED FOR ACTIVATION ────────────────────────────────────────
// This code is complete and tested. Uncomment when app.betterbase.com is live.
// See: betterbase_backend_rebuild.md Part 3
// ────────────────────────────────────────────────────────────────────────────

const BETTERBASE_API = process.env.BETTERBASE_API_URL ?? "https://app.betterbase.com"
const CREDENTIALS_PATH = path.join(os.homedir(), ".betterbase", "credentials.json")
const POLL_INTERVAL_MS = 2000
const POLL_TIMEOUT_MS = 300000 // 5 minutes

// runLoginCommand
// Authenticates the CLI with app.betterbase.com via browser OAuth flow.
export async function runLoginCommand(): Promise<void> {
// Check if already logged in
const existing = await getCredentials()
if (existing) {
info(`Already logged in as ${existing.email}`)
info("Run bb logout to sign out.")
return
}

// Generate a one-time device code
const code = generateDeviceCode()
const authUrl = `${BETTERBASE_API}/cli/auth?code=${code}`

info("Opening browser for authentication...")
info(`Auth URL: ${authUrl}`)
info("Waiting for authentication... (timeout: 5 minutes)")

// Try to open the browser
await openBrowser(authUrl)

// Poll for authentication
const credentials = await pollForAuth(code)

if (!credentials) {
logError("Authentication timed out. Run bb login to try again.")
process.exit(1)
}

// Store credentials
await saveCredentials(credentials)
success(`Logged in as ${credentials.email}`)
}

// runLogoutCommand
// Removes stored credentials.
export async function runLogoutCommand(): Promise<void> {
if (existsSync(CREDENTIALS_PATH)) {
await fs.unlink(CREDENTIALS_PATH)
success("Logged out successfully.")
} else {
warn("Not currently logged in.")
}
}

// getCredentials
// Reads stored credentials from ~/.betterbase/credentials.json
// Returns null if not logged in or credentials expired.
export async function getCredentials(): Promise<Credentials | null> {
if (!existsSync(CREDENTIALS_PATH)) return null
try {
const raw = await fs.readFile(CREDENTIALS_PATH, "utf-8")
const creds = JSON.parse(raw) as Credentials
if (new Date(creds.expiresAt) < new Date()) return null
return creds
} catch {
return null
}
}

// requireCredentials
// Used by commands that require authentication (like bb init in managed mode).
// Exits with a helpful message if not logged in.
export async function requireCredentials(): Promise<Credentials> {
const creds = await getCredentials()
if (!creds) {
logError(
"Not logged in. Run: bb login\n" +
"This connects your CLI with app.betterbase.com so your project\n" +
"can be registered and managed from the dashboard."
)
process.exit(1)
}
return creds
}

// Internal helpers

function generateDeviceCode(): string {
const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
const part1 = Array.from({ length: 4 }, () => chars[Math.floor(Math.random() * chars.length)]).join("")
const part2 = Array.from({ length: 4 }, () => chars[Math.floor(Math.random() * chars.length)]).join("")
return `${part1}-${part2}`
}

async function openBrowser(url: string): Promise<void> {
const { platform } = process
try {
if (platform === "darwin") {
const { execSync } = await import("child_process")
execSync(`open "${url}"`, { stdio: "ignore" })
} else if (platform === "win32") {
const { execSync } = await import("child_process")
execSync(`start "" "${url}"`, { stdio: "ignore" })
} else {
const { execSync } = await import("child_process")
execSync(`xdg-open "${url}"`, { stdio: "ignore" })
}
} catch {
// Browser open failed — URL already printed, user can open manually
}
}

async function pollForAuth(code: string): Promise<Credentials | null> {
const startTime = Date.now()

while (Date.now() - startTime < POLL_TIMEOUT_MS) {
await sleep(POLL_INTERVAL_MS)

try {
const response = await fetch(
`${BETTERBASE_API}/api/cli/auth/poll?code=${code}`
)

if (response.status === 200) {
const data = await response.json() as {
token: string
email: string
userId: string
expiresAt: string
}
return data
}
// 202 = still pending, continue polling
// Any other status = error, continue polling until timeout
} catch {
// Network error — continue polling
}
}

return null
}

async function saveCredentials(creds: Credentials): Promise<void> {
const dir = path.dirname(CREDENTIALS_PATH)
await fs.mkdir(dir, { recursive: true })
await fs.writeFile(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8")
}

function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}

*/
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The login command API is effectively absent in this file.

Line 14 comments out the full implementation (runLoginCommand, runLogoutCommand, getCredentials, requireCredentials). The module currently exports only Credentials, which creates an availability gap and prevents compile-time coverage for the auth flow.

💡 Proposed stopgap (explicit stubs until activation)
+export async function runLoginCommand(): Promise<void> {
+  throw new Error("bb login is not enabled in this build.");
+}
+
+export async function runLogoutCommand(): Promise<void> {
+  throw new Error("bb logout is not enabled in this build.");
+}
+
+export async function getCredentials(): Promise<Credentials | null> {
+  return null;
+}
+
+export async function requireCredentials(): Promise<Credentials> {
+  throw new Error("Authentication is not enabled in this build.");
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/login.ts` around lines 14 - 169, The file currently
has the full auth implementation commented out which removes exports for
runLoginCommand, runLogoutCommand, getCredentials, and requireCredentials; add
minimal explicit stub implementations for these functions (exported) so the
module compiles and other code paths can call them: create simple async stubs
for runLoginCommand and runLogoutCommand that log a clear "not yet available" or
throw a specific NotImplemented error, implement getCredentials to return null
and requireCredentials to call getCredentials then log the same message and exit
or throw; ensure the exported Credentials type/signature is preserved and the
stub functions use the same names (runLoginCommand, runLogoutCommand,
getCredentials, requireCredentials) so switching back to the real implementation
is trivial.

Comment thread README.md
Comment on lines +193 to +196
Init -->|login| LoginCmd[User Login]
Init -->|rls| RLSCmd[Manage RLS Policies]
Init -->|storage| StorageCmd[Storage Operations]
Init -->|webhook| WebhookCmd[Webhook Management]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

README CLI examples currently contradict implemented commands.

Line 193 (login flow), Lines 629-672 (bb rls, bb storage, bb webhook usage), and Line 1006 (bb dev --generate) don’t match the current command surface in packages/cli/src/index.ts. This will cause immediate copy/paste failures for users.

Also applies to: 629-672, 1001-1007

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 193 - 196, The README CLI examples (LoginCmd, RLSCmd,
StorageCmd, WebhookCmd and the dev --generate example) do not match the actual
command registrations in packages/cli/src/index.ts, causing copy/paste failures;
sync them by either updating README examples to use the exact subcommand names
and flags implemented in packages/cli/src/index.ts or by re-introducing the
missing commands into the CLI; inspect the command registration code in
packages/cli/src/index.ts (look for where commands are registered/defined) and
ensure README entries for login, rls, storage, webhook and the dev --generate
usage reflect the exact command names, options, and invocation patterns present
in that file.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/index.ts`:
- Around line 298-307: The action callback currently treats projectRoot as part
of the options object but Commander passes positional args separately; update
the .action signature for the deploy command from (name, options) to (name,
projectRootArg, options) so the positional '[project-root]' is received, then
compute const projectRoot = projectRootArg ?? process.cwd() and pass that into
runFunctionCommand(['deploy', name, options.syncEnv ? '--sync-env' : ''],
projectRoot). Change references to the action callback on
fn.command('deploy')/.argument('[project-root]') so runFunctionCommand uses the
positional projectRoot parameter rather than options.projectRoot.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 655e007 and bb92526.

📒 Files selected for processing (1)
  • packages/cli/src/index.ts

Comment thread packages/cli/src/index.ts
Comment on lines +298 to +307
fn
.command('deploy')
.description('Deploy function to cloud')
.argument('<name>', 'function name')
.option('--sync-env', 'Sync environment variables from .env')
.argument('[project-root]', 'project root directory', process.cwd())
.action(async (name: string, options: { syncEnv?: boolean; projectRoot?: string }) => {
const projectRoot = options.projectRoot ?? process.cwd();
await runFunctionCommand(['deploy', name, options.syncEnv ? '--sync-env' : ''], projectRoot);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Bug: projectRoot argument won't be received in options object.

In Commander, positional arguments are passed as separate parameters to the action callback before the options object. With .argument('[project-root]'), the callback signature should be (name: string, projectRoot: string, options: {...}), not (name: string, options: { projectRoot?: string }).

Currently, options.projectRoot will always be undefined, causing the command to always use process.cwd() regardless of what the user provides.

🐛 Proposed fix
   fn
     .command('deploy')
     .description('Deploy function to cloud')
     .argument('<name>', 'function name')
-    .option('--sync-env', 'Sync environment variables from .env')
     .argument('[project-root]', 'project root directory', process.cwd())
-    .action(async (name: string, options: { syncEnv?: boolean; projectRoot?: string }) => {
-      const projectRoot = options.projectRoot ?? process.cwd();
-      await runFunctionCommand(['deploy', name, options.syncEnv ? '--sync-env' : ''], projectRoot);
+    .option('--sync-env', 'Sync environment variables from .env')
+    .action(async (name: string, projectRoot: string, options: { syncEnv?: boolean }) => {
+      await runFunctionCommand(['deploy', name, options.syncEnv ? '--sync-env' : ''], projectRoot);
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/index.ts` around lines 298 - 307, The action callback
currently treats projectRoot as part of the options object but Commander passes
positional args separately; update the .action signature for the deploy command
from (name, options) to (name, projectRootArg, options) so the positional
'[project-root]' is received, then compute const projectRoot = projectRootArg ??
process.cwd() and pass that into runFunctionCommand(['deploy', name,
options.syncEnv ? '--sync-env' : ''], projectRoot). Change references to the
action callback on fn.command('deploy')/.argument('[project-root]') so
runFunctionCommand uses the positional projectRoot parameter rather than
options.projectRoot.

@weroperking weroperking merged commit 519efbb into main Mar 1, 2026
1 check passed
@coderabbitai coderabbitai Bot mentioned this pull request Mar 5, 2026
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.

1 participant