Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@

## High Impact, Moderate Effort – Do Next

- [ ] Agent personas for chat — per-project `system_prompt` in settings + per-section `agent_prompt` override. Ship 5-6 presets (PRD Architect, Technical Reviewer, UX/Design, QA Strategist, Executive Summary). Users pick preset or write custom. Passed as system message to the chat provider. Section-level prompt overrides project-level when chatting in that section context.
- [ ] Section templates — offer project templates beyond blank/SnapHabit: "SaaS MVP", "API Design", "Mobile App", "Infrastructure Migration". Each is a seed SQL or importable markdown showcasing different dependency patterns.
- [ ] add notes (accordion) to section. Here, I would like the option to add a note to the entire section.
- [ ] We need to update the readme relative to all our recent changes, create a preview as we did through the playwrite, and make it as commercially product-successful as possible to attract potential users' attention.
- [ ] Agent personas for chat — per-project `system_prompt` in settings + per-section `agent_prompt` override. Ship 5-6 presets (PRD Architect, Technical Reviewer, UX/Design, QA Strategist, Executive Summary). Users pick preset or write custom. Passed as system message to the chat provider. Section-level prompt overrides project-level when chatting in that section context. *(Base system prompt exists in `_chat_system_prompt`, needs UI + per-project/section override)*

## Medium Impact, Lower Effort – Quick Wins

- [ ] CONTRIBUTING.md — how to run tests locally, code style expectations, PR process
- [ ] GitHub repo metadata — description, topics/tags (`mcp`, `claude`, `prd`, `product-requirements`, `ai-tools`, `developer-tools`, `mcp-server`), website URL
- [ ] `prd_diff_sections` tool — unified diff between two revisions of a section, avoids loading both and diffing manually
- [ ] ui playwrite tests
- [ ] add playwrite preview autoupdate (ci for pr + agents.md for agents instaction which sections observe)
- [ ] UI Playwright tests

## Medium Impact, Higher Effort – Plan For These

Expand All @@ -34,10 +30,9 @@
- [ ] Add `prd_merge_sections` tool (combine two sections into one)
- [ ] Add `prd_reorder_sections` tool (bulk sort_order update)
- [ ] Export as PDF via headless browser
- [ ] UI: keyboard navigation (j/k to move through sections, Enter to select)
- [ ] MCP auth for remote Claude clients (SSH tunnel or authenticated ingress)
- [ ] Redis jti uniqueness for WS tokens (SET NX EX — currently TODO in code)
- [ ] move to tasks github projects
- [ ] add Playwright preview autoupdate (CI for PR + agents.md for agent instructions on which sections to observe)

## Done

Expand Down Expand Up @@ -88,3 +83,8 @@
- [x] Org-level encrypted API key — Fernet/AES-256
- [x] Wider chat section — 40% viewport width, min 480px, max 700px
- [x] Honest token savings math — section_access_log with session-based dedup, coverage fractions (full/summary/snippet), 30-min session windowing
- [x] Section templates — SaaS MVP, Mobile App project templates with seeded sections and dependencies
- [x] Notes accordion — per-section collapsible notes with inline editing
- [x] README + Playwright demo preview — `scripts/record_demo.py` rewritten, demo.gif regenerated
- [x] Redis jti uniqueness for WS tokens — SET NX EX replay protection in websocket handler
- [x] Security hardening — member endpoint auth, ws-token auth from session, schema-qualified `to_regclass`, default secret warnings
4 changes: 2 additions & 2 deletions api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2463,7 +2463,7 @@ async def add_project_member(slug: str, request: Request):
VALUES ($1, $2, $3)
ON CONFLICT (project_id, user_id) DO UPDATE SET role = EXCLUDED.role
RETURNING id, user_id, role, created_at
""", proj["id"], _uuid.UUID(user_id), role)
""", proj["id"], user_id, role)
return row_dict(row)
except Exception:
return JSONResponse({"error": "internal error"}, 500)
Expand All @@ -2484,7 +2484,7 @@ async def remove_project_member(slug: str, user_id: str, request: Request):
return JSONResponse({"error": f"project '{slug}' not found"}, 404)
result = await pool.execute(
"DELETE FROM project_members WHERE project_id = $1 AND user_id = $2",
proj["id"], _uuid.UUID(user_id),
proj["id"], user_id,
)
removed = result.split()[-1] != "0"
return {"removed": removed}
Expand Down
14 changes: 7 additions & 7 deletions db/07_multi_user.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ DO $$ BEGIN
SELECT 1 FROM information_schema.columns
WHERE table_name = 'projects' AND column_name = 'created_by'
) THEN
ALTER TABLE projects ADD COLUMN created_by UUID;
ALTER TABLE projects ADD COLUMN created_by TEXT;
END IF;
END $$;

Expand All @@ -25,7 +25,7 @@ DO $$ BEGIN
SELECT 1 FROM information_schema.columns
WHERE table_name = 'sections' AND column_name = 'updated_by'
) THEN
ALTER TABLE sections ADD COLUMN updated_by UUID;
ALTER TABLE sections ADD COLUMN updated_by TEXT;
END IF;
END $$;

Expand All @@ -34,7 +34,7 @@ DO $$ BEGIN
SELECT 1 FROM information_schema.columns
WHERE table_name = 'section_revisions' AND column_name = 'created_by'
) THEN
ALTER TABLE section_revisions ADD COLUMN created_by UUID;
ALTER TABLE section_revisions ADD COLUMN created_by TEXT;
END IF;
END $$;

Expand All @@ -43,7 +43,7 @@ DO $$ BEGIN
SELECT 1 FROM information_schema.columns
WHERE table_name = 'section_comments' AND column_name = 'created_by'
) THEN
ALTER TABLE section_comments ADD COLUMN created_by UUID;
ALTER TABLE section_comments ADD COLUMN created_by TEXT;
END IF;
END $$;

Expand All @@ -52,7 +52,7 @@ DO $$ BEGIN
SELECT 1 FROM information_schema.columns
WHERE table_name = 'chat_messages' AND column_name = 'created_by'
) THEN
ALTER TABLE chat_messages ADD COLUMN created_by UUID;
ALTER TABLE chat_messages ADD COLUMN created_by TEXT;
END IF;
END $$;

Expand All @@ -61,15 +61,15 @@ DO $$ BEGIN
SELECT 1 FROM information_schema.columns
WHERE table_name = 'mcp_activity' AND column_name = 'user_id'
) THEN
ALTER TABLE mcp_activity ADD COLUMN user_id UUID;
ALTER TABLE mcp_activity ADD COLUMN user_id TEXT;
END IF;
END $$;

-- Project members (5 roles)
CREATE TABLE IF NOT EXISTS project_members (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
user_id UUID NOT NULL,
user_id TEXT NOT NULL,
role TEXT NOT NULL CHECK (role IN ('owner', 'admin', 'editor', 'commenter', 'viewer')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
Expand Down
Binary file modified demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading