Add public GET /api/version (current version + GitHub-release update check,
cached, fail-soft) and GET /api/network (detected LAN addresses). Accept
localhost/private-LAN origins in CORS and Better Auth trusted origins via a
shared isAllowedOrigin helper, so staff can reach the app over the clinic
network. The seed-demo.ts fake test data is removed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Chat: history pill now shows a History icon + a Start-new-chat (SquarePen)
button; removed the duplicate chat-history list from the sidebar.
Email: deployment-wide email provider config (Resend/Postmark/SendGrid/SMTP) in
Settings → Developers, with encrypted API key and a Send-test action. sendEmail
dispatches via the chosen provider (REST via fetch; SMTP via nodemailer).
Forgot password with no provider: alert the clinic admin(s) via a "System"
message card in Messages + a bell notification (seeded system user + per-clinic
System conversation); clicking deep-links to /settings?tab=careTeam&member=<id>.
Admins can set a member's password directly from the employee dialog
(PATCH /api/staff/:id/password via Better Auth's internal context — no admin
plugin needed).
Patient Portal: "New patient" booking path registers a demographics-only patient
then books; bookings reject double-booked slots (409).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the email-invitation flow with admin-provisioned staff accounts and
add role-based access that changes what each member sees.
Backend:
- Enable Better Auth `username` plugin (staff sign in by username); regenerate
auth schema (+ username/displayUsername on user) and migration 0007.
- Add `doctor` and `reception` roles to the access-control RBAC. `reception` is
scoped to scheduling + registration (no `prescription` statement).
- New `/api/staff` route: POST creates a user (auth.api.signUpEmail) and adds
them to the active clinic (auth.api.addMember); GET lists members + usernames.
Gated by requirePermission({ member: ["create"] }).
- Redact clinical PHI for the reception role in the patients service (read,
create and update) so demographics-only is enforced server-side.
Frontend:
- usernameClient + Email|Username tabs on the login form.
- lib/roles.ts: useActiveRole + Better-Auth-permission-driven nav visibility,
default landing, and a route guard (reception -> /appointments, blocked from
clinical routes). Applied to the sidebar, command palette and auth guard.
- Care team page now provisions staff via a two-step Add-team-member dialog
(details -> username/password) hitting /api/staff; removes the email-invite
and pending-invitation UI. New members are contactable from Messages
automatically (they become org members).
- Hide clinical sections of the patient form and the admin-only settings tabs
for non-clinical/non-admin roles.
All permission management stays in Better Auth (per the better-auth skills now
referenced in backend/CLAUDE.md).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Returning members were sent to onboarding on every sign-in because the new
session had no activeOrganizationId. Add a session.create `before` hook that
defaults it to the user's first clinic membership, so sign-in lands straight
in the app.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Since email verification is no longer enforced at sign-in, gating
organization creation on `user.emailVerified` blocked onboarding with
"You are not allowed to create a new organization". Allow any signed-in
user to create a clinic; re-tie to emailVerified when verification returns.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- emailAndPassword.requireEmailVerification = false so users can sign in
immediately; verification emails are still sent and /verify-email still
works. Flip back to true to make it mandatory later (TODO noted in code).
- Add backend/CLAUDE.md documenting stack, commands, the auth/schema
generation workflow, and runtime gotchas.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- useSecureCookies now keys off the BETTER_AUTH_URL scheme instead of
NODE_ENV, so login works over http://localhost in the (production-mode)
Docker stack instead of the browser silently dropping the session cookie.
- env parsing treats empty strings as unset, so compose-supplied optionals
like `SMTP_PORT=` no longer fail coercion (Number("") === 0) and crash boot.
- docker-compose: configurable host Postgres port (POSTGRES_PORT) to avoid
clashing with an existing local Postgres.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the first temetro backend: an Express 5 API on Postgres via
Drizzle ORM, with authentication and multi-tenant clinics powered by
Better Auth.
- Auth: email/password with required email verification, password reset,
rate limiting, CSRF/trusted-origins, secure cookies, session audit hook.
- Organizations (clinics) with RBAC (owner/admin/member/viewer) and an
extended `patient` permission set; member invitations by email.
- Org-scoped patient records mirroring the frontend Patient shape, with
CRUD endpoints gated by permission (read/write/delete).
- Email helper logs links to the console when SMTP is unset (zero-setup
local dev); Dockerfile + docker-compose (db + backend + frontend) with
migrations applied on startup and a configurable Postgres host port.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>