Skip to content

feat(resourcemanager): Unify organization model and onboarding gate#675

Open
mattdjenkinson wants to merge 14 commits into
mainfrom
feat/unified-organizations
Open

feat(resourcemanager): Unify organization model and onboarding gate#675
mattdjenkinson wants to merge 14 commits into
mainfrom
feat/unified-organizations

Conversation

@mattdjenkinson

Copy link
Copy Markdown
Contributor

Summary

Personal and Standard org types split the same resource into two code paths and locked people into workspaces they could not grow out of. This change removes spec.type, adds org-level contactInfo, and introduces a single onboarding gate the API can enforce.

Portal clients create orgs with generateName: org- and a display name only. The mutating webhook defaults that prefix for non-admin callers; the validating webhook rejects user-chosen slugs. An org is onboarding-complete when contact info (email and name), a billing account in the org namespace, and DefaultPaymentMethodReady on that account are all present. The organization controller writes that outcome to status.conditions[OnboardingComplete].

Related enhancement: datum-cloud/enhancements#770. Portal UI work is tracked separately and is not in this PR.

Supersedes #673 (reopened after branch restore).

Test plan

  • go build ./...
  • go test ./internal/controllers/resourcemanager/... ./internal/webhooks/resourcemanager/...
  • Chainsaw suites updated for org fixtures without spec.type
  • Manual create with generateName: org- assigns an opaque name and owner membership
  • OnboardingComplete flips to True when contact info and billing payment method are ready

Breaking changes

  • Organization.spec.type is removed. Clients must stop sending or reading it.
  • OrganizationMembership.status.organization.type is removed; contactEmail is cached instead.
  • Non-admin org creates must use metadata.generateName with prefix org-.

Notes for reviewers

  • Depends on go.miloapis.com/billing for typed reads in the onboarding reconciler.
  • Migration steps live in docs/runbooks/unified-organizations-migration.md.
  • Deploy before or with the matching datum PR that removes auto-provision.

Related to #636

mattdjenkinson and others added 7 commits June 28, 2026 16:18
Collapse Personal/Standard into a single org with contactInfo and an
OnboardingComplete status condition reconciled from billing readiness.
🤖 Automatically added newlines to 6 file(s)

Co-Authored-By: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
The onboarding controller imports go.miloapis.com/billing but go.sum
was not updated when the module was added, breaking CI builds.
The info and created-timestamp generators were accidentally merged into
one YAML object, duplicating resource/families keys and failing kustomize
validation.
Remove leftover spec.type from e2e org fixtures, drop empty spec from
grant-creation assert, and treat missing BillingAccount API as no billing
account in test clusters without billing CRDs.
The organization controller registered a BillingAccount informer even in
test clusters without the billing API, contributing to controller-manager
restarts and webhook connection refused failures during parallel chainsaw
runs. Also extend owner-protection namespace cleanup timeout for CI load.
@scotwells

Copy link
Copy Markdown
Contributor

The tight coupling this introduces between the billing service and milo's core system seems rigid. Wonder if we can consider a more dynamic model where services can register onboarding gates with an organization that they're responsible for providing status for?

@mattdjenkinson

Copy link
Copy Markdown
Contributor Author

@scotwells we could do something like introduce an OrganizationOnboardingGate resource per org (e.g. contact-info, billing in the org namespace). Each service owns its gate and sets status.conditions[Ready]; milo’s org controller only creates the required gates, watches them, and aggregates into OnboardingComplete that the UIs can watch for?

mattdjenkinson and others added 5 commits June 30, 2026 10:29
…feature flag

Keep deprecated spec.type in the schema and switch webhook, onboarding,
and membership behavior based on the feature gate so environments can roll
out gradually without divergent CRD bundles.
Fix compile error in organization_defaults.go so webhook tests and CI
builds succeed again.
The deployment passes --feature-gates=$(FEATURE_GATES) but the
controller-manager command did not expose the flag, causing the pod
to crash on startup during test-environment-validation.
E2E tests run with UnifiedOrganizations disabled, so organization creates
must include spec.type until the test environment enables the unified gate.
🤖 Automatically added newlines to 21 file(s)

Co-Authored-By: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 I automatically added missing newlines at the end of 21 file(s) in this PR.

All files should now end with a newline character as per coding standards.

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