Skip to content

Make tenancy quotas (workspaces/user, environments/workspace) configurable via LIMITS_* env vars#144

Open
andhus wants to merge 1 commit into
mainfrom
bump-env-limit-to-15
Open

Make tenancy quotas (workspaces/user, environments/workspace) configurable via LIMITS_* env vars#144
andhus wants to merge 1 commit into
mainfrom
bump-env-limit-to-15

Conversation

@andhus
Copy link
Copy Markdown
Collaborator

@andhus andhus commented May 25, 2026

Summary

Moves the two hardcoded class constants on Workspace
MAX_WORKSPACES_PER_USER (3) and MAX_ENVIRONMENTS_PER_WORKSPACE (6) —
into the existing LimitsSettings (pydantic-settings, LIMITS_* env
vars), so they follow the same OSS-safe + env-overridable pattern as
the other SaaS guardrails in app/stardag-api/src/stardag_api/limits.py.

Why

Re-using LimitsSettings instead of constants:

  • OSS-safe defaults. None = no enforcement, matching the rest of
    the file's "all limits default to disabled" contract. Self-hosted
    users hit no hidden cap.
  • Env-overridable per deployment. Operators tune quotas without a
    code release.
  • Single source of truth for SaaS quotas. The two quotas now live
    next to max_*_per_workspace_24h etc., not as anonymous class-level
    ints inside an ORM model.

What changed

File Change
app/stardag-api/src/stardag_api/limits.py Add max_workspaces_per_user and max_environments_per_workspace fields to LimitsSettings (None default).
app/stardag-api/src/stardag_api/models/workspace.py Remove the two MAX_* class constants.
app/stardag-api/src/stardag_api/routes/workspaces.py Read from limits_settings.max_* in create_workspace and create_environment; skip the check when value is None.
infra/aws-cdk/lib/api-stack.ts Add LIMITS_MAX_WORKSPACES_PER_USER: "3" and LIMITS_MAX_ENVIRONMENTS_PER_WORKSPACE: "15" to the ECS task environment block, next to the other LIMITS_* values.

Backwards-compat

  • Self-hosted / OSS deployments without LIMITS_* set: behaviour
    changes from "3 workspaces, 6 environments" to "unlimited". This
    matches the documented contract for limits.py ("all limits default
    to None / disabled for OSS-safe operation").
  • Deployments using the bundled CDK template: pick up the explicit
    3 / 15 values. The env-cap goes from 6 → 15.

Notes

  • The env-cap bump (6 → 15) is the motivating fix here: a deployed
    workspace had hit the old cap.
  • Pure config / wiring change. No DB migration. No schema change.
  • No tests reference the old constants directly.

Test plan

  • CI green.
  • After deploy with the new CDK values, POST /api/v1/ui/workspaces/{id}/environments succeeds in a workspace that previously had exactly 6 envs.
  • Unset LIMITS_MAX_ENVIRONMENTS_PER_WORKSPACE locally → no env cap enforced.

🤖 Generated with Claude Code

The two hardcoded class constants on Workspace —
MAX_WORKSPACES_PER_USER and MAX_ENVIRONMENTS_PER_WORKSPACE — couldn't
be tuned per deployment without a code release. Move them into the
existing LimitsSettings (pydantic-settings, env prefix LIMITS_) so
they follow the same OSS-safe + env-overridable pattern as the other
SaaS guardrails in limits.py:

- Defaults to None (unlimited) for OSS / self-hosted users.
- Production sets concrete caps via env vars on the ECS task
  definition (added to infra/aws-cdk/lib/api-stack.ts).

Production values (3 workspaces/user, 15 envs/workspace) are added to
the api-stack.ts environment block alongside the other LIMITS_*
values. The 15 env cap raises the previous hardcoded 6, which a
deployed workspace had hit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@andhus andhus force-pushed the bump-env-limit-to-15 branch from 5e57283 to 0d850c1 Compare May 25, 2026 18:59
@andhus andhus changed the title Raise MAX_ENVIRONMENTS_PER_WORKSPACE from 6 to 15 Make tenancy quotas (workspaces/user, environments/workspace) configurable via LIMITS_* env vars May 25, 2026
@andhus andhus requested a review from Copilot May 25, 2026 19:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR moves two tenancy quota limits (workspaces per user, environments per workspace) out of hardcoded Workspace model constants and into the existing LimitsSettings configuration, making them configurable via LIMITS_* environment variables and defaulting to OSS-safe “disabled” (None) when unset.

Changes:

  • Added max_workspaces_per_user and max_environments_per_workspace to LimitsSettings (default None).
  • Updated workspace/environment creation routes to enforce these limits only when configured.
  • Updated the AWS CDK ECS task environment to set the new LIMITS_MAX_* variables.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
infra/aws-cdk/lib/api-stack.ts Adds tenancy quota env vars to the API container environment.
app/stardag-api/src/stardag_api/routes/workspaces.py Switches quota enforcement from model constants to limits_settings with None disabling.
app/stardag-api/src/stardag_api/models/workspace.py Removes hardcoded quota constants from the ORM model.
app/stardag-api/src/stardag_api/limits.py Adds new configurable tenancy quota fields to LimitsSettings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 209 to +213
LIMITS_MAX_ASSETS_PER_WORKSPACE_24H: "1000",
LIMITS_MAX_DEPENDENCY_IDS_PER_TASK: "500",
LIMITS_MAX_ASSETS_PER_TASK: "10",
LIMITS_MAX_WORKSPACES_PER_USER: "3",
LIMITS_MAX_ENVIRONMENTS_PER_WORKSPACE: "15",
Comment on lines 234 to 240
workspace_count = workspace_count_result.scalar() or 0
if workspace_count >= Workspace.MAX_WORKSPACES_PER_USER:
max_workspaces = limits_settings.max_workspaces_per_user
if max_workspaces is not None and workspace_count >= max_workspaces:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"You can create at most {Workspace.MAX_WORKSPACES_PER_USER} workspaces",
detail=f"You can create at most {max_workspaces} workspaces",
)
Comment on lines 764 to 770
environment_count = environment_count_result.scalar() or 0
if environment_count >= Workspace.MAX_ENVIRONMENTS_PER_WORKSPACE:
max_environments = limits_settings.max_environments_per_workspace
if max_environments is not None and environment_count >= max_environments:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Workspace can have at most {Workspace.MAX_ENVIRONMENTS_PER_WORKSPACE} environments",
detail=f"Workspace can have at most {max_environments} environments",
)
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