Skip to content

feat(api): add project creation endpoint#6472

Merged
ogzhanolguncu merged 14 commits into
mainfrom
06-15-feat_api_add_project_creation_endpoint
Jun 19, 2026
Merged

feat(api): add project creation endpoint#6472
ogzhanolguncu merged 14 commits into
mainfrom
06-15-feat_api_add_project_creation_endpoint

Conversation

@ogzhanolguncu

@ogzhanolguncu ogzhanolguncu commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Adds POST /v2/projects.createProject, the first endpoint of the new projects API.

Creates a project (name + workspace-unique slug) scoped to the caller's workspace, then returns the project's slug. Duplicate slugs within a workspace are rejected with 409. Delete protection defaults to off.

Because it's the base of the stack, this PR also lands the shared scaffolding the later endpoints build on:

  • Project OpenAPI schema + the projects.* path scaffold.
  • RBAC project resource type + create_project action.
  • project.create audit event.
  • projects table queries (insert) and generated code.

Fixes # (issue)

Type of change

  • New feature (non-breaking change which adds functionality)

How should this be tested?

Covered by Go integration tests (svc/api/routes/v2_projects_create_project/):

  • 200 — create with a fresh slug; assert returned slug + meta.requestId, and a project.create audit log.
  • 409 — duplicate slug in the same workspace (err:unkey:data:project_already_exists).
  • 400 — missing name, missing slug, bad slug pattern (uppercase / _), slug too long, malformed JSON, missing auth header.
  • 401 — invalid token.
  • 403 — valid key without create_project.
mise exec -- bazel test //svc/api/routes/v2_projects_create_project:v2_projects_create_project_test

Checklist

  • Self-reviewed my own code
  • Commented on my code in hard-to-understand areas
  • Ran mise run fmt
  • Checked for warnings, there are none
  • Merged the latest changes from main onto my branch

@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
dashboard Ready Ready Preview, Comment Jun 19, 2026 10:03am
design Ready Ready Preview, Comment Jun 19, 2026 10:03am

Request Review

@mintlify

mintlify Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
unkey 🟢 Ready View Preview Jun 16, 2026, 10:49 AM

Comment thread pkg/db/queries/project_find_by_workspace_and_slug.sql
@ogzhanolguncu ogzhanolguncu marked this pull request as ready for review June 16, 2026 11:42

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues — one minor robustness note inline.

Reviewed changes — initial review of the new POST /v2/projects.createProject endpoint and the shared projects scaffolding it lands.

  • Add createProject handlerGetPrincipalBindBodyAuthorize(project.*.create_project)TxRetry wrapping InsertProject + a project.create audit log, returning {id, slug}. Ordering matches existing create handlers.
  • Duplicate handling — relies on the existing projects UNIQUE(workspace_id, slug) constraint; db.IsDuplicateKeyError maps to the new err:unkey:data:project_already_exists code (409 via the middleware mapping).
  • RBAC — new rbac.CreateProject action (Go) and create_project in projectActions (TS) plus both dashboard permission catalogs.
  • Errors / codes / docsproject_already_exists code, conflict middleware mapping, error .mdx page, and docs.json nav entry.
  • AuditProjectCreateEvent (project.create) and ProjectResourceType (project).
  • OpenAPI — request body (name 1-256, slug 1-256 pattern ^[a-z0-9]+(-[a-z0-9]+)*$), response {id, slug}, and the path index documenting 200/400/401/403/409/429/500. Generated gen.go + yaml regenerated.
  • Query renameFindProjectByWorkspaceSlugFindProjectByWorkspaceAndSlug across the .sql, generated code, BUILD.bazel, seed, and the 200 test.
  • Tests — 200 (incl. multi-create + audit-log assertion), 400 (missing/invalid/too-long fields, bad JSON, missing auth), 401, 403 action matrix, and 409 (dup within workspace + same slug in a different workspace succeeds).

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread svc/api/routes/v2_projects_create_project/handler.go Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues — one minor test-coverage note inline.

Reviewed changes — re-review of the delta since the prior pullfrog review: a tighter slug pattern, the new project id in the response, and audit-log metadata.

  • Tightened slug pattern^[a-z0-9-]+$^[a-z0-9]+(-[a-z0-9]+)*$ across request body, response data, and the rendered OpenAPI/gen.go, forbidding leading, trailing, and consecutive hyphens; descriptions and the 400 example detail updated to match.
  • Added project id to the responseV2ProjectsCreateProjectResponseData now returns {id, slug} (id pattern ^[a-zA-Z0-9_]+$, minLength 8), wired through the handler and asserted in the 200 test (proj_ prefix + echo equals the persisted project.ID).
  • Populated audit-log Meta — the project.create resource Meta changed from nil to {"name", "slug"}.
  • Renamed queryFindProjectByWorkspaceSlugFindProjectByWorkspaceAndSlug across .sql, generated code, BUILD.bazel, seed, and the 200 test.
  • Duplicate-key error — switched from fault.Wrap(err, …) to fault.New("project already exists", …) while keeping the same 409 code and public message.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread svc/api/routes/v2_projects_create_project/400_test.go

@chronark chronark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

let's clean up the schema a little, rest looks good

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — re-review of the delta since the prior pullfrog review (fe6e252, now rebased onto main): commit 379d65d refactor: allow actor util to accept session, which addresses chronark's request to have ctrlclient.Actor parse the session itself.

  • Actor now takes a *zen.Sessionctrlclient.Actor(p *principal.Principal, remoteIP, userAgent string) became Actor(s *zen.Session) (*ctrlv1.ActorInfo, error), reading the principal off s.GetPrincipal() and the origin off s.Location()/s.UserAgent() so handlers no longer assemble the arguments by hand; it now also seeds Meta with an empty map and returns an error when the session has no principal.
  • Updated the lone caller — the create-project handler calls ctrlclient.Actor(s) and propagates its error; the //pkg/zen dep was added to ctrlclient's BUILD.bazel.

This implements chronark's suggestion cleanly. The handler already calls s.GetPrincipal() before Actor(s), and GetPrincipal() is a cached field read (pkg/zen/session.go:129), so the second call inside Actor is safe and cheap. The only caller is updated and all three session methods used (GetPrincipal/Location/UserAgent) exist. chronark's review thread is already resolved.

Pullfrog  | View workflow run | Using Claude Opus𝕏

@ogzhanolguncu ogzhanolguncu added this pull request to the merge queue Jun 19, 2026
Merged via the queue into main with commit 1f4fbba Jun 19, 2026
16 checks passed
@ogzhanolguncu ogzhanolguncu deleted the 06-15-feat_api_add_project_creation_endpoint branch June 19, 2026 13:35
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.

3 participants