listProjects already returns only the projects a user has access to
based on their org/project roles. Client-side filtering was wrong.
Keep graceful degradation on listPlatforms so a flaky call can't
crash the entire org page.
Fetch all projects in one call (up to 100) before filtering, then
paginate client-side. This ensures the total count and page numbers
reflect only the projects the user can actually access, avoiding the
broken pagination that occurred when filtering server-paginated results.
Restore graceful "No apps" degradation on org overview so pagination
stays correct. Add a try/catch around project.get() in the project
layout so clicking an inaccessible project card redirects back to the
org page rather than rendering a 404 error screen.
Projects whose platform API call fails (inaccessible/deleted on backend)
are now filtered out of the org projects list instead of shown as broken
cards. Also corrects the displayed total to match the visible count.
If any project's platform API call fails (e.g. project deleted or
inaccessible), fall back to empty platforms instead of crashing the
entire org page with a 404.
- listProjects in members page load now uses .catch(() => null) so a
permissions or network error does not break the entire page
- projectAccessSelector disables "Add project" when projects list is
empty (prevents unusable required dropdown row)
- createMember resets orgProjects on modal close so subsequent opens
fetch a fresh list instead of showing a stale one
- edit modal init effect now checks supportsProjectRoles before setting
accessType to 'specific', preventing a silent role re-submission when
the org plan is downgraded below the project-roles threshold
Add support for assigning org members to specific projects with
per-project roles (owner, developer, editor, analyst) rather than
granting access to all projects in the organization.
- Add project-role helpers to billing store: isProjectSpecificRole,
parseProjectRole, buildProjectRole, getRoleLabel, projectRoles
- Pass projectId to getScopes in project layout so project-specific
members receive correct scopes inside their assigned projects
- Add owner-only guard on org settings page
- Load orgProjects alongside members in the members page load
- New projectAccessSelector component for inline project+role rows
with duplicate-project prevention
- Invite and edit modals use radio toggle (All / Specific projects)
with inline selector — gated to plans with supportsOrganizationRoles
- Members table shows per-project role badges for project-specific members
- roles.svelte accepts isProjectSpecific prop for contextual role descriptions
Extends the same fix to three non-settings flows that call functions.update
or sites.update and had the same bugs:
- functions/(modals)/createGit.svelte: enabled/logging || → ??; add deploymentRetention
- functions/domains/add-domain/+page.svelte: enabled/logging || → ??; add
providerSilentMode, providerRootDirectory, buildSpecification, and deploymentRetention
which were missing entirely from this connect() call
- sites/deployments/createGitDeploymentModal.svelte: enabled/logging/
providerSilentMode || → ??; add deploymentRetention
Extends the fix from #3064 to the remaining 20 settings update components
for both functions and sites. Two bugs were present in every file not
touched by that PR:
1. `enabled`, `logging`, and `providerSilentMode` were passed through
`|| undefined` instead of `?? undefined`, causing `false` values to
be silently coerced to `undefined` and reset to their API defaults
whenever any other setting was saved.
2. `deploymentRetention` was absent from every partial-update payload,
so saving name, timeout, scopes, schedule, runtime, permissions,
resource limits, build command, events, build triggers, or repository
settings would silently reset the retention value.
Also fixes `providerSilentMode: silentMode || undefined` in sites/
updateRepository.svelte to `silentMode` (matching the functions version),
so disabling silent mode is correctly preserved on save.
Bumps @appwrite.io/console SDK to 35c3dea which introduces the Organization
class. All projects.list/create/update calls are now routed through
sdk.forConsole.organization(orgId) so requests carry the
X-Appwrite-Organization header required by the new API contract.
The plan summary table used a hardcoded `addon_<key> -> label` lookup
to render addon line items, with a fallback that called every unknown
addon an "overage". Switch to reading `addon.name` from the API
response, which the aggregation endpoint now populates from the addon
catalog.
The hardcoded map stays as a fallback for older cloud builds that
don't yet send `addon.name`, and a plain resourceId is the final
fallback in place of the misleading "overage (N)" string.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The cloud backend (already merged) now cancels pending/failed invoices on
organization delete instead of throwing BILLING_INVOICE_PENDING. The
console was still gating the delete modal via the unpaid-invoices branch
of the delete-estimation endpoint, which rendered an alternate view
without the org-name confirmation input and left the Delete button
permanently disabled.
Drop the estimation-based gate (and the now-unused estimation fetch,
component, and import) so the confirm-name form always renders. The
backend will cancel any failed invoices server-side as part of the
delete. The informational upcoming-invoice Alert is preserved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>