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
7 changes: 5 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_your_key

# apps/web: canonical site URL for SEO (metadataBase, sitemap, Open Graph). Production: https://abstrack.org
# apps/mobile: use EXPO_PUBLIC_USER_WEB_ORIGIN with the same origin (Universal Links / App Links).
NEXT_PUBLIC_USER_WEB_ORIGIN=https://abstrack.org
NEXT_PUBLIC_USER_WEB_ORIGIN=http://localhost:3000

# apps/practitioner: canonical origin for metadataBase / Open Graph. Production: https://practitioner.abstrack.org
# NEXT_PUBLIC_PRACTITIONER_WEB_ORIGIN=http://localhost:3000

# apps/practitioner: set `NEXT_PUBLIC_APP_NAME` so the TOTP issuer in authenticator apps matches
# your product name per environment. If unset, the issuer falls back to "ABStrack".
Expand All @@ -72,7 +75,7 @@ NEXT_PUBLIC_APP_NAME=ABStrack
EXPO_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co
EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_your_key
# Same origin as NEXT_PUBLIC_USER_WEB_ORIGIN on user web (caretaker invite / App Links).
EXPO_PUBLIC_USER_WEB_ORIGIN=https://abstrack.org
EXPO_PUBLIC_USER_WEB_ORIGIN=http://localhost:3000

# PowerSync Service HTTP/WebSocket endpoint for mobile offline replication (configure instance + upload `packages/powersync/sync-rules.yaml`).
# Copy the current instance URL from the PowerSync Dashboard — it may change if the Cloud project was disabled and re-enabled (see docs/SUPABASE_CLOUD_DEVELOPER.md).
Expand Down
Binary file added apps/practitioner/public/og.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions apps/practitioner/specs/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { render, screen } from '@testing-library/react';
import { LiveAnnouncerProvider } from '@abstrack/ui/a11y-web';
import Page from '../src/app/page';
import Page from '../src/app/mfa/page';
import type { PractitionerSupabaseProfilesRow } from '../src/lib/supabase-wiring';
import { useAuth } from '../src/lib/auth-provider';
import type { Session } from '@abstrack/supabase';
Expand Down Expand Up @@ -59,11 +59,11 @@ const patientProfileRow: PractitionerSupabaseProfilesRow = {
updated_at: '2020-01-01T00:00:00.000Z',
};

/** Home page calls `getSupabaseBrowserClient()` on mount; env-public throws without URL + key. */
/** MFA enrollment page calls `getSupabaseBrowserClient()` on mount; env-public throws without URL + key. */
const JEST_SUPABASE_URL = 'https://test.supabase.co';
const JEST_SUPABASE_KEY = 'sb_publishable_test_jest_placeholder';

describe('Page', () => {
describe('MfaEnrollmentPage', () => {
let prevUrl: string | undefined;
let prevKey: string | undefined;

Expand Down
2 changes: 1 addition & 1 deletion apps/practitioner/specs/login-page.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ describe('LoginPage MFA state machine', () => {
await submitCredentials();

await waitFor(() => {
expect(mockPush).toHaveBeenCalledWith('/');
expect(mockPush).toHaveBeenCalledWith('/mfa');
});
expect(mockedClearBundle).toHaveBeenCalled();
});
Expand Down
2 changes: 1 addition & 1 deletion apps/practitioner/src/app/invite/join/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export default function PractitionerInviteJoinPage() {
<div className="flex flex-col gap-3">
{donePasswordSet ? (
<Link
href="/"
href="/mfa"
className="min-h-[44px] rounded-full bg-app-primary-solid px-5 py-3 text-center text-sm font-semibold text-app-on-primary-solid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-app-ring focus-visible:ring-offset-2 focus-visible:ring-offset-app-bg"
>
Set up two-factor authentication
Expand Down
13 changes: 2 additions & 11 deletions apps/practitioner/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import './global.css';
import type { Metadata } from 'next';
import type { ReactNode } from 'react';
import { Plus_Jakarta_Sans } from 'next/font/google';
import Script from 'next/script';
Expand All @@ -8,6 +7,7 @@ import { PractitionerPublicTopNav } from '../components/app-shell/PractitionerPu
import { LiveAnnouncerRoot } from '../components/a11y/LiveAnnouncerRoot';
import { ThemeProvider } from '../components/theme/ThemeProvider';
import { AuthProvider } from '../lib/auth-provider';
import { buildRootPractitionerMetadata } from '../lib/site-seo';
import { THEME_INIT_SCRIPT } from '../lib/theme-init-script';

const fontSans = Plus_Jakarta_Sans({
Expand All @@ -16,16 +16,7 @@ const fontSans = Plus_Jakarta_Sans({
display: 'swap',
});

export const metadata: Metadata = {
title: 'ABStrack Practitioner',
description:
'Practitioner access for ABStrack patient support and care workflows',
robots: {
index: false,
follow: false,
googleBot: { index: false, follow: false },
},
};
export const metadata = buildRootPractitionerMetadata();

export default function RootLayout({ children }: { children: ReactNode }) {
return (
Expand Down
4 changes: 2 additions & 2 deletions apps/practitioner/src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ async function waitForSessionWithJwtAal2(
* Practitioner email/password login with MFA step-up and optional device trust (browser storage).
* Successful verification with “Remember this device” set to ask every time clears any stored
* bundle so trust matches the choice for this sign-in. If there is no verified TOTP factor, any existing bundle
* is cleared before redirecting to practitioner home for TOTP enrollment so stale tokens are not kept in storage.
* is cleared before redirecting to `/mfa` for TOTP enrollment so stale tokens are not kept in storage.
* After email/password authentication succeeds, password state is cleared immediately so the secret
* is not retained through MFA or device-trust checks.
* If `getUser` does not return a user id after a successful password sign-in, the client signs out
Expand Down Expand Up @@ -331,7 +331,7 @@ export default function LoginPage() {
const message =
'No verified TOTP factor yet. Redirecting so you can enroll an authenticator.';
announce(message, { politeness: 'assertive' });
router.push('/');
router.push('/mfa');
router.refresh();
return;
}
Expand Down
4 changes: 2 additions & 2 deletions apps/practitioner/src/app/manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "ABStrack Practitioner",
"short_name": "ABStrack",
"description": "Practitioner access for ABStrack patient support and care workflows",
"start_url": "/",
"description": "Invite-only clinician access for ABStrack patient support and care workflows",
"start_url": "/patients",
"display": "browser",
"icons": [
{
Expand Down
Loading