Skip to content

feat(platform): settings permissions, admin, billing attribution/concurrency lims - #5545

Merged
icecrasher321 merged 16 commits into
stagingfrom
fix/invite-bug
Jul 13, 2026
Merged

icecrasher321 merged 16 commits into
stagingfrom
fix/invite-bug

Conversation

@icecrasher321

@icecrasher321 icecrasher321 commented Jul 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Split account, organization, and workspace settings (did not change UI organization for now)
  • Fixed workspace-scoped billing and entitlements.
  • Hardened invites, memberships, and external access.
  • Added durable storage and execution accounting.
  • Introduced backward-compatible Copilot billing attribution.

Type of Change

  • Bug fix

Testing

N/A

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Keep organization activation server-owned so failed membership checks cannot clear a valid session context.
@vercel

vercel Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 13, 2026 7:48am

Request Review

@cursor

cursor Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

PR Summary

High Risk
Changes payment routing, admission, and settlement across copilot validate/update-cost, unified billing, and execution paths—incorrect attribution or org gates could mis-bill or block usage; large surface area with extensive tests but production billing impact is critical.

Overview
Introduces account settings as a first-class route (/account/settings with shell, section pages, and personal credit usage) and tightens who can see or change billing: unified GET /api/billing separates personal vs organization payers, requires org admin for team billing, exposes subscription state (active/free/lapsed), payer block flags, and upgrade workspace hints; plan switches can be scoped to a workspace payer with billing-admin checks.

Copilot and hosted usage move to versioned billing protocols on validate/update-cost (legacy markerless Go, explicit legacy-v0, attribution-v1, direct-v1), routing charges to the workspace organization payer with member-cap checks, immutable attribution envelopes where required, payer-level overage settlement, and retryable 503s on threshold failures. Chat, guardrails, and execution paths pass billing attribution and avoid charging on preprocess/upload failures (skipCost). The standalone member-credits API is removed in favor of attributed limits.

Session and org context: upgrade recovery only auto-sets active org when there is exactly one membership; intentional “no active organization” and external-only users are not forced into an org. Audit log list/export validate access against organizationId in the query. Storage quotas use workspace billing context; mothership chat attachments stay quota-exempt. Invitations accept forwards actor/provenance into core acceptance (audit handling adjusted). Docs and resume UI copy reflect workspace payer billing, org billing authority, and automatic resume waiting reasons.

Reviewed by Cursor Bugbot for commit e598c51. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR keeps invite acceptance from changing the active organization on the client. The main changes are:

  • Removed the client-side organization.setActive call after invite acceptance.
  • Left query invalidation and redirect handling in the invite accept flow.
  • Added a jsdom regression test for external workspace invites.

Confidence Score: 4/5

The changed flow looks mergeable after checking the external workspace redirect context.

  • Server-owned activation still covers organization-joining invite paths.
  • External workspace invites now preserve the previous active organization.
  • The redirect can still depend on workspace pages not using stale session organization state.

apps/sim/app/invite/[id]/invite.tsx

Important Files Changed

Filename Overview
apps/sim/app/invite/[id]/invite.tsx Removes client-owned organization activation after accepting an invite.
apps/sim/app/invite/[id]/invite.test.tsx Adds a regression test that asserts external workspace invites do not call client-side organization activation.

Reviews (1): Last reviewed commit: "fix(invites): preserve active organizati..." | Re-trigger Greptile

Comment thread apps/sim/app/invite/[id]/invite.tsx
Remove locally generated migrations so they can be regenerated against the latest staging schema without preserving stale snapshots or numbering.
Resolve storage, webhook, Jupyter, workspace-layout, and API-validation conflicts while preserving both staging updates and billing durability changes.
Remove this branch's generated migrations so they can be regenerated against the latest staging schema with fresh numbering.
Resolve mothership executor, upload-test mocks, and regenerate tool schemas from the copilot staging catalog.
@icecrasher321 icecrasher321 changed the title fix(invites): preserve active organization for external access feat(platform): settings permissions, admin, billing attribution Jul 11, 2026
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

@greptile

@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

@greptile-apps

greptile-apps Bot commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor

Too many files changed for review. (522 files found, 500 file limit)

Comment thread apps/sim/app/api/chat/[identifier]/route.ts
Comment thread apps/sim/app/api/billing/switch-plan/route.ts Outdated
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

@greptile

@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

Comment thread apps/sim/app/api/billing/update-cost/route.ts
Comment thread apps/sim/lib/billing/core/billing.ts
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

Comment thread apps/sim/app/account/settings/billing/credit-usage/page.tsx
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

Comment thread apps/sim/app/api/billing/update-cost/route.ts
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

Comment thread apps/sim/app/api/guardrails/validate/route.ts Outdated
Comment thread apps/sim/app/api/files/multipart/route.ts
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

@cursor cursor 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e598c51. Configure here.

@icecrasher321
icecrasher321 merged commit ef7c8e2 into staging Jul 13, 2026
17 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/invite-bug branch July 13, 2026 16:51
@icecrasher321 icecrasher321 changed the title feat(platform): settings permissions, admin, billing attribution feat(platform): settings permissions, admin, billing attribution/concurrency lims Jul 13, 2026
waleedlatif1 added a commit that referenced this pull request Sep 22, 2026
…gainst other files (#8129)

* fix(files): stop promising immutable caching for documents compiled against other files

A versioned serve URL (`?v=<updatedAt>`) was always answered with a one-year
`immutable` Cache-Control. That holds for a stored source — a content write
rotates the storage key, so a given key's bytes never change — but not for a
response the route resolves against OTHER files: a document compiled against the
files it references, or a sim page inlining its images, recompiles on every
request. Those bytes change when a referenced file changes, while this file's key
and `updatedAt` stay put, so the whole URL is unchanged and the browser served a
stale render from cache until the document itself was edited.

The resolver now reports when it read referenced content, and the route withholds
the immutable lifetime for exactly those responses, keeping it for stored sources
and self-contained artifacts.

Also corrects three comments that claimed generated docs are edited in place under
the same storage key. That stopped being true in #5545 (2026-07-13), which made
every content write allocate a new key; the caching rule above was reasoned from
the stale claim.

* improvement(files): make serve cacheability a declared, required property

An optional boolean let a branch added to the resolver inherit the cacheable
default by saying nothing — the exact failure this change exists to prevent.
Cacheability is now a required field every branch must declare, so forgetting it
fails the build rather than silently promising a year of immutability.

* improvement(files): answer a file revalidation with 304 instead of the whole body

A response the browser is told to revalidate carried no validator, so every check
re-sent the entire file. That is the cost a document compiled against other files
now pays on each window focus: it cannot be given a cache lifetime, because its
bytes really may have changed, so the only way to make the check cheap is to let
the client prove what it already holds.

Authorized serves now carry an ETag — the digest of the bytes about to be sent,
which is exact by construction however those bytes were produced — and answer 304
to a matching If-None-Match. Matching is weak, per RFC 9110, so a cache that
stored a weak validator still revalidates.

Kept out of createFileResponse deliberately: digesting costs a pass over the
buffer, up to the 100MB transfer ceiling, and a response served as immutable is
never revalidated, so it would pay that pass and never collect. Public assets and
the assistant-image path are unchanged.

* fix(files): report a reference dependency from the isolated-VM compile path

The isolated-VM fallback returns before the static reference scan, so a document
it compiled never reported one — yet that path reads workspace files live through
its broker, which is what `onWorkspaceFileAccess` records. A versioned request for
such a document therefore still took a one-year immutable lifetime, and changing a
referenced file left the browser serving a stale render.

Fixed at the root rather than in that one branch: the flag is now required on
CompiledDocResult, so every compile path must declare it and a new one cannot
inherit a cacheable-forever answer by staying silent. Each site reports the union
of what the source references statically and what the compile actually touched —
neither alone is sufficient, since a failed read records no access and the broker
reaches files the static scan cannot see.

Making it required immediately surfaced a second case: the process-local compile
cache is shared with compiles that carried a workspace, so a cached entry can hold
contributor identities even when the reading call passes none. That branch now
reads the cached identities instead of assuming independence.

* improvement(files): compute a validator only where a response can be revalidated

Both reviewers caught the same contradiction: the digest was documented as worth
paying only where a 304 can be collected, then applied to every authorized serve
including immutable ones, which are never revalidated. One place now decides, so
an immutable response takes the plain path and spends no pass over its buffer.

Also drops a redundant translation. The resolver was converting the compiler's
boolean into a string union and the cache rule was converting it straight back;
the producer's own required boolean now travels end to end, which is one fact in
one shape and keeps the same build-time guarantee that a new branch must declare it.

This branch was previously deployed

1 inactive deployment
Preview — e598c51f Deployed Jul 13, 2026 by vercel[bot]
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.

1 participant