Skip to content

feat: session-authenticated /me usage surface + account Usage panel#108

Merged
Zach Dunn (zachdunn) merged 2 commits into
mainfrom
claude/me-usage-surface
Jul 13, 2026
Merged

feat: session-authenticated /me usage surface + account Usage panel#108
Zach Dunn (zachdunn) merged 2 commits into
mainfrom
claude/me-usage-surface

Conversation

@zachdunn

@zachdunn Zach Dunn (zachdunn) commented Jul 12, 2026

Copy link
Copy Markdown
Member

Closes #107.

Summary

  • apps/api: new src/routes/me.ts — session-cookie-authenticated GET /me/workspaces and GET /me/workspaces/:name/usage, gated by sessionAuth, requireSessionUser (not requireAdminUser). Memberships resolve via the AUTH service binding's /internal/memberships, mapped to workspace names with workspacesForOrg. Usage reuses getWorkspaceUsage + usageWithLimits, same shape as GET /v1/:ws/usage. A workspace the caller isn't a member of 404s (workspace_not_found) — that membership check is the authorization boundary.
  • apps/api: extracted loadWorkspaceRecord out of workspace.ts's workspaceAuthWith so /me/workspaces/:name/usage reuses the same KV read instead of duplicating it.
  • apps/api: wired /me into src/index.ts behind the existing adminUiCors policy (same origins, credentials: true, GET+OPTIONS) — CORS isn't the security boundary, the session check is.
  • apps/api tests: src/routes/me.test.ts, mirroring admin-ui.test.ts's stub-AUTH pattern plus the UsageFakeD1 harness — 401 with no session, membership-to-workspace mapping, 404 for a non-member workspace, and the usage+limits shape for a member.
  • apps/web: new src/lib/api-client.ts with getMyWorkspaces / getMyWorkspaceUsage, credentials: "include", defensive []/null on failure (same convention as auth-client.ts).
  • apps/web: account.astro now passes UPLOADS_API_ORIGIN through like admin.astro, adds it to the CSP connect-src, and the Workspaces panel now sources from /me/workspaces (shows role) instead of listOrganizations(), with per-workspace usage (bytes used vs. limit, object count) fetched and rendered underneath each row.

Non-goals (per the issue)

No file listing, no token UI, no write operations over the session surface.

Test plan

  • pnpm test in apps/api (189 tests) and apps/web (17 tests) — all pass
  • pnpm run typecheck in both apps under Node 24 — no new errors (the 2 pre-existing admin.astro errors are untouched and not from this PR)
  • Manual browser check of /account signed-in (not run in this session — no live session cookie in the sandbox)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a signed-in account view showing the workspaces available to you.
    • Added per-workspace storage usage, limits, remaining capacity, and usage-period details.
    • Added session-authenticated workspace and usage API access.
  • Bug Fixes

    • Workspace access and usage requests now consistently enforce authentication and membership permissions.
    • Improved handling of unavailable or malformed workspace data with safe fallback states.

…107)

Adds a read-only, session-cookie-gated /me/* surface on apps/api
(GET /me/workspaces, GET /me/workspaces/:name/usage) so any signed-in
user can see their own workspace memberships and usage, not just
admins. Membership lookup via the AUTH service binding is the
authorization check — non-member workspaces 404.

Wires the account.astro Workspaces panel to consume it instead of
listOrganizations(), showing role and per-workspace bytes/object usage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (2)
  • coderabbit:review
  • review
🚫 Excluded labels (none allowed) (1)
  • wip

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ad16b086-0a3b-4c56-bee9-816033eb3e11

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The API now exposes session-authenticated workspace membership and usage endpoints. The web account page uses these endpoints to display workspaces and usage details, while workspace record lookup is centralized and covered by route tests.

Changes

Workspace access flow

Layer / File(s) Summary
Workspace record loading
apps/api/src/workspace.ts
Workspace validation and registry lookup are centralized in loadWorkspaceRecord, which workspaceAuthWith now uses.
Authenticated workspace API
apps/api/src/routes/me.ts, apps/api/src/routes/me.test.ts
Adds session-authenticated workspace listing and usage endpoints, with coverage for authentication, memberships, missing workspaces, usage, and limits.
API route and CORS wiring
apps/api/src/index.ts
Mounts /me and applies credentialed CORS handling to /me/*.
Account workspace display
apps/web/src/lib/api-client.ts, apps/web/src/pages/account.astro
Adds session-cookie API clients and renders workspace usage with loading, formatting, and unavailable states.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Possibly related PRs

  • buildinternet/uploads#20 — Refactors workspaceAuthWith in the same module, related to this PR’s workspace record-loading extraction.

Suggested labels: coderabbit:review

Poem

A bunny found workspaces hopping in line,
With usage and limits displayed just fine.
Cookies carry the session bright,
API paths now guide the flight,
And every workspace gets a little green light.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: a session-authenticated /me API surface and the account Usage panel.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/me-usage-surface

Comment @coderabbitai help to get the list of available commands.

@zachdunn

Copy link
Copy Markdown
Member Author

CodeRabbit (@coderabbitai) review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 12, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
uploads-api a2adfd5 Commit Preview URL

Branch Preview URL
Jul 13 2026, 12:07 AM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 12, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
uploads-web a2adfd5 Commit Preview URL

Branch Preview URL
Jul 13 2026, 12:07 AM

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

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/src/routes/me.ts`:
- Around line 98-99: Update the usage-read flow around getWorkspaceUsage in the
route handler to obtain the storage abstraction through createStorage() from
packages/storage, then invoke the usage query through that returned object
instead of passing c.env.DB directly. Preserve the existing usageWithLimits
response behavior.
- Around line 83-84: Normalize the workspace name from c.req.param("name") at
the start of the "/workspaces/:name/usage" handler before authorization or any
other logic. Use the normalized value for all downstream membership checks and
workspace operations, preserving the existing handler behavior otherwise.
- Around line 38-40: Update the membership-fetching flow in the `/workspaces`
route to throw an appropriate 5xx AppError from `@uploads/errors` when the AUTH
request fails, returns a non-2xx response, or provides a malformed body; do not
convert these cases to an empty memberships array. Preserve the valid
Membership[] path, and let respondError serialize the thrown error so binding
failures and usage requests receive the correct failure status.

In `@apps/api/src/workspace.ts`:
- Around line 122-127: Move the workspace registry lookup out of
loadWorkspaceRecord and expose an equivalent workspace-record read through the
storage API in createStorage(). Update loadWorkspaceRecord to obtain the storage
abstraction and call that method, preserving the existing name validation, key,
JSON type, and cache TTL while removing direct env.REGISTRY access.

In `@apps/web/src/lib/api-client.ts`:
- Around line 27-28: Update the response parsing in the workspace and usage API
client methods to validate each entry’s required workspace and organization
fields, and validate that usage fields are numeric before returning them. Reject
malformed payloads and preserve the documented [] workspace fallback and null
usage fallback instead of passing invalid objects through.

In `@apps/web/src/pages/account.astro`:
- Around line 251-262: Update formatUsage to include the upload-period quota
using uploadsInPeriod, maxUploadsPerPeriod, uploadsRemaining, and periodStart,
alongside the existing storage and object metrics. Preserve the current
formatting for storage and object counts while rendering the API’s upload usage
and limit information.
- Around line 302-312: Update the workspace usage update flow around
getMyWorkspaceUsage so all workspace requests start concurrently after the list
renders, rather than awaiting each request sequentially inside the loop.
Preserve each workspace’s existing usage element lookup and text formatting, and
ensure one request’s delay or failure does not block updates for other
workspaces.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2372171e-fc15-49a7-a8df-857f4dfd16ff

📥 Commits

Reviewing files that changed from the base of the PR and between 20ee136 and 8111930.

📒 Files selected for processing (6)
  • apps/api/src/index.ts
  • apps/api/src/routes/me.test.ts
  • apps/api/src/routes/me.ts
  • apps/api/src/workspace.ts
  • apps/web/src/lib/api-client.ts
  • apps/web/src/pages/account.astro

Comment thread apps/api/src/routes/me.ts Outdated
Comment thread apps/api/src/routes/me.ts
Comment thread apps/api/src/routes/me.ts
Comment thread apps/api/src/workspace.ts
Comment thread apps/web/src/lib/api-client.ts Outdated
Comment thread apps/web/src/pages/account.astro
Comment thread apps/web/src/pages/account.astro Outdated
- /me memberships lookup now throws ServiceUnavailableError
  (auth_lookup_failed) on a non-ok or malformed AUTH response instead of
  reporting an outage as zero memberships; test added.
- api-client validates workspace entries and numeric usage fields before
  returning them; malformed payloads fall back to []/null.
- account page shows the monthly upload quota when a workspace has one.
- per-workspace usage fetches now run concurrently via Promise.all.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

Session-authenticated usage surface (/me/*) + Usage panel on /account

1 participant