mirror of
https://github.com/saltbo/zpan.git
synced 2026-09-19 01:51:11 +08:00
* docs: add spaces/quota/sharing design decisions Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(store): require team owner role for billing and purchase endpoints Team orgs now gate checkout, billing portal, credits (balance/ledger/ redemptions), and order management behind the owner role. Personal orgs are unaffected. Implements docs/design/spaces-quota-sharing.md §2.1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(store): clarify purchase target and gate billing UI to owners The store page now states which space purchases fund, hides purchase and billing surfaces from non-owner team members with guidance to contact the owner, and labels team orders with the team name on the cloud side. Implements docs/design/spaces-quota-sharing.md §2.1.2-3. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(objects): cross-space copy/move with file manager entry Adds POST /api/objects/:id/transfers (copy or move a file/folder into another space) reusing the save-to-drive copy engine; move = copy + trash source, and the source survives any partial copy. The file manager gains a 'Copy/Move to space' action with a space/folder picker. Also fixes a privilege hole: save-to-drive (and the new transfer endpoint) previously accepted any personal org as a write target, allowing writes into other users' personal spaces; targets are now restricted to orgs with editor access or the caller's own personal org. The transfer folder picker also fixes the save-to-drive dialog listing the active org's folders instead of the selected target's. Implements docs/design/spaces-quota-sharing.md §3. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(admin): per-team quota management and default team quota Admins can now grant, edit, and revoke storage entitlements for any space (team or personal) via /api/admin/quotas/:orgId/entitlements and a new admin Quotas page. New teams take their initial quota from the default_team_quota system option (falling back to default_org_quota), configurable in admin settings. Completes the v2.2 roadmap item 'Per-team storage quota set by admin'; implements design doc §2.3. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(quotas): allocate purchased storage packs between owned spaces Space owners can move whole one-time purchased packs (cloud_order grants) between spaces they own via POST /api/quotas/me/entitlements/:id/transfers. Plans and admin grants are not transferable, and a transfer is blocked when the source space's usage would exceed its remaining quota. The storage page lists the current space's packs with a move dialog. Implements design doc §2.2. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(shares): received shares inbox on the shares page GET /api/shares?box=received lists active shares addressed to the current user (matched by user id or the email the share targeted), with the sharer's name. The shares page gains a sent/received toggle; received items open the share landing page. This is an inbox of share links, not a mounted filesystem (design doc §4.4). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(hooks): cover default team quota in site options hook Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(store,admin): drop purchase-target banner; scope admin quotas page to teams The storage page no longer shows the 'purchases fund X space' line — owners see the store normally and non-owner members keep the guidance notice. The admin Quotas page now lists team spaces only; personal quotas stay on the user detail page, removing the overlapping entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * revert(quotas): remove storage pack allocation Allocation (§5.5) operated on an empty set: the store only sells per-workspace subscriptions, and the original design restricted moves to one-time cloud packs, which don't exist in the catalog. Subscriptions can't be safely allocated either — the webhook cancellation/downgrade path matches on the original targetOrgId, so a moved entitlement's claw-back silently fails and leaves ghost capacity. The feature is also redundant: family owners subscribe the team space directly (§2.1) and self-hosted admins grant capacity straight to it (§2.3). Removes the quota-allocation service, /api/quotas/me/entitlements endpoints, the storage-page packs panel, isOrgOwner helper, and related tests/i18n. Design doc §2.2 updated to record why it was deferred and the prerequisite (a one-time pack SKU) for revisiting. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(admin): replace quotas page with Teams management (list + detail) Promotes the admin quota surface to a proper Teams section, sibling to Users: a team list page where each row opens a team detail page, and the detail page manages quota entitlements (grant/edit/revoke) — mirroring the user detail page. All backed by org data. - New /api/admin/teams (list + detail) with member count, owner, and effective storage usage; teams identified by non-personal slug so legacy teams with null metadata are included. - New /admin/teams list + /admin/teams/$orgId detail routes; the old /admin/quotas page is removed and the nav item becomes 'Teams'. - Entitlement CRUD continues to reuse the org-generic /api/admin/quotas/:orgId/entitlements endpoints (invisible to users). - Personal-space quotas remain on the user detail page. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(admin): use a distinct icon for the Teams nav item Users and Teams both used people icons (Users / UsersRound) and were hard to tell apart in the sidebar. Teams now uses Building2 (org). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(admin): chunk team member/owner IN-lists under D1's param cap listTeams bound all team orgIds into single member-count and owner-name queries; on D1 (100 bound-param cap) that breaks past ~100 teams. getEffectiveQuotasByOrg already chunks at 90 — match it for the two new queries. Members of a given org all land in one chunk, so per-org owner ordering is preserved. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>