Commit Graph
15 Commits
Author SHA1 Message Date
saltbo e55dae3d2f refactor(admin): standardize management forms 2026-06-24 14:50:08 -04:00
saltbo d693837150 chore: update default branch references from master to main 2026-06-12 12:45:39 -04:00
Jasper VanandClaude Fable 5 583678967d feat: spaces, quota ownership, and sharing — design doc §5 implementation (#426)
* 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>
2026-06-12 01:12:45 -04:00
saltbo 30bc6e1a12 build: migrate project to pnpm 2026-06-01 10:44:33 -04:00
saltbo b310145752 fix(migrations): correct 0010/0011 timestamps; add CLAUDE.md rules
The manually-authored journal entries for 0010_shares and 0011_notifications
used when=1745xxxxxxxxx (April 2025), one year before the last applied
migration 0009 (when=1776200000000, March 2026). drizzle-kit migrator
orders by when, so dev databases already at 0009 silently skipped the new
migrations. CI passed because it starts from an empty DB.

- Fix the two timestamps to 1776300000000 / 1776400000000 so drizzle
  sees them as new.
- Add CLAUDE.md rules: never hand-author migrations; always add tests
  for src/lib/api.ts wrappers in the same PR.
2026-04-20 13:28:31 -04:00
saltboandClaude Opus 4.6 ecba0b5f8d docs: enforce CONTRIBUTING.md compliance and document admin test credentials
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:14:07 -04:00
saltboandClaude Opus 4.6 3b80eff413 feat: migrate from CF Pages to Workers with one-click deploy button
- Replace Pages Functions with Workers entry (`workers/bootstrap.ts`)
- Add Deploy to Cloudflare button in README
- Integrate `@cloudflare/vite-plugin` for CF dev with HMR
- Integrate `@hono/vite-dev-server` for Node dev with HMR
- `npm run dev` now defaults to CF Workers mode
- Add `run_worker_first = ["/api/*"]` so static assets stay free
- Extract shared Node bootstrap (`server/bootstrap.ts`) for reuse
- Update all docs from Pages to Workers references

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:40:15 -04:00
saltboandClaude Opus 4.6 862e6be8fc fix: search triggers on Enter key, not on every keystroke
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:39:50 -04:00
saltboandClaude Opus 4.6 67475be340 feat: replace SVAR with custom file manager, path-based navigation, sidebar folder tree
- Replace @svar-ui/react-filemanager with custom file manager built on
  @tanstack/react-table, @dnd-kit, and shadcn/ui (ContextMenu, Breadcrumb,
  Table, Checkbox, ToggleGroup, Collapsible)
- List view with sortable columns (folders-first), Grid view with card layout
- Right-click context menu, row dropdown actions, drag-and-drop file moving
- Dialogs: rename, new folder, delete confirm, move (with folder picker)
- URL-based path navigation (?path=folder/subfolder), breadcrumb from URL
- Backend: parent field stores materialized path instead of folder ID,
  cascade rename/move updates all descendants, self-move protection
- Backend: type filter API (?type=photos|videos|music|documents) for
  cross-folder file browsing by MIME type
- Sidebar: My Files with lazy-loading folder tree (auto-expands to current
  path), Photos/Videos/Music/Documents categories, Trash
- Settings moved to user avatar dropdown menu
- Migrate pnpm references to npm across docs and config
- i18n: all new keys in en.json and zh.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:26:52 -04:00
saltboandClaude Opus 4.6 310e4950b3 refactor: flatten monorepo to single-package CF Pages Functions structure
Replace pnpm workspace monorepo (packages/server, packages/web, packages/shared)
with a flat single-package layout following Hono's pages-stack pattern. Switch from
pnpm to npm and from Workers+Assets to CF Pages Functions deployment model.

- Move source: packages/server/src/ → server/, packages/web/src/ → src/, packages/shared/src/ → shared/
- Add functions/api/[[route]].ts as CF Pages Functions entry (replaces entry-cloudflare.ts)
- Update 22 import paths: server uses relative, web uses @shared/@server aliases
- Merge three package.json into one, switch to npm
- Update wrangler.toml: remove main/assets (Pages auto-detects functions/ dir)
- Add per-directory tsconfig.json for VS Code type resolution
- Simplify Dockerfile for flat layout
- Fix react-pdf CSS import path (dist/esm/ → dist/)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 00:27:38 -04:00
saltboandClaude Opus 4.6 2f7ef9f7a1 chore: strengthen infrastructure quality gates
- Pre-commit: add typecheck before lint-staged (catches type errors locally)
- Shared types: add StorageStatus constant, fix Storage.status type (string not number)
- Delete duplicate web/src/types/storage.ts, import from @zpan/shared
- Use StorageStatus.ACTIVE constant instead of magic string
- CLAUDE.md: document Hono RPC requirement, shared types rule, updated hook description

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 21:32:25 -04:00
saltboandClaude Opus 4.6 1646edc3d3 chore: add husky pre-commit hook with lint-staged
Prevents lint failures from reaching CI. Runs biome check --write on
staged files before each commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 09:19:05 -04:00
saltboandClaude Opus 4.6 175c52a548 feat: fix CF Pages deployment and update project docs
- Restructure for wrangler Workers mode (main + [assets] + run_worker_first)
- Move wrangler.toml to project root, add nodejs_compat flag
- Move migrations to root, managed by wrangler d1 migrations
- Web builds to root dist/, wrangler bundles worker entry directly
- Update CONTRIBUTING.md with full dev workflow and quality gates
- CLAUDE.md indexes docs instead of duplicating content

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 11:09:18 -04:00
saltboandClaude Opus 4.6 b817cab2c1 feat: ZPan v2.0 roadmap, architecture, and repo reset
Remove the Go v1 codebase (preserved in the v1 branch) and establish
the foundation for v2 — a complete rewrite in TypeScript (server) and
Rust (CLI/desktop). This commit includes the product roadmap (v2.0–v2.9),
technical architecture document, and updated project documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:57:15 -04:00
saltbo f43d49f45a docs: add CLAUDE.md and AGENTS.md
Signed-off-by: saltbo <saltbo@foxmail.com>
2026-01-20 22:36:43 +08:00