Skip to content

Scaffold API routes with OpenAPI documentation - #24

Merged
Andreas-Froyland merged 12 commits into
mainfrom
claude/multi-tenant-feedback-page-q83YH
Feb 9, 2026
Merged

Andreas-Froyland merged 12 commits into
mainfrom
claude/multi-tenant-feedback-page-q83YH

Conversation

@Andreas-Froyland

Copy link
Copy Markdown
Member

Related to #4

  • Install Zod for validation and @scalar/nuxt for OpenAPI docs
  • Create shared utilities for API routes:
    • Response formatter with standardized success/error format
    • Auth middleware (requireAuth, optionalAuth, role checking)
    • Input validation helpers with Zod schemas
    • Rate limiting stubs (placeholder for production implementation)
    • OpenAPI documentation helpers and common schemas
  • Configure Scalar module for API documentation at /api-docs
  • Scaffold authentication routes:
    • POST /api/auth/github/login - GitHub OAuth initiation (501)
    • GET /api/auth/github/callback - OAuth callback handler (501)
    • GET /api/auth/session - Current session info
  • Scaffold organization routes:
    • POST /api/orgs - Create organization (501)
    • GET /api/orgs/[slug] - Get organization (501)
  • Scaffold project routes:
    • POST /api/orgs/[slug]/projects - Create project (501)
    • GET /api/projects/[slug] - Get project (501)
  • Scaffold feedback routes:
    • POST /api/feedback - Create feedback (501)
    • GET /api/feedback - List with filters/pagination (501)
    • GET /api/feedback/[id] - Get single feedback (501)
    • POST /api/feedback/[id]/vote - Toggle vote (501)
  • Scaffold GitHub integration routes:
    • POST /api/github/webhook - Receive webhook events (501)
    • GET /api/github/issues - Search issues (501)
    • POST /api/github/issues - Create issue from feedback (501)
  • Create OpenAPI 3.0 specification endpoint at /api/openapi.json
  • All routes include comprehensive OpenAPI documentation
  • Protected routes return 401 when unauthenticated
  • Unimplemented routes return 501 with consistent error format

https://claude.ai/code/session_01VHP8WHUaGX3Wvqz7dRpUM3

Related to #4

- Install Zod for validation and @scalar/nuxt for OpenAPI docs
- Create shared utilities for API routes:
  * Response formatter with standardized success/error format
  * Auth middleware (requireAuth, optionalAuth, role checking)
  * Input validation helpers with Zod schemas
  * Rate limiting stubs (placeholder for production implementation)
  * OpenAPI documentation helpers and common schemas
- Configure Scalar module for API documentation at /api-docs
- Scaffold authentication routes:
  * POST /api/auth/github/login - GitHub OAuth initiation (501)
  * GET /api/auth/github/callback - OAuth callback handler (501)
  * GET /api/auth/session - Current session info
- Scaffold organization routes:
  * POST /api/orgs - Create organization (501)
  * GET /api/orgs/[slug] - Get organization (501)
- Scaffold project routes:
  * POST /api/orgs/[slug]/projects - Create project (501)
  * GET /api/projects/[slug] - Get project (501)
- Scaffold feedback routes:
  * POST /api/feedback - Create feedback (501)
  * GET /api/feedback - List with filters/pagination (501)
  * GET /api/feedback/[id] - Get single feedback (501)
  * POST /api/feedback/[id]/vote - Toggle vote (501)
- Scaffold GitHub integration routes:
  * POST /api/github/webhook - Receive webhook events (501)
  * GET /api/github/issues - Search issues (501)
  * POST /api/github/issues - Create issue from feedback (501)
- Create OpenAPI 3.0 specification endpoint at /api/openapi.json
- All routes include comprehensive OpenAPI documentation
- Protected routes return 401 when unauthenticated
- Unimplemented routes return 501 with consistent error format

https://claude.ai/code/session_01VHP8WHUaGX3Wvqz7dRpUM3
- Add .github/workflows/ci.yml: four parallel jobs (lint, typecheck,
  test, build) on push to main and PRs targeting main, Node 20 LTS
  with yarn cache.  Build step runs `npx nuxt build` directly to skip
  the postbuild hook that requires a live database.
- Wire ESLint (flat config via @nuxt/eslint-config), Prettier, and
  Vitest as devDependencies; add lint, format:check, typecheck, and
  test scripts to package.json.
- eslint.config.mjs: excludes shadcn-vue generated components/ui/,
  downgrades no-explicit-any to warn (drizzle ORM patterns).
- Add vitest.config.ts and a first unit test (tests/utils.test.ts)
  covering the cn() helper.
- Run Prettier over the entire repo so format:check is green from day
  one; fix the handful of lint errors that surfaced (dead imports,
  unused-var prefixes).
- Add CI status badge to README.

https://claude.ai/code/session_0143PEXicpSS8sXgc83Ljr9U
Resolved conflicts in NavUser, TeamSwitcher, auth.ts, and email.ts
by taking the CI branch's cleaner Options API approach with consistent
formatting from prettier/eslint.

https://claude.ai/code/session_01Fy84J7B89N5ry8MyFzdDnR
Brings in scaffolded API routes for feedback, projects, organizations,
GitHub integration, OpenAPI documentation, and server utilities
(auth middleware, rate limiting, validation, response helpers).

https://claude.ai/code/session_01Fy84J7B89N5ry8MyFzdDnR
Schema:
- Add customDomain field to project table with unique index

API Routes (implemented, replacing 501 stubs):
- POST /api/orgs/:slug/projects - Create project with default categories
- GET /api/orgs/:slug/projects - List org projects with feedback counts
- GET /api/projects/:slug - Get project details with categories
- GET /api/feedback - List feedback with filtering, sorting, pagination
- POST /api/feedback - Create feedback (supports anonymous submissions)
- POST /api/feedback/:id/vote - Toggle vote on feedback

Public API (new, no auth required):
- GET /api/public/:orgSlug/:projectSlug - Project info, stats, categories
- GET /api/public/:orgSlug/:projectSlug/feedback - Public feedback listing
- POST /api/public/:orgSlug/:projectSlug/feedback - Submit feedback publicly

Frontend:
- /products - Dashboard page for managing products per organization
- /p/:orgSlug/:projectSlug - Public feedback page (no layout/sidebar)
- Products link added to sidebar navigation
- /products added to protected routes in auth middleware

Infrastructure:
- hasOrganizationRole() now queries the member table
- Each product gets a public URL: /p/{org-slug}/{product-slug}
- Custom domains stored for future DNS-based routing

https://claude.ai/code/session_01Fy84J7B89N5ry8MyFzdDnR
@vercel

vercel Bot commented Feb 8, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
veerify Error Error Feb 9, 2026 3:42pm

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c03bdcd1a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/api/orgs/[slug]/projects.get.ts Outdated
const [membership] = await db
.select()
.from(member)
.where(eq(member.organizationId, org.id))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restrict membership lookup to requesting user

The authorization check only verifies that the organization has at least one member row, not that the current session user belongs to it. As written, any authenticated user can pass this guard for most organizations and read their project list/feedback counts. Add a member.userId === session.user.id condition to this query so access is scoped to the caller.

Useful? React with 👍 / 👎.

Comment thread server/api/projects/[slug].get.ts Outdated
projects = await db
.select()
.from(project)
.where(eq(project.slug, slug))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Apply org filter when resolving project by slug

When orgSlug is supplied, the code resolves the organization but then queries projects by slug only, so the org constraint is never applied. If multiple organizations use the same project slug, this endpoint can return the wrong tenant's project data despite the caller specifying an org, which breaks disambiguation and can leak cross-org data. Include project.organizationId = org.id in this branch's where clause.

Useful? React with 👍 / 👎.

- Implemented team creation and membership functionality.
- Updated project schema to include team association.
- Added endpoints for managing projects within teams.
- Enhanced session management to support active team context.
- Migrated existing data to accommodate new team structure.
- Updated OpenAPI documentation to reflect new team and project relationships.
…onfigurations

feat: enhance database connection handling in run-playwright-if-available script
test: improve team-primary workspace spec with API interactions and session management
@Andreas-Froyland
Andreas-Froyland merged commit 410fe76 into main Feb 9, 2026
8 of 11 checks passed
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