The admin nav hook read orgMembersAtom, which is wrapped in refreshOnWindowFocus — a browser-only atom whose signal touches window at read time. Evaluating it during SSR threw ReferenceError synchronously in render, above the routed outlet, so the whole authenticated document fell back to client rendering and the landing page was blank on first paint. Give the atom an explicit server value so its read never runs on the server; the role reads as unknown during SSR and resolves client-side, and the nav still fails closed. Org API keys could be minted and listed but never revoked. Add DELETE /account/org-api-keys/:apiKeyId with the same admin gate as the mint, resolving ownership against the org's own keys so a member's personal key or a sibling org's key cannot be destroyed through it. Self-host and cloudflare refuse it as they already refuse the mint.
Showing the changes to apps/cloud/src/api (2 of 15 files). Show all
Unified · Split
| @@ -25,6 +25,7 @@ const stubApiKeys = Layer.succeed(ApiKeyService)({ · 24 unmodified lines | ||
| 25 | 25 | revokeUserKey: () => Effect.void, |
| 26 | 26 | listOrgKeys: () => Effect.die("auth resolution test does not list org API keys"), |
| 27 | 27 | createOrgKey: () => Effect.die("auth resolution test does not create org API keys"), |
| 28 | + revokeOrgKey: () => Effect.die("auth resolution test does not revoke org API keys"), | |
| 28 | 29 | }); |
| 29 | 30 | |
| 30 | 31 | const stubWorkOS = Layer.succeed( |
| @@ -42,6 +42,7 @@ const stubApiKeys = Layer.succeed(ApiKeyService)({ · 41 unmodified lines | ||
| 42 | 42 | revokeUserKey: () => Effect.void, |
| 43 | 43 | listOrgKeys: () => Effect.die("auth resolution test does not list org API keys"), |
| 44 | 44 | createOrgKey: () => Effect.die("auth resolution test does not create org API keys"), |
| 45 | + revokeOrgKey: () => Effect.die("auth resolution test does not revoke org API keys"), | |
| 45 | 46 | }); |
| 46 | 47 | |
| 47 | 48 | const stubWorkOS = Layer.succeed( |