export interface FederatedBot { larkAppId: string; botName: string; cliId: string; /** Whether this bot has real Feishu transport. A core-only (apiOnly) bot is * `false` — it has no Feishu identity, so it can be neither a group creator * nor an invited member cross-deployment. Explicitly true/false on new * versions; ABSENT means a pre-capability spoke → treated as legacy normal * (true) for backward compatibility. */ larkTransportEnabled?: boolean; /** Tenant-stable bot id (used by P2 拉群 to add the bot cross-app). */ botUnionId?: string; capability?: string | null; hasTeamRole?: boolean; /** Owner (the person) of this bot, tenant-stable union_id — so 拉群 can pull * the owner into the group by union_id (open_id is app-scoped, union_id not). */ ownerUnionId?: string; ownerName?: string; } export interface FederatedDeployment { deploymentId: string; name: string; syncToken: string; bots: FederatedBot[]; joinedAt: number; lastSeenAt: number; /** The spoke deployment's OWNER (the person), tenant-stable union_id. Hub uses * this — derived from syncToken — as the trusted operator identity when this * spoke initiates 拉群 (so the operator is pulled into the group). */ ownerUnionId?: string; ownerName?: string; /** Spoke's dashboard base URL — so this hub can call back to delegate 拉群 * (hub→spoke) when no local online bot can be the group creator. */ callbackUrl?: string; /** Token the SPOKE issued to THIS hub at join; the hub presents it on * delegate calls so the spoke can verify the request is from its hub. */ delegationToken?: string; } export interface RegisterInput { deploymentId: string; name: string; bots: FederatedBot[]; ownerUnionId?: string; ownerName?: string; callbackUrl?: string; delegationToken?: string; } /** * Register a NEW remote deployment under a team and issue a fresh syncToken. * * NOT idempotent on purpose: `deploymentId` is public (it appears in the roster), * so re-registering an existing id must NOT hand back its long-lived syncToken — * otherwise anyone with an invite could claim another deployment's token by * guessing its id. A duplicate returns `{ created: false }` with NO token; the * caller surfaces `deployment_already_joined`. Ongoing bot refresh is via * `syncDeployment` (syncToken), not this. Re-binding/rotation is a future * explicit reset proving the old syncToken. */ export declare function registerDeployment(dataDir: string, teamId: string, input: RegisterInput, now?: number): { syncToken: string; created: boolean; }; /** Resolve a syncToken to its {teamId, deployment}, or null. */ export declare function getDeploymentByToken(dataDir: string, syncToken: string): { teamId: string; deployment: FederatedDeployment; } | null; /** Refresh a deployment's advertised bots + heartbeat, by syncToken. Returns true if found. */ export declare function syncDeployment(dataDir: string, syncToken: string, bots: FederatedBot[], owner?: { ownerUnionId?: string; ownerName?: string; name?: string; }, now?: number): boolean; /** Member deployments of a team (empty if none). */ export declare function listFederatedDeployments(dataDir: string, teamId: string): FederatedDeployment[]; /** Member deployments across ALL hosted teams, each tagged with its teamId. */ export declare function listAllFederatedDeployments(dataDir: string): Array<{ teamId: string; deployment: FederatedDeployment; }>; /** Remove a deployment from a team (leave/kick). Returns true if removed. */ export declare function removeDeployment(dataDir: string, teamId: string, deploymentId: string): boolean; /** Remove the deployment owning a syncToken (spoke-initiated leave/revoke). Returns true if removed. */ export declare function removeDeploymentByToken(dataDir: string, syncToken: string): boolean; /** Drop all federation records for a team (e.g. when the team is deleted). */ export declare function removeTeamFederation(dataDir: string, teamId: string): void; //# sourceMappingURL=federation-store.d.ts.map