Files
zooqueen 75bbc36d38 fix(rpc): carry the team on every call; read the wordmark from env
Team scope never reached the server. mint() takes it from an `x-team-id`
header on the WebSocket handshake, but a browser cannot set headers on a
WebSocket, so every session ran at teamId -1 and the team-scoped reads
answered "Team not found". The envelope already has a teamId field: the
app declares the team once, where it knows it, and every call carries it.
Handlers still resolve the team through the caller's membership, so this
selects a scope rather than granting one.

Branding: the wordmark comes from NEXT_PUBLIC_APP_NAME at runtime instead
of being drawn into the logo, so a tenant rebrands by setting env. The
mark's geometry now has one home that the icon, the wordmark and the
signin lockup all draw from.

The rate-limit sweep deletes by rowid, SQLite's row identity.
2026-08-13 23:13:08 -07:00

37 lines
1.0 KiB
TypeScript

import { createContext, useContext } from 'react';
import React from 'react';
import type { TeamSession } from '@hanzo/esign-trpc/server/organisation-router/get-organisation-session.types';
import { setZapTeam } from '@hanzo/esign-trpc/zap/client';
type TeamProviderValue = TeamSession;
interface TeamProviderProps {
children: React.ReactNode;
team: TeamProviderValue | null;
}
const TeamContext = createContext<TeamProviderValue | null>(null);
export const useCurrentTeam = () => {
const context = useContext(TeamContext);
if (!context) {
throw new Error('useCurrentTeam must be used within a TeamProvider');
}
return context;
};
export const useOptionalCurrentTeam = () => {
return useContext(TeamContext);
};
export const TeamProvider = ({ children, team }: TeamProviderProps) => {
// Scope RPC to the same team the tree below is about. Set while rendering, so
// it is in place before any descendant issues its first call.
setZapTeam(team?.id ?? null);
return <TeamContext.Provider value={team}>{children}</TeamContext.Provider>;
};