Преминете към основното съдържание

Предоставяне на Hospital акаунти

Саморегистрацията в Hospital остава изключена. Влезлият Status administrator използва общата страница Status → Акаунти, research grants и OMOP. Всеки Status administrator има еднакви комбинирани права там: appliance операции, управление на clinical/research identities, research grants и OMOP approvals. Няма нива на Status администратори. Тази оперативна identity не дава достъп до clinical records и не може да стане clinical JWT.

Новите clinical/research identities започват от точно три профила:

ПрофилСъхранена класификацияРеален достъп
Клиничен членAccountKind=CLINICAL, role=MEMBERСобствената клинична работа; прилагат се обичайните институционални правила
Клиничен ръководител на отделениеAccountKind=CLINICAL, role=HEAD_OF_DEPTКлинични права за отделението; Без институция се отказва
Само за научни целиAccountKind=RESEARCH_ONLYСамо research workspace; няма достъп до данни, докато не съществува отделен активен research grant

Идентификатор за вход​

Всеки клиничен или research акаунт в Hospital има едно изрично потребителско име. То е от 3 до 64 ASCII знака, започва с латинска буква, а след това съдържа само латински букви, цифри, точка, долна черта или тире. Главните и малките букви са разрешени и въведеният вид се запазва; уникалността и сравнението при вход не различават регистъра. Интервали, @, прави и обратни наклонени черти, контролни знаци, full-width знаци и букви извън латиницата се отказват. Няма запазени имена или представки.

Потребителското име остава запазено за акаунта при спиране, изтриване и през retention периода. Само транзакцията за окончателна анонимизация освобождава активното запазване; историческият запис за притежанието остава. Друг акаунт може да използва името едва след това освобождаване. Промяна само на главни и малки букви използва същото canonical запазване.

Името за показване е отделно и може да съдържа кирилица, цифри, пунктуация и обичайната титла на клинициста. Имейлът за контакт е по желание, уникален е, ако е попълнен, и никога не се приема за вход или резервен начин за възстановяване в Hospital. Status създава начални Member, HOD и research-only акаунти. Никога не създава неактивен Admin и не задава постоянна парола: Member/HOD първо се активира с еднократната си връзка и после се повишава чрез обоснованата промяна на роля само в Status. Водената инсталация изисква изрично потребителско име за първия клиничен администратор и никога не го извежда от имейл или вътрешен database ID.

Системният оператор се съгласува между Status и клиничната база чрез общо, монотонно поколение на данните за достъп. Двете хранилища умишлено не сравняват хешове на имейли: имейлът в Status е техническа самоличност за вход, а имейлът за контакт в клиничния профил е незадължителна информация.

Същото правило се прилага както за browser/PWA сесии, така и за native mobile bearer tokens. Hospital вход с email, с двете полета едновременно или с непознато резервно поле се отказва. Потребителското име се сравнява чрез неговия canonical ключ с малки букви, а въведеният вид се запазва за показване. Ако Hospital mode е зададен без private account-administration capability, authentication връща unavailable, вместо мълчаливо да приеме имейл.

Само администратор в Status може да преименува Hospital login. Старото canonical име остава запазено за същия акаунт до окончателната анонимизация. Операцията прекратява сесиите и неизползваните връзки, записва само че е дадена причина без свободния ѝ текст и връща нова еднократна recovery връзка. Определеният първоначален clinical authority не може да бъде преименуван така.

Откриването на езика на инсталацията използва български по подразбиране. Изборът на English при вход записва bg/en за акаунта, без да премахва останалите настройки; следващите browser, PWA и native сесии връщат езика.

Сесията на Status и нейният account-control service bearer нямат клинични или research права. (Посоченият човек appliance operator може отделно да има синхронизирания клиничен ADMIN акаунт, създаден от инсталатора.) Status не получава клинична сесия/JWT и не може да извиква общите clinical или research маршрути. Неговият отделен bearer във файл достига само endpoint-ите за управление на Hospital акаунти; bearer за read-only snapshot е различен. Създаването на акаунт не дава на Status сесията достъп до данните на този акаунт.

Управление само през Status​

Промените на clinical role и login name съществуват само на общата страница в Status. И двете изискват нормална Status сесия с парола, завършена Status MFA, повторно потвърждение на паролата и причина. Частният role маршрут може да променя активиран clinical Member/HOD/Admin към MEMBER, HEAD_OF_DEPT или ADMIN. Той отказва HOD без допустима институция, понижаване на определения първоначален chief и премахване на последния активен clinical Admin. Понижаването на HOD променя само бъдещите права и никога не прехвърля или изтрива собствените случаи на клинициста.

Username маршрутът прилага точната проверка по-горе, запазва всяко предишно canonical име, прекратява сесиите и неизползваните връзки и създава нова recovery връзка. Clinical приложенията не предоставят тези mutations.

Предаване на връзката за активиране​

След създаването Status показва еднократната връзка за активиране само веднъж. Болничният ИТ екип може:

  1. да позволи на конкретния клиницист, ръководител на отделение или изследовател да сканира локално генерирания QR code от екрана;
  2. да копира пълната връзка в одобрен болничен комуникационен канал; или
  3. да разпечата еднократната страница и да я предаде лично на получателя.

Не е необходим доставчик на електронна поща. Получателят отваря връзката, избира парола и акаунтът става активен. Връзката изтича след 72 часа, работи еднократно и се съхранява в PostgreSQL само като SHA-256 digest. Замени връзката за активиране обезсилва всички предишни неизползвани връзки за активиране, преди да издаде новата.

Token се пренася след # в URL. Браузърите не изпращат URL fragments в HTTP заявките, затова при отваряне Caddy, Web и обичайните access logs никога не го получават. Екранът за задаване на парола прочита fragment в браузъра и изпраща token само в защитеното POST body. QR се генерира локално от Status; външна QR услуга не вижда връзката.

Предоставянето на акаунт никога не създава фиктивно приемане на общите условия или съобщението за поверителност. Притежателят на акаунта трябва да приеме точните активни документи в самото приложение; migration-ът за идентичност и legal evidence, който записва това доказателство, е приложен.

Локално възстановяване​

За активен акаунт Издай връзка за възстановяване създава еднократна връзка с валидност 8 часа, представена по същия начин за копиране/печат/QR. Издаването на нова връзка за възстановяване веднага обезсилва всички по-стари неизползвани такива връзки. Първото използване сменя паролата, прекратява по-старите сесии чрез passwordChangedAt, използва връзката атомарно и обезсилва обикновените връзки за reset на парола.

Текущият код отказва activation/recovery връзки за всеки clinical ADMIN, включително повишен Admin, който не е определеният operator. Дали такива повишени Admin-и да получават recovery през Status очаква изрично security одобрение; дотогава отказът остава fail-closed. Определеният първоначален chief/operator остава защитен независимо от това и използва координирания credential workflow. Паролата на operator акаунта е синхронизирана със Status и трябва да се променя чрез scripts/appliance-operator.sh; промяна само на клиничния verifier би разделила двете данни за достъп. Директно създаване на неактивен Admin остава невъзможно.

В Hospital mode няма reset на парола или потвърждение чрез имейл. Recovery е раздаваната от администратора еднократна връзка по-горе. Използването ѝ все пак обезсилва всеки стар обикновен reset token, който може да е останал в development база. Болничният ИТ екип може по-късно изрично да издаде нова recovery връзка.

Status console-recovery session умишлено не е достатъчна за управление на акаунти. Влезте с нормалната парола на appliance administrator, за да видите списъка или да издадете връзка за акаунт.

Договор за транзакции и одит​

Създаването, издаването/преиздаването, атомарното използване, смяната на паролата и съответните им одитни доказателства се записват в една транзакция на клиничната база данни. Одитните действия са:

  • HOSPITAL_ACCOUNT_CREATED
  • HOSPITAL_ACCOUNT_ACTIVATION_ISSUED
  • HOSPITAL_ACCOUNT_ACTIVATION_REISSUED
  • HOSPITAL_ACCOUNT_ACTIVATED
  • HOSPITAL_ACCOUNT_RECOVERY_ISSUED
  • HOSPITAL_ACCOUNT_RECOVERY_CONSUMED
  • ADMIN_ACCOUNT_AUTHORITY_CHANGE
  • HOSPITAL_ACCOUNT_USERNAME_CHANGED

Одитните details съдържат класификации, институция, locale, време на изтичане и броя обезсилени по-стари връзки. Никога не съдържат URL, plaintext token, token digest, парола или email на оператора. Историята на Status не получава нищо от отговора на account lifecycle. Всички страници за акаунти използват Cache-Control: no-store.

Частните API маршрути са:

GET /v1/internal/hospital/accounts
POST /v1/internal/hospital/accounts
POST /v1/internal/hospital/accounts/{id}/activation
POST /v1/internal/hospital/accounts/{id}/recovery
PATCH /v1/internal/hospital/accounts/{id}/role
PATCH /v1/internal/hospital/accounts/{id}/username

Caddy връща 404 за /v1/internal/*; само Status достига тези маршрути по backend мрежата и трябва да представи отделния account-control bearer.

Договор за инсталираната схема​

Общите migrations за идентичност, legal evidence и потребителски имена са импортирани и приложени. Дървото с migrations на модула съдържа 20260822120000_identity_legal_case_creator, 20260822170000_hospital_account_control, 20260823120000_deployment_username_identity и 20260823130000_hospital_username_identity, а UPSTREAM_VERSIONS.json фиксира owner API, който ги носи. AccountKind (CLINICAL, RESEARCH_ONLY) съществува в схемата.

За съвместимост с кода за research grants новият research-only акаунт носи и старото RESEARCHER role; граница на Hospital-only proxy блокира това role от всички клинични маршрути.

User.approvedAt се запазва умишлено. Общата migration за идентичност го премахва, защото публичната саморегистрация използва проверка по имейл като праг за активиране и вече няма състояние „одобрено от администратор“. Hospital инсталацията няма такъв праг — акаунтите се създават през Status и се активират с еднократна връзка — а маршрутът admin/users/[id]/approve продължава да записва тази колона, както и account-provisioning.ts. Затова 20260822170000_hospital_account_control добавя колоната обратно веднага след като общата migration я премахне. Този ред е част от договора: не „довършвайте“ import-а, като премахнете колоната или записа — това би счупило маршрута за одобрение срещу база данни, на която никой не е казал, че се е променила.

Граница при надграждане и връщане назад. Всяка от тези migrations пази DDL с IF EXISTS / IF NOT EXISTS, така че повторно изпълнение от частично приложено състояние е безопасно. Hospital overlay трябва да остане след общата migration в реда на изпълнение; обратният ред оставя approvedAt премахната. Промяна на фиксирания owner API влиза отново в същото изискване — проверете дали новоимпортирана обща migration не е започнала да премахва колона, от която Hospital overlay още зависи, и никога не редактирайте UPSTREAM_VERSIONS.json преди истински tagged import.

Проверка​

Unit и route тестовете покриват точната азбука, дължина и регистър на потребителското име, незадължителния имейл за контакт, проверката на профилите, изтичането след 72 и 8 часа, съхранението само на digest, обезсилването при преиздаване, отказа за administrator/operator guards, fragment-only URL, стабилното съпоставяне на грешки, CSRF, защитата на последния Admin, запазването на HOD cases, прекратяването на сесии при role/username промяна, нормалните Status сесии с парола, двуезичните екрани и отсъствието от историята на Status. Незадължителният PostgreSQL пакет състезава два consumer-а за един activation token и доказва, че се записват точно една смяна на парола и един activation audit. Той състезава и двама издатели на връзка и доказва, че row-level serialization оставя точно една активна заместваща връзка.

Пълният Hospital Web Playwright suite проверява и видимия за потребителя сценарий през реалните private account-control и password-confirmation routes: създава локален акаунт, заменя activation връзката, доказва, че предишната е невалидна, задава парола през fragment-only страницата, доказва еднократната употреба на новата връзка, влиза, приема onboarding и вижда акаунта като active. Fixture bearer е изрично само за тест и не включва self-registration или email service.

Изпълнявайте тази database gate само срещу disposable база данни, в която Hospital migrations вече са приложени:

npm --prefix apps/api run test:pg:hospital-accounts