mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-26 20:45:37 +02:00
PR #1868 conflated "has workspace" with "completed onboarding" — restore `onboarded_at` as the single signal, and route invited users through a dedicated /invitations page before they ever see onboarding. - Backend: CreateWorkspace + AcceptInvitation atomically set onboarded_at alongside the member insert, establishing the invariant "member row exists ↔ onboarded_at != null" at the DB layer. - Migration 065: one-shot backfill closes the dirty rows produced by PR #1868 (users with a workspace but onboarded_at == null). - Entry points (web callback, login, desktop App): if onboarded_at is null, look up pending invitations by email and route to the new batch /invitations page; otherwise the resolver picks workspace / new-workspace as before. - OnboardingPage: stops bouncing on hasWorkspaces; only hasOnboarded bounces. Unblocks the user from completing Step 3 (workspace creation) → Steps 4 / 5. - StarterContentPrompt: only shows when the user is the solo member of the workspace, so invited users never get prompted to import starter content into someone else's workspace. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { Workspace } from "../types";
|
|
import { paths } from "./paths";
|
|
import { resolvePostAuthDestination } from "./resolve";
|
|
|
|
function makeWs(slug: string): Workspace {
|
|
return {
|
|
id: `id-${slug}`,
|
|
name: slug,
|
|
slug,
|
|
description: null,
|
|
context: null,
|
|
settings: {},
|
|
repos: [],
|
|
issue_prefix: slug.toUpperCase(),
|
|
created_at: "",
|
|
updated_at: "",
|
|
};
|
|
}
|
|
|
|
describe("resolvePostAuthDestination", () => {
|
|
it("!onboarded → /onboarding regardless of workspace count", () => {
|
|
// Un-onboarded users are routed back to the onboarding flow. The
|
|
// "un-onboarded but in workspace" state is now physically impossible
|
|
// (backend invariant + migration 065 backfill), but the resolver still
|
|
// does the right thing if it ever appears: send the user to onboarding
|
|
// rather than dropping them into a workspace with `onboarded_at` null.
|
|
expect(resolvePostAuthDestination([], false)).toBe(paths.onboarding());
|
|
expect(resolvePostAuthDestination([makeWs("acme")], false)).toBe(
|
|
paths.onboarding(),
|
|
);
|
|
});
|
|
|
|
it("onboarded + has workspace → /<first.slug>/issues", () => {
|
|
const ws = [makeWs("acme"), makeWs("beta")];
|
|
expect(resolvePostAuthDestination(ws, true)).toBe(
|
|
paths.workspace("acme").issues(),
|
|
);
|
|
});
|
|
|
|
it("onboarded + zero workspaces → /workspaces/new", () => {
|
|
expect(resolvePostAuthDestination([], true)).toBe(paths.newWorkspace());
|
|
});
|
|
});
|