fix(workspaces): wire top-header create-workspace button + clarify echodo db naming
The Create Workspace button in the top-header dropdown was still calling
`window.alert("Create workspace (placeholder)")` instead of opening the
real CreateWorkspaceDialog. Wires it to the same dialog the sidebar
workspace switcher uses.
Also clarifies in .env.example and AGENTS.md that the canonical Postgres
database name is `echodo` everywhere (local, Coolify, drizzle ledger,
docker-compose POSTGRES_DB). A stale `tasks` database on CT 102 from the
pre-rename era was the root cause of the 2026-06 Authentik "Configuration"
SSO outage: Coolify correctly pointed at `echodo` (which was empty), while
the only initialized schema lived in the relic `tasks` DB.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
8b981723b6
commit
011d3eb710
3 changed files with 23 additions and 5 deletions
14
.env.example
14
.env.example
|
|
@ -10,8 +10,14 @@
|
|||
# =====================================================================
|
||||
|
||||
# ----- Database (CT 102 shared Postgres) -----
|
||||
# Local dev: postgresql://postgres:postgres@localhost:5432/tasks
|
||||
# Production: dedicated `echodo` user/db on CT 102
|
||||
# The database name is `echodo` everywhere — local dev, Coolify, and the
|
||||
# drizzle migration ledger all assume it. Do NOT use `tasks` (an early
|
||||
# pre-rename name); see commit 93565cd and the 2026-06 drift incident for
|
||||
# why a parallel `tasks` DB caused production OAuth to look broken when
|
||||
# it was really just connected to an empty schema.
|
||||
#
|
||||
# Local dev (Docker compose): postgresql://postgres:postgres@localhost:5432/echodo
|
||||
# Production (Coolify, CT 102): dedicated `echodo` user/db on shared Postgres
|
||||
DATABASE_URL="postgresql://echodo:CHANGE_ME@192.168.68.102:5432/echodo"
|
||||
|
||||
# ----- Redis (CT 102 shared Redis) -----
|
||||
|
|
@ -79,7 +85,9 @@ MCP_SERVER_PORT=3001
|
|||
# =====================================================================
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=postgres
|
||||
POSTGRES_DB=tasks
|
||||
# Keep this aligned with the database name in DATABASE_URL above. The
|
||||
# docker-compose files default to `tasks` (the old name) — override here.
|
||||
POSTGRES_DB=echodo
|
||||
POSTGRES_PORT=5432
|
||||
REDIS_PORT=6379
|
||||
WEB_PORT=3000
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Operating manual for AI coding agents (Cursor, Codex, Copilot, etc.) working in this repo. Humans should read it too. Keep it short and accurate — if you change conventions in code, update this file in the same change.
|
||||
|
||||
> Product: **Echodo** — a multitenant task app whose backlog is mirrored as markdown under `plans/` and synced to Cursor.
|
||||
> Repo name on disk is `tasks`. Package scope is `@tasks/*`.
|
||||
> Repo name on disk is `tasks` and the package scope is `@tasks/*` (historical, pre-rename). Everything else — the database, the deploy, the public domain — is `echodo`. If you see a `tasks` database anywhere, it's an artifact of the old name; the source of truth is `echodo`.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -55,6 +55,8 @@ Run from the repo root unless noted. Always use `pnpm`, never `npm` or `yarn`.
|
|||
|
||||
Before opening a PR or finishing a task, run **`pnpm lint && pnpm type-check && pnpm test`** at minimum. Run `pnpm build` if you touched build config, server entry points, or cross-package exports.
|
||||
|
||||
If you edit anything under `apps/mcp-server/` or any library it imports, your changes won't be visible to MCP tool calls in the **current** Cursor chat — the MCP server is a long-lived stdio process per session and doesn't auto-reload. See the **MCP server lifecycle** section in [config/CursorSync.md](./config/CursorSync.md) for how to find and kill stale servers.
|
||||
|
||||
Tests live next to source as `*.test.ts` files. Vitest is configured per package (see `vitest.config.ts` in `packages/shared`, `packages/database`, `packages/ai`). When you add a new package that has logic worth verifying, copy one of those configs and add `test` / `test:watch` scripts to the package's `package.json`. CI gates merges on lint + type-check + test — see [.github/workflows/ci.yml](./.github/workflows/ci.yml).
|
||||
|
||||
---
|
||||
|
|
@ -64,6 +66,7 @@ Tests live next to source as `*.test.ts` files. Vitest is configured per package
|
|||
- Local dev reads `.env` at the repo root. `.env.example` documents every variable; keep it in sync when you add a new one.
|
||||
- `.env`, `*.secrets`, `*-credentials.*`, `id_rsa`, `*.key`, and `AGENT-DEPLOY.md` are gitignored. **Never** read `AGENT-DEPLOY.md` contents into a committed file, log, or PR description — it contains homelab IPs and credentials.
|
||||
- Production deploys run on Coolify (CT 107) against shared Postgres/Redis on CT 102. Don't change deploy assumptions (Docker compose files, `next.config.docker.ts`) without flagging it explicitly.
|
||||
- **The Postgres database name is `echodo`**, full stop — local dev, Coolify, the drizzle migration ledger, and the docker-compose `POSTGRES_DB` all need to agree. An older `tasks` database may still exist on CT 102 as a relic of the pre-rename era; treat it as a dev sandbox at best and never point Coolify at it. The 2026-06 "Authentik SSO returns `Configuration`" incident was caused by Coolify pointing at `echodo` (correct) while a stale `tasks` database had the only initialized schema.
|
||||
- `NEXT_PUBLIC_*` is the only browser-exposed prefix. Never put secrets behind it.
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { signOut } from "next-auth/react";
|
||||
import {
|
||||
|
|
@ -34,6 +35,7 @@ import {
|
|||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { CreateWorkspaceDialog } from "@/components/workspaces/create-workspace-dialog";
|
||||
import { useWorkspaceStore } from "@/lib/stores/workspace-store";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
@ -48,6 +50,7 @@ export function TopHeader({ onOpenSearch, onQuickAction }: TopHeaderProps) {
|
|||
const workspace = useWorkspaceStore((s) => s.currentWorkspace);
|
||||
const workspaceName = workspace?.name ?? "Workspace";
|
||||
const workspaceId = workspace?.id;
|
||||
const [createWorkspaceOpen, setCreateWorkspaceOpen] = useState(false);
|
||||
const initials = workspaceName.trim().slice(0, 2).toUpperCase() || "WS";
|
||||
|
||||
return (
|
||||
|
|
@ -157,7 +160,7 @@ export function TopHeader({ onOpenSearch, onQuickAction }: TopHeaderProps) {
|
|||
variant="outline"
|
||||
size="sm"
|
||||
className="w-full gap-1.5 text-xs"
|
||||
onClick={() => window.alert("Create workspace (placeholder)")}
|
||||
onClick={() => setCreateWorkspaceOpen(true)}
|
||||
>
|
||||
<Plus className="size-3.5" />
|
||||
Create Workspace
|
||||
|
|
@ -165,6 +168,10 @@ export function TopHeader({ onOpenSearch, onQuickAction }: TopHeaderProps) {
|
|||
</div>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<CreateWorkspaceDialog
|
||||
open={createWorkspaceOpen}
|
||||
onOpenChange={setCreateWorkspaceOpen}
|
||||
/>
|
||||
|
||||
{/* Center search bar */}
|
||||
<div className="flex flex-1 justify-center px-2">
|
||||
|
|
|
|||
Loading…
Reference in a new issue