Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions src/components/ClinicalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { DocumentManagementActions, type DocumentDeleteResult } from "@/componen
import { documentCitationHref, formatCompactCitationLabel, formatCitationLabel } from "@/lib/citations";
import { extractSafetyFindings, formatSafetyFindingLabel } from "@/lib/clinical-safety";
import { clearCachedSignedUrl, getCachedSignedUrl, setCachedSignedUrl } from "@/lib/signed-url-cache";
import { readLocalProjectIdentity, unsafeLocalProjectMessage } from "@/lib/local-project-identity";
import { isLocalNoAuthMode } from "@/lib/env";
import {
appBackdrop,
Expand Down Expand Up @@ -179,14 +180,6 @@ type SetupStatusPayload = {
indexingActive?: boolean;
pollAfterMs?: number | null;
};
type LocalProjectIdentityPayload = {
localServer?: {
currentUrl?: string | null;
projectPortStart?: number;
projectPortEnd?: number;
safeLocalOrigin?: boolean;
};
};
type DocumentsPayload = {
documents?: ClinicalDocument[];
pagination?: DocumentPagination | null;
Expand Down Expand Up @@ -225,21 +218,6 @@ type SearchResultModePayload =
payload: AnswerPayload;
};

async function readLocalProjectIdentity() {
const response = await fetch("/api/local-project-id", { cache: "no-store" });
if (!response.ok) return null;
return (await response.json()) as LocalProjectIdentityPayload;
}

function unsafeLocalProjectMessage(identity: LocalProjectIdentityPayload | null) {
const range =
typeof identity?.localServer?.projectPortStart === "number" &&
typeof identity.localServer.projectPortEnd === "number"
? ` Use the URL printed by npm run ensure; managed ports are ${identity.localServer.projectPortStart}-${identity.localServer.projectPortEnd}.`
: " Use the URL printed by npm run ensure.";
return `This tab is not using the guarded Clinical KB local URL.${range}`;
}

function parseSseData(lines: string[]) {
const data = lines.join("\n").trim();
if (!data) return null;
Expand Down Expand Up @@ -4093,7 +4071,7 @@ export function ClinicalDashboard() {
key={`${section.heading}:${section.citation_chunk_ids.join(",")}:${section.body.slice(0, 24)}`}
className={cn(panelSubtle, "space-y-3 p-4")}
>
<div className="rounded-lg border border-[color:var(--accent)]/20 bg-[color:var(--surface)] p-3">
<div className="rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] p-3">
<div className="flex items-start gap-2">
<span className="mt-0.5 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[color:var(--primary-soft)] text-[color:var(--primary)]">
<ListChecks className="h-4 w-4" />
Expand Down
24 changes: 1 addition & 23 deletions src/components/DocumentViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
toolbarButton,
} from "@/components/ui-primitives";
import { clearCachedSignedUrl, getCachedSignedUrl, setCachedSignedUrl } from "@/lib/signed-url-cache";
import { readLocalProjectIdentity, unsafeLocalProjectMessage } from "@/lib/local-project-identity";
import { formatClinicalDate, normalizeSourceMetadata, sourceStatusLabel } from "@/lib/source-metadata";
import { isLocalNoAuthMode } from "@/lib/env";
import { useAuthSession } from "@/lib/supabase/client";
Expand All @@ -68,29 +69,6 @@ type PageRow = {
ocr_used: boolean;
};

type LocalProjectIdentityPayload = {
localServer?: {
projectPortStart?: number;
projectPortEnd?: number;
safeLocalOrigin?: boolean;
};
};

async function readLocalProjectIdentity() {
const response = await fetch("/api/local-project-id", { cache: "no-store" });
if (!response.ok) return null;
return (await response.json()) as LocalProjectIdentityPayload;
}

function unsafeLocalProjectMessage(identity: LocalProjectIdentityPayload | null) {
const range =
typeof identity?.localServer?.projectPortStart === "number" &&
typeof identity.localServer.projectPortEnd === "number"
? ` Use the URL printed by npm run ensure; managed ports are ${identity.localServer.projectPortStart}-${identity.localServer.projectPortEnd}.`
: " Use the URL printed by npm run ensure.";
return `This tab is not using the guarded Clinical KB local URL.${range}`;
}

type ImageRow = {
id: string;
page_number: number | null;
Expand Down
17 changes: 1 addition & 16 deletions src/lib/local-project-guard.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
import { NextResponse } from "next/server";
import type { LocalProjectIdentityPayload } from "@/lib/local-project-identity";
import { appName, localProjectId, projectPortEnd, projectPortStart } from "../../scripts/local-server-utils.mjs";

const localHosts = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);

export type LocalProjectIdentityPayload = {
appName: string;
projectId: string;
identityPath: "/api/local-project-id";
localServer: {
currentUrl: string | null;
currentPort: number | null;
projectPortStart: number;
projectPortEnd: number;
safeLocalOrigin: boolean;
requestOrigin: string | null;
requestReferer: string | null;
unsafeLocalCaller: string | null;
};
};

function portFor(url: URL) {
const explicit = Number.parseInt(url.port, 10);
if (Number.isInteger(explicit)) return explicit;
Expand Down
30 changes: 30 additions & 0 deletions src/lib/local-project-identity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export type LocalProjectIdentityPayload = {
appName: string;
projectId: string;
identityPath: "/api/local-project-id";
localServer: {
currentUrl: string | null;
currentPort: number | null;
projectPortStart: number;
projectPortEnd: number;
safeLocalOrigin: boolean;
requestOrigin: string | null;
requestReferer: string | null;
unsafeLocalCaller: string | null;
};
};

export async function readLocalProjectIdentity() {
const response = await fetch("/api/local-project-id", { cache: "no-store" });
if (!response.ok) return null;
return (await response.json()) as LocalProjectIdentityPayload;
}

export function unsafeLocalProjectMessage(identity: LocalProjectIdentityPayload | null) {
const range =
typeof identity?.localServer?.projectPortStart === "number" &&
typeof identity.localServer.projectPortEnd === "number"
? ` Use the URL printed by npm run ensure; managed ports are ${identity.localServer.projectPortStart}-${identity.localServer.projectPortEnd}.`
: " Use the URL printed by npm run ensure.";
return `This tab is not using the guarded Clinical KB local URL.${range}`;
}