Skip to content

refactor: encapsulate project creation logic into the ProjectCreator interface#6557

Merged
evankanderson merged 7 commits into
mindersec:mainfrom
ShantKhatri:feat/issue-5002
Jul 9, 2026
Merged

refactor: encapsulate project creation logic into the ProjectCreator interface#6557
evankanderson merged 7 commits into
mindersec:mainfrom
ShantKhatri:feat/issue-5002

Conversation

@ShantKhatri

Copy link
Copy Markdown
Contributor

Summary

The PR centralizes project creation logic into internal/projects, removing duplication between the control plane and the projects module.

Before, CreateProject in handlers_projects.go directly managed the DB transaction, authz check, and feature flag validation before delegating to ProvisionChildProject / ProvisionSelfEnrolledProject.

Now, a new ProvisionProject method on the ProjectCreator interface owns the full creation orchestration. The handler is now a thin gRPC adapter.

Changes as, internal/projects/creator.go is the core change. ProvisionProject is added to the ProjectCreator interface with db.Store and flags.Interface injected as dependencies, so the module now owns its own transaction boundaries, authz checks, and feature flag gates. As a result, CreateProject in internal/controlplane/handlers_projects.go is reduced to a single delegate call with no business logic. internal/service/service.go is updated to pass store and featureFlagClient to NewProjectCreator to satisfy the new dependencies. Test call sites in creator_test.go and handlers_user_test.go are updated accordingly to supply the two new constructor arguments.

The flaggable intentional design made here is to makeProjectFactory in service.go still calls ProvisionSelfEnrolledProject directly with an existing db.ExtendQuerier. GitHub App webhook flows arrive with an in-flight transaction that must not be re-wrapped; routing those through ProvisionProject would start a nested transaction.

Fixes #5002

Testing

  1. Install required tools
    make bootstrap

  2. Generate example rules/profiles used by some tests
    make init-examples

image
  1. Lint
    make lint
image
  1. Run tests for affected packages
    go test ./internal/projects/... ./internal/controlplane/... ./internal/service/...
image
  1. Full suite
    go test ./...
image

…interface

Signed-off-by: Prashantkumar Khatri <khatri2105104@st.jmi.ac.in>
@ShantKhatri ShantKhatri requested a review from a team as a code owner June 29, 2026 18:38

@intelligent-ears intelligent-ears left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice work on this, @ShantKhatri — this is a clean shape for the refactor and matches what the issue asked for. A couple of things I'd like addressed before merging, the authz one being the one I'd consider blocking.

Comment thread internal/projects/creator.go Outdated
…ject creator

Signed-off-by: Prashantkumar Khatri <khatri2105104@st.jmi.ac.in>

@intelligent-ears intelligent-ears left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The existing tests were updated for the new constructor signature (mockStore, &flags.FakeClient{}), but I don't see new tests targeting ProvisionProject itself. Since this method now owns permission checks, the feature-flag gate, and transaction boundaries — logic that previously lived in the handler — could we get coverage for:

  • child-project creation when authzClient.Check denies
  • child-project creation when ProjectAllowsProjectHierarchyOperations is false
  • top-level creation when flags.ProjectCreateDelete is disabled
  • top-level creation with no identity in context
  • the project == nil post-creation guard

Even a few table-driven cases covering these branches would close the gap left by the handler logic moving here.

@evankanderson evankanderson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I realize that we didn't have existing coverage for this code, but it might be good to add test coverage while you're here. Other than that, a couple comments on the service interface between the handlers in controlplane and the rest of the system -- this is somewhere that we were pretty sloppy at first, but we've been trying to clean things up over time.

Comment thread internal/authz/interface.go Outdated
Comment thread internal/projects/creator.go Outdated
Comment thread internal/projects/creator.go Outdated
@ShantKhatri

Copy link
Copy Markdown
Contributor Author

The existing tests were updated for the new constructor signature (mockStore, &flags.FakeClient{}), but I don't see new tests targeting ProvisionProject itself. Since this method now owns permission checks, the feature-flag gate, and transaction boundaries — logic that previously lived in the handler — could we get coverage for:

  • child-project creation when authzClient.Check denies
  • child-project creation when ProjectAllowsProjectHierarchyOperations is false
  • top-level creation when flags.ProjectCreateDelete is disabled
  • top-level creation with no identity in context
  • the project == nil post-creation guard

Even a few table-driven cases covering these branches would close the gap left by the handler logic moving here.

Fair, will add table-driven tests covering as Check denied, hierarchy flag off, top-level flag disabled, missing identity, and the nil project guard. Will be straightforward since the logic is now centralized.

@ShantKhatri

Copy link
Copy Markdown
Contributor Author

I realize that we didn't have existing coverage for this code, but it might be good to add test coverage while you're here. Other than that, a couple comments on the service interface between the handlers in controlplane and the rest of the system -- this is somewhere that we were pretty sloppy at first, but we've been trying to clean things up over time.

Thanks for the review. For sure, I'll be adding the test coverage as described by @intelligent-ears.

@coveralls

coveralls commented Jul 3, 2026

Copy link
Copy Markdown

Coverage Status

Coverage is 60.926%ShantKhatri:feat/issue-5002 into mindersec:main. No base build found for mindersec:main.

…z checks in project handlers

Signed-off-by: Prashantkumar Khatri <khatri2105104@st.jmi.ac.in>
@ShantKhatri

Copy link
Copy Markdown
Contributor Author

The existing tests were updated for the new constructor signature (mockStore, &flags.FakeClient{}), but I don't see new tests targeting ProvisionProject itself. Since this method now owns permission checks, the feature-flag gate, and transaction boundaries — logic that previously lived in the handler — could we get coverage for:

  • child-project creation when authzClient.Check denies
  • child-project creation when ProjectAllowsProjectHierarchyOperations is false
  • top-level creation when flags.ProjectCreateDelete is disabled
  • top-level creation with no identity in context
  • the project == nil post-creation guard

Even a few table-driven cases covering these branches would close the gap left by the handler logic moving here.

Done! I've added a comprehensive table-driven test (TestProvisionProject) in creator_test.go that covers all of these branches: child-project creation (when authzClient.Check denies and when ProjectAllowsProjectHierarchyOperations is false), top-level creation (when ProjectCreateDelete is disabled and with no identity in context), as well as the successful happy path. CC: @evankanderson

evankanderson
evankanderson previously approved these changes Jul 9, 2026

@evankanderson evankanderson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

test coverage looks good, thanks!

Need to fix the lint error, and then should be good to merge

Comment thread internal/authz/interface.go Outdated
Comment thread internal/projects/creator.go Outdated
Co-authored-by: Evan Anderson <evan.k.anderson@gmail.com>

@intelligent-ears intelligent-ears left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM !

@evankanderson evankanderson merged commit 1eebaad into mindersec:main Jul 9, 2026
27 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.

Refactor Project Creation into internal/projects Module

4 participants