IAM — մուտք, կազմակերպություններ, դերեր և իրավունքներ
Սա այն մոդուլն է, որտեղից սկսվում է ցանկացած սեսիա. հաստատել, թե ով ես դու, ապա ընտրել (կամ հայտնվել) կազմակերպության մեջ։ Ամեն ինչ ստորև հենվում է apps/core-api/src/modules/auth-ի և .../organizations, .../roles-ի վրա։
Ինչպես անել...
Խմբավորված է նույն կերպ, ինչ տեխնիկական բաժինները ստորև — յուրաքանչյուր էջի օգնության պատկերակը տանում է հենց իր խումբը, ոչ թե այս ամբողջ ցանկը։
Նույնականացում
Ստեղծել հաշիվ — /auth/sign-up → Email, Գաղտնաբառ → Ստեղծել հաշիվ → ստուգիր փոստարկղդ, այնտեղ հաստատման հղումով նամակ կլինի։ Տես դաշտերի ուղեցույցը ստորև։
Մուտք գործել առանց գաղտնաբառի — /auth/sign-in-ում սեղմիր Մուտք գործել մուտքի հղումով կամ Մուտք գործել կոդով գաղտնաբառի փոխարեն (անջատիչներ գաղտնաբառի ձևի կողքին), մուտքագրիր էլ. փոստը, ստուգիր փոստարկղը։ Տես դաշտերի ուղեցույցը ստորև։
Մուտք գործել Google-ով — Շարունակել Google-ով /auth/sign-in-ում։
Վերականգնել մոռացված գաղտնաբառը — Մոռացե՞լ եք գաղտնաբառը /auth/sign-in-ում → մուտքագրիր էլ. փոստը → հետևիր նամակի հղմանը։ Տես դաշտերի ուղեցույցը ստորև։
Ստեղծել հաշիվ — դաշտերի ուղեցույց
- Email (պարտադիր) — պետք է իրական email հասցեի տեսք ունենա։ Եթե այն արդեն գրանցված է, ուղղակիորեն կասես ուղարկելիս — ի տարբերություն ստորև գաղտնաբառազուրկ հոսքերի, գրանցումը չի թաքցնում, թե արդեն կա՞ հաշիվ այս հասցեով։
- Գաղտնաբառ (պարտադիր) — 8–128 նիշ։ Այլ բարդության պահանջ չկա (պարտադիր մեծատառ/թիվ/նշան պետք չէ)։
- Ուղարկելուց հետո հաստատման նամակ է ուղարկվում և հայտնվում է Կրկին ուղարկել հաստատման նամակը հղում — սահմանափակված է րոպեում 3 ուղարկումով; գերազանցելիս ցույց է տալիս առանձին rate-limit հաղորդագրություն ընդհանուր սխալի փոխարեն։ Գրանցումն ինքնաբերաբար ստեղծում է անհատական աշխատավայր քեզ համար ֆոնում (տես Ի՞նչ է P4P-ն) — այս էկրանին դրա մասին ոչինչ չի ասվում։
Մուտք գործել առանց գաղտնաբառի — դաշտերի ուղեցույց
Թե՛ մուտքի հղումի, թե՛ միանվագ կոդի անջատիչները ամբողջովին փոխարինում են գաղտնաբառի ձևը (ոչ թե երկրորդ դաշտ ավելացնում դրան) — մեկ եղանակ ընտրվում է մեկ այցելության համար, ոչ երկուսը միասին։
- Մուտքի հղում. Email (պարտադիր, ստուգվում է միայն ոչ դատարկ լինելը — ձևաչափի ստուգում հաճախորդում չկա) → Ուղարկել հղումը։ Ինչ էլ գրես, հաստատման տեքստը միշտ նույնն է. «Եթե այդպիսի հաշիվ գոյություն ունի, մուտքի հղումն ուղարկվել է» — հավելվածը միտումնավոր երբեք չի հաստատում կամ հերքում, թե արդյոք հասցեն գրանցված է, ուստի սխալ մուտքագրված email-ը ցույց կտա հենց նույն հաջողության հաղորդագրությունը, ինչ իրական հասցեն։ Հենց հղումն ինքնին վավեր է 15 րոպե։
- Միանվագ կոդ. Email (նույն չբացահայտող վարքագիծը, ինչ մուտքի հղումինը) → Ուղարկել կոդը → հայտնվում է 6-նիշանոց կոդ դաշտ (միայն թվեր, ուղիղ 6 նիշ — Հաստատել կոճակը մնում է ապաակտիվ, մինչև բոլոր 6-ը մուտքագրվեն)։ Կոդը վավեր է 10 րոպե, և վավեր է միայն վերջին ուղարկված կոդը — նորի հայցումն անմիջապես անվավեր է դարձնում նախորդը։
- Երկու եղանակներն էլ կիսում են նույն րոպեում 3 ուղարկումի սահմանաչափը, ինչ այս հարթակի ցանկացած այլ նամակ ուղարկող գործողություն, ցուցադրվում է որպես հետհաշվարկ կրկին ուղարկելու կոճակի վրա։
Վերականգնել մոռացված գաղտնաբառը — դաշտերի ուղեցույց
- Հայցում (
/auth/forgot-password). Email (պարտադիր, ձևաչափի ստուգումով) → Ուղարկել վերականգնման հղումը։ Նույն չբացահայտող հաստատման հաղորդագրությունը, ինչ վերևի գաղտնաբառազուրկ մուտքի եղանակներինը — միայն այս էկրանից հնարավոր չէ իմանալ, թե մուտքագրված հասցեն իրապես ունի՞ հաշիվ։ - Սահմանել նոր գաղտնաբառ (նամակի հղումը,
/auth/reset-password?token=…). Նոր գաղտնաբառ (պարտադիր, 8–128 նիշ) և Հաստատել գաղտնաբառը (պարտադիր) — երկուսը պետք է ճշգրիտ համընկնեն, ստուգումը կապակցված է հատկապես Հաստատել գաղտնաբառը դաշտին (հենց այնտեղ է հայտնվում անհամապատասխանության սխալը, ոչ Նոր գաղտնաբառի տակ)։ Բացակայող token-ը (էջը բացելը ընդհանրապես առանց հղումի) փոխարինում է ամբողջ ձևը պարզ սխալի հաղորդագրությամբ; անվավեր կամ արդեն օգտագործված token-ը բռնվում է միայն ուղարկելիս և ցուցադրվում է ձևի տակ, ինչպես ցանկացած այլ ուղարկման սխալ։
Անձնական էջ
Խմբագրել պրոֆիլը — /account/profile → թարմացրու լուսանկարը, անունը, հեռախոսը, ժամային գոտին, կենսագրությունը, տեղադրությունը, ծննդյան ամսաթիվը, հմտությունները և հետաքրքրությունների ոլորտները։
Հրավերի ընդունում
Ընդունել գործընկերոջ հրավերը — բացիր հրավերի նամակի հղումը (/invitations/[token]) → եթե դեռ հաշիվ չունես, ավտոմատ կերևա գաղտնաբառի դաշտ; եթե ունես — պարզապես հաստատիր։
Կազմակերպության ստեղծում
Դրա համար այսօր կոճակ չկա — տես Կազմակերպության ստեղծում ստորև այն միակ անուղղակի ձևի մասին, որով դա տեղի է ունենում (գրանցման ժամանակ ինքնաստեղծ անձնական տիրույթ, կամ հարթակի ադմինիստրատորի «New workspace» պատուհանը)։
Կազմակերպության կարգավորումներ
Փոխել կազմակերպության անունը/նկարագրությունը/կայքը — «Կարգավորումներ» → խմբագրիր դաշտերը → Պահպանել փոփոխությունները։ Տես դաշտերի ուղեցույցը ստորև։
Փոխել կազմակերպության կարգավորումները — դաշտերի ուղեցույց
Առանց portal:organization:manage-ի (լռելյայն փոխանցված չէ ամեն դերի — տես Դերեր ստորև), ամբողջ այս էջը ցույց է տալիս նույն երեք արժեքները որպես սովորական՝ միայն-կարդալու տեքստ, ձևի փոխարեն — այստեղ ապաակտիվ/գորշ ձև չկա «կարող ես նայել, բայց չդիպչել» ազդանշանելու համար, դաշտերը պարզապես չկան։
- Տիրույթի URL (ցուցադրվում է ձևից վերևում, երբեք չի խմբագրվում) — սահմանվում է մեկ անգամ ստեղծելիս և մնում է հավերժ; ապրանքում ոչ մի տեղ ոչ մի դաշտ կամ գործողություն այն հետագայում չի փոխում։
- Անուն (պարտադիր) — 2–100 նիշ։
- Նկարագրություն (ոչ պարտադիր) — մինչև 500 նիշ։
- Կայք (ոչ պարտադիր) — եթե ընդհանրապես ինչ-որ բան մուտքագրես, պետք է լինի ամբողջական, վավեր URL (օրինակ՝
https://example.com) — առանց սխեմայի մերկ դոմեյնը մերժվում է։ Դատարկ թողնելը լիովին նորմալ է — սա այս ձևի միակ դաշտն է, որ իսկապես երկուստեք ոչ պարտադիր է։ - Ինչ չես գտնի այստեղ, թեև կարող ես սպասել. կազմակերպության սեփականատիրոջ փոփոխությունը (դա Փոխանցել սեփականությունը-ն է, Անդամներ ցանկի տողային գործողություն ստորև, միայն OWNER-ի համար) և կազմակերպության արխիվացումը/վերականգնումը (դրա համար այսօր ընդհանրապես ինտերֆեյս չկա — տես տեխնիկական բաժինը ստորև)։
Անդամներ
Հրավիրել ինչ-որ մեկին քո կազմակերպություն — «Անդամներ» → Հրավիրել անդամի → Էլ. փոստ, ընտրիր Դեր → Ուղարկել հրավերը։ Տես դաշտերի ուղեցույցը ստորև։
Հեռացնել անդամի կամ փոխանցել սեփականությունը — «Անդամներ» ցանկ → տողի գործողությունների մենյու → Փոխանցել սեփականությունը (կարող է միայն ընթացիկ OWNER-ը) կամ հեռացում։
Անդամին տալ դեր կամ փոխել նրա պաշտոնը — բացիր այդ անդամի սեփական էջը (ոչ ցանկը) → Դերեր բաժինը կամ Պաշտոնը այս աշխատանքային տիրույթում → Պահպանել։ Տես դաշտերի ուղեցույցը ստորև։
Հրավիրել անդամ — դաշտերի ուղեցույց
- Email (պարտադիր) — ձևաչափի ստուգում հաճախորդում չկա; սխալ հասցեն բռնվում է միայն ուղարկելիս։ Հասցե, որն արդեն անդամ է կամ արդեն ունի սպասող հրավեր, նույնպես բռնվում է միայն այդ պահին։
- Դեր (պարտադիր, մեկ ընտրություն) — ի տարբերություն հարթակի անձնակազմի հրավերի, կազմակերպության անդամը երբեք չի կարող մնալ ընդհանրապես առանց դերի; ցանկը լռելյայն առաջարկում է MEMBER (կամ ինչ դեր էլ պատահի առաջինը լինել, եթե MEMBER դեր ընդհանրապես չկա), ուստի դաշտը երբեք պատահաբար դատարկ չի մնում։ OWNER-ը երբեք չի երևում տարբերակների մեջ — ինչ-որ մեկին սեփականատեր դարձնելու միակ ձևը Փոխանցել սեփականությունը-ն է, երբեք հրավերը։
- Ուղարկել հրավերը-ն սահմանափակված է րոպեում 3 ուղարկումով, նույն հետհաշվարկով վարքագիծը, ինչ այս հարթակի ցանկացած այլ հրավերի երկխոսություն։
Անդամի դերեր և պաշտոն — դաշտերի ուղեցույց
- Պաշտոնը այս աշխատանքային տիրույթում (ոչ պարտադիր, սովորական տեքստ, մինչև 100 նիշ) — այս էջի միակ դաշտն է, որը միշտ կարող ես խմբագրել քո սեփական անդամակցության վրա՝ անկախ դերից կամ իրավունքից; ուրիշի պաշտոնը խմբագրելը պահանջում է
portal:members:manage։ Դա կազմակերպության մակարդակի է, ոչ գլոբալ — նույն մարդը կարող է ունենալ տարբեր պաշտոն յուրաքանչյուր աշխատանքային տիրույթում, որին պատկանում է։ - Դերեր (չեքբոքսեր, պահանջում է
portal:members:manage) — ցանկացած քանակ, ներառյալ զրո (բոլոր դերերը հանելը չի հեռացնում հենց անդամակցությունը, պարզապես թողնում է առանց իրավունքների)։ OWNER-ը նույնպես երբեք չի երևում այս ցանկում — նույն պատճառով, ինչ հրավերի երկխոսությունում. այն տեղափոխվում է միայն Փոխանցել սեփականությունը-ով, երբեք այստեղ նշանակված չէ։ - Պահպանել-ը երկու վահանակներից յուրաքանչյուրի վրա ակտիվանում է միայն երբ հենց այդ կոնկրետ վահանակում ինչ-որ բան իրապես փոխվել է — դրանք անկախ են. պաշտոնի խմբագրումը չի պահանջում Դերերին էլ դիպչել, և հակառակը։
Դերեր
Ստեղծել կազմակերպության համար սեփական դեր — «Դերեր» → Ստեղծել դեր → անվանիր, ընտրիր իրավունքներ։ Տես դաշտերի ուղեցույցը ստորև։
Խմբագրել, կրկնօրինակել կամ ջնջել դերը — դերի ⋯ → Խմբագրել, Կրկնօրինակել կամ Ջնջել։ Չորս ներկառուցված դերերը (Owner/Admin/Member/Viewer) հնարավոր չէ վերանվանել կամ ջնջել — նրանց Խմբագրել կետն անգամ չի երևում մենյուում, ի տարբերություն հարթակային դերերի նմանատիպ էկրանի, որտեղ Խմբագրելը մնում է հասանելի համակարգային դերերի վրա՝ միայն անունը արգելափակված (տես Հարթակի կառավարում → Դերեր); Կրկնօրինակել-ը դեռ աշխատում է նաև դրանց վրա, ինչպես ցանկացած դերի վրա։ Նույն դաշտերի ուղեցույցը ստորև Ստեղծել/Խմբագրելու համար։
Ստեղծել/խմբագրել կազմակերպության դեր — դաշտերի ուղեցույց
Կառուցվածքով նույն ձևն է, ինչ հարթակային դերը, երկու իրական տարբերությամբ, որոնց արժե իմանալ.
- Անուն (պարտադիր) — պետք է լինի եզակի միայն այս կազմակերպության ներսում, ոչ ամբողջ հարթակում; երկու տարբեր կազմակերպություններ կարող են ունենալ բառացիորեն նույն «Billing Manager» անունով դեր՝ առանց հակասության։ Երկխոսությունն ինքը լրացուցիչ մերժում է 2 նիշից պակասը, թեև միայն backend-ը կընդուներ մեկ նիշն էլ։ Մինչև 100 նիշ։
- Նկարագրություն (ոչ պարտադիր) — մինչև 500 նիշ։
- Իրավունքներ (չեքբոքսեր, խմբավորված ըստ տիրույթի) — նվազագույն չկա։ Չորս ներկառուցված դերերի համար այս բաժինն ընդհանրապես երբեք հասանելի չէ (նրանց համար «Խմբագրել» գործողություն չկա, ինչպես նշված է վերևում) — չկա առանձին «միայն-կարդալու իրավունքների դիտում», ի տարբերություն հարթակային դերի, որտեղ համակարգային տողերը բացում են երկխոսությունը՝ միայն Անունը արգելափակված։
- Ջնջել-ը լրացուցիչ մերժում է ջնջել դեր, որը դեռ նշանակված է ինչ-որ ակտիվ անդամակցության կամ սպասող հրավերի — նախ վերանշանակիր բոլորին այլ դերի։ Հարթակային դերերն այդպիսի ստուգում չունեն։
Նույնականացում (/auth/*)
Պարզ ասած՝ սա այն ամենն է, ինչ գտնվում է «Sign In» / «Sign Up» էկրանի տակ — հաշվի ստեղծում, մուտք հինգ տարբեր եղանակով (գաղտնաբառ, email-ով ուղարկված հղում, email-ով ուղարկված միանվագ կոդ, Google, կամ մոռացված գաղտնաբառի վերականգնում), և ելք։ Ստորև տեխնիկական մասը կարող ես չկարդալ, եթե չես վրիպազերծում այս հոսքերից որևէ մեկը։
Այս բոլոր route-երը նշված են @Public()-ով auth.controller.ts-ում (սեսիա պետք չէ դրանց հասնելու համար), իսկ գրառման վրա «ծանր» route-երը (register, login, magic-link, password-reset/request, otp/send) նաև կրում են @UseGuards(ThrottlerGuard) — եթե դրանց դեմ script ես գործարկում կրկնակի, սպասիր rate limit (տես docs/TESTING.md, նախքան որևէ բան script անելը)։
- Sign up / Sign in (
/auth/[mode].vue,mode=sign-in|sign-up) — մեկ էջ, երկու ռեժիմ, փոխարկվում է route-ի պարամետրով։ Sign-up-ը հարվածում էPOST /auth/register-ին, որը ստեղծում էUserPERSONALկազմակերպություն նրա համար (տես Ի՞նչ է P4P-ն — յուրաքանչյուր օգտատեր ունի անհատական աշխատավայր) և dev-ում Mailpit-ի միջոցով ուղարկում է հաստատման նամակ։ Sign-in-ը հարվածում էPOST /auth/login-ին, պաշտպանված էLocalAuthGuard-ով (email+գաղտնաբառ)։
- Verify email (
/auth/verify-email) — ընդունում է token-ը հաստատման նամակից (POST /auth/verify-email)։POST /auth/resend-verification-ը կանգնած է «նորից ուղարկել» գործողության հետևում, եթե հղումը ժամկետանց է։ - Forgot / Reset password (
/auth/forgot-password,/auth/reset-password) —POST /auth/password-reset/request(միշտ վերադարձնում է հաջողություն, անկախ նրանից՝ email-ը գոյություն ունի, թե ոչ — «ստուգիր փոստդ» պատասխանը մի՛ ընկալիր որպես հաշվի գոյության հաստատում), ապաPOST /auth/password-reset/confirm՝ նամակից ստացված token-ով։ - Magic link (
/auth/magic-link) — մուտք առանց գաղտնաբառի.POST /auth/magic-link-ը ուղարկում է նամակը,POST /auth/magic-link/verify-ը ընդունում է token-ը և սկսում սեսիա — նույն token-ի ձևով, ինչ գաղտնաբառով մուտքի դեպքում։ - Email OTP —
POST /auth/otp/send/POST /auth/otp/verify։ Առանձին էջ չկա — հասանելի է անջատիչի միջոցով («Մուտք գործել կոդով») հենց/auth/sign-in-ի վրա (LoginForm.vue-իsignInMethodվիճակը), Magic Link-ի նմանատիպ անջատիչի կողքին։ - Google OAuth (
/auth/callback,/auth/error) —GET /auth/google-ը սկսում է OAuth-ձեռքսեղմումը (GoogleAuthGuard),GET /auth/google/callback-ը ավարտում է այն և ուղղորդում դեպի/auth/callback(հաջողություն) կամ/auth/error(ձախողում՝ ժամկետանց/մերժված համաձայնություն, հաշվի կոնֆլիկտներ և այլն)։ - Logout (
/auth/logout) —POST /auth/logout-ը հետ է կանչում refresh token-ը. access token-ները կարճ կյանքով են (15 րոպե), այնպես որ դրանց համար սերվերային հետկանչ պետք չէ։ - Session refresh —
POST /auth/refresh— ոչ էջ է, կանչվում է ավտոմատ պորտալի HTTP client-ի կողմից, երբ access token-ը ժամկետանց է դառնում։ Refresh token-ները անթափանց են, 30-օրյա, ռոտացվող, գողության հայտնաբերմամբ (արդեն ռոտացված token-ի կրկնակի օգտագործումը հետ է կանչում ամբողջ շղթան) — տեսdocs/iam/ADR-001-authentication.md։
Անձնական էջ (/account/profile)
User-մակարդակի պրոֆիլի էջը — ցուցադրվող անուն, ավատար (POST/DELETE /me/avatar) և այլ դաշտեր GET/PATCH /me-ում։ Կապված չէ որևէ կազմակերպության հետ. տես Ճարտարապետական մակարդակներ։
Հրավերի ընդունում (/invitations/[token])
Պարզ ասած՝ էջ, որտեղ գործընկերը հայտնվում է՝ սեղմելով հրավերի նամակի հղումը։ Աշխատում է անկախ նրանից՝ նա արդեն ունի P4P հաշիվ, թե ոչ — եթե չունի, ավտոմատ հայտնվում է email/գաղտնաբառի ձև։
Հանրային էջ (GET /organizations/invitations/:token, POST /organizations/invitations/:token/accept) — աշխատում է թե՛ արդեն մուտք գործած օգտատիրոջ համար, որը միանում է մեկ այլ կազմակերպության, թե՛ բոլորովին նոր մարդու համար, որը մուտքագրում է email/գաղտնաբառ՝ մեկ քայլով հաշիվ ստեղծելու և միանալու համար։ Հրավերները կրում են Role-երի հավաքածու (InvitationRole), որոնք նշանակվում են ընդունելիս MembershipRole-ի միջոցով։
Կազմակերպության ստեղծում
POST /organizations-ը պահանջում է միայն նույնականացված օգտատեր — առանց հատուկ իրավունքի։ Ցանկացած մուտք գործած օգտատեր կարող է ստեղծել լրացուցիչ կազմակերպություններ իր ավտոմատ ստեղծված անհատականից բացի (օրինակ՝ ներկայացնելու համար ընկերություն, որը հիմնում է)։ Հաստատված է (2026-08-04, apps/portal-ում որոնում երկու API-ուղիների համար). այսօր պորտալում սրա համար UI ընդհանրապես չկա — ոչ /org/create էջ, ոչ «նոր կազմակերպություն» պատուհան, հասանելի /dashboard-ից։ UI-ից POST /organizations-ին հասնելու միակ եղանակը հիմա անուղղակի է՝ գրանցման կողմնակի էֆեկտ (որը ստեղծում է ավտոմատ PERSONAL կազմակերպություն) կամ Հարթակի կառավարման «New workspace» պատուհանից (հասանելի միայն այնտեղ)։ Ինքնուրույն «ստեղծել ևս մեկ կազմակերպություն» սցենարը պատրաստ է backend-ում, բայց դեռ կապակցված չէ frontend-ին։
Կազմակերպության կարգավորումներ (/org/[slug]/settings)
Պարզ ասած՝ Settings էջը կազմակերպության ներսում այսօր թույլ է տալիս խմբագրել միայն անունը, նկարագրությունը և կայքը — ոչ ավելին։ Երկու բան, որոնք կարող ես ակնկալել այստեղ գտնել՝ «դարձնել մեկ ուրիշին սեփականատեր» և «արխիվացնել/վերականգնել այս կազմակերպությունը» — կամ ապրում են այլ տեղում, կամ դեռ գոյություն չունեն ինտերֆեյսում (մանրամասները ստորև)։
- Պրոֆիլի դաշտեր (անուն, նկարագրություն, կայք) —
PATCH /organizations/:id, փակված էportal:organization:manageիրավունքով, փոխանցելի է ADMIN-ին կամ հատուկ դերի։ Սա ամբողջն է, ինչ տալիս էsettings.vue-ն — հաստատված է ֆայլը կարդալով (2026-08-04), նրանում արխիվացման/ակտիվացման կառավարիչներ չկան։ - Սեփականության փոխանցում — չնայած որ դա կազմակերպության կյանքի ցիկլի գործողություն է, այն չկա Settings էջում։ Դա տողի գործողություն է Անդամներ էջում (
workspace.members.actions.transferOwnership,members/index.vue) — «դարձնել այս անդամին սեփականատեր՝ ինձ փոխարեն»։PATCH /organizations/:id/transfer-ownership, փակված է միայնTenantGuard-ով route-ի մակարդակում, իրական ստուգումով (assertActorIsOwner())organizations.service.ts-ի ներսում — փոխանցելի չէportal:organization:manage-ով. պետք է իրապես ունենալOWNERդերը։ - Արխիվացում / ակտիվացում (
POST /organizations/:id/archive,PATCH /organizations/:id/activate) — հաստատված է (2026-08-04, որոնումapps/portal-ում երկու ուղիների համար). frontend մուտքի կետ չկա ընդհանրապես։ Երկու route-երն էլ աշխատում են (նույն միայնTenantGuard+assertActorIsOwner()սահմանափակումով, ինչ սեփականության փոխանցումը) և հասանելի են ուղղակի API-կանչով, բայց հիմա պորտալում կոճակ/պատուհան չկա, որը դրանք կանչի — OWNER-ը չի կարող ինքնուրույն արխիվացնել իր կազմակերպությունը UI-ի միջոցով այսօր։ Միակ արխիվացմանը մոտ պորտալի UI-ն Հարթակի կառավարում → Կազմակերպություններ-ի restore գործողությունն է (հակառակ ուղղություն, հասանելի միայն այնտեղ)։ - Slug-ը անփոփոխելի է և չունի խմբագրման ուղի (նույն տրամաբանությունը, ինչ
User.email-ինը)։
Անդամներ (/org/[slug]/members, /org/[slug]/members/[userId])
Պարզ ասած՝ անդամների ցանկը այն տեղն է, որտեղ հրավիրում ես մարդկանց, հեռացնում նրանց կամ փոխանցում սեփականությունը։ Կոնկրետ մարդու դերը կամ job title-ը փոխելու համար պետք է մտնել նրա անհատական էջը — այս երկուսը ցանկի վրա չեն։
- Ցանկ (
GET /organizations/:id/members), «Գործողություններ» բացվող ցանկով յուրաքանչյուր տողում (portal:members:readհենց ցանկի համար. տեսանելի է ցանկացած դերի, ներառյալ VIEWER-ի)։ - Հրավեր (
POST /organizations/:id/members/invite) —portal:invitations:manage։ Throttled (ThrottlerGuard)՝ ի հավելումնTenantGuard/PermissionsGuard-ի։ - Անդամի հեռացում և սեփականության փոխանցում — երկուսն էլ ապրում են ցանկի էջում (
members/index.vue), որպես տողի բացվող ցանկի գործողություններ, իրենց հաստատման պատուհաններով։ Հեռացումը պահանջում էportal:members:manage; սեփականության փոխանցումը՝ միայն OWNER-ի համար (տես Կազմակերպության կարգավորումներ վերևում — սա կյանքի ցիկլի գործողություն է, թեև ապրում է այս էջում, ոչ թե Settings-ում)։ - Դերի նշանակում/հանում, job title-ի փոփոխություն — երկուսն էլ ապրում են անդամի մանրամասների էջում (
members/[userId].vue), ոչ թե ցանկում։POST/DELETE .../members/:userId/roles/:roleIdևPATCH .../members/:userId/job-title-ը պահանջում ենportal:members:manage; սեփական job title-ի փոփոխությունը (PATCH .../members/me/job-title) պահանջում է միայնTenantGuard— բարձրացված իրավունք պետք չէ սեփական ցուցադրվող տիտղոսը փոխելու համար։ - Կազմակերպությունից դուրս գալ (
DELETE /organizations/:id/leave) — հաստատված է (2026-08-04, որոնումapps/portal-ում). frontend մուտքի կետ չկա։ Backend route-ը աշխատում է (միայնTenantGuard, ցանկացածը կարող է հեռացնել իրեն, արգելափակված է միակ/վերջին OWNER-ի համար ըստdocs/iam/ADR-007-security-invariants.md-ի), բայց «Կազմակերպությունից դուրս գալ» կոճակ այսօր պորտալում ոչ մի տեղ չկա։ ՉշփոթելSetOnLeaveDialog.vue-ի հետ — դա Staffing-ի կապ չունեցող ֆունկցիա է (մարդուն HR արձակուրդում նշելը), ոչ թե անդամակցությունից դուրս գալը։
Դերեր (/org/[slug]/roles)
Պարզ ասած՝ դերերը իրավունքների անվանված փաթեթներ են (օրինակ՝ «կարող է հրավիրել մարդկանց» կամ «կարող է խմբագրել կազմակերպության անունը»), որոնք նշանակվում են անդամներին։ Չորս դեր ներկառուցված են և չեն կարող վերանվանվել կամ ջնջվել՝ Owner, Admin, Member, Viewer — և դրանց վրա կարող ես ստեղծել քո սեփականները։
roles.controller.ts, տեղադրված է organizations/:id/roles-ի վրա։ Յուրաքանչյուր route պահանջում է @UseGuards(TenantGuard, PermissionsGuard)հենց այս հերթականությամբ — տես նշումը CLAUDE.md/docs/iam/PERMISSIONS_CATALOG.md-ում՝ թե ինչու PermissionsGuard-ը երբեք չի կարող գրանցվել գլոբալ կերպով։
- Դերերի ցանկ + նշանակելի իրավունքների կատալոգի ցանկ (
GET /organizations/:id/roles,GET .../roles/permissions) —portal:roles:read։ - Հատուկ դերի ստեղծում / խմբագրում / ջնջում, դերի իրավունքի ավելացում/հեռացում (
POST,PATCH :roleId,DELETE :roleId,POST/DELETE :roleId/permissions/:permissionId) — բոլորը պահանջում ենportal:roles:manage։ Համակարգային դերերը (OWNER/ADMIN/MEMBER/VIEWER) պաշտպանված են ջնջումից/վերանվանումից DB trigger-ով, ոչ միայն հավելվածի ստուգումով — տեսdocs/iam/ADR-003-rbac.md։
MEMBER-ը և VIEWER-ը միտումնավոր նույնական են այսօրվա սերմանված իրավունքների հավաքածուում (երկուսն էլ միայն կարդալու համար) — սա փաստաթղթավորված, կրկին հաստատված որոշում է, ոչ թե բաց։ Մի՛ «ուղղիր» դա՝ նախապես չկարդալով հիմնավորումը docs/iam/PERMISSIONS_CATALOG.md-ում։
Impersonation
Պարզ ասած՝ թույլ է տալիս SUPER_ADMIN-ին ժամանակավորապես տեսնել հարթակը մեկ այլ օգտատիրոջ աչքերով՝ օգնելու վրիպազերծել նրա հաշիվը կամ վերարտադրել խնդիր, որի մասին նա հայտնում է։ Ամեն օգտագործում գրանցվում է։ Այս պահին սրա համար կոճակ ոչ մի տեղ չկա — տես հաստատված գտածոն ստորև։
Միայն SUPER_ADMIN-ի համար (SuperAdminGuard — բառացի դերի ստուգում, ոչ թե փոխանցելի իրավունք, քանի որ impersonation-ը միտումնավոր չի փոխանցվում)։ POST /auth/impersonate-ը սկսում է սեսիա մեկ այլ ակտիվ օգտատիրոջ անունից. POST /auth/impersonate/:sessionId/end-ը ավարտում է այն։ Յուրաքանչյուր սկիզբ/ավարտ/մերժում գրանցվում է audit log-ում (impersonation.started/.ended/.rejected)։
Հաստատված է (2026-08-04, որոնում apps/portal-ում impersonat բառի և առանձին /auth/impersonate-ի համար). դրա համար frontend ընդհանրապես չկա։ Ոչ իրավունքի հետևում թաքցված կոճակ — impersonat տողը պորտալի կոդում հանդիպում է ուղիղ երկու անգամ, երկուսն էլ պատահական (AuditLog-ի ոլորտի ֆիլտրի տարբերակ /platform/audit-ում և կոդի մեկնաբանություն), և ոչինչ չի կանչում POST /auth/impersonate-ը։ Սա այսօր ամբողջությամբ backend-ային ֆունկցիա է — հասանելի է միայն ուղղակի API-կանչով SUPER_ADMIN սեսիայով, ոչ թե Հարթակի կառավարման որևէ էջից կամ որևէ այլ տեղից։ Եթե հիմա անհրաժեշտ է ինչ-որ մեկին impersonate անել՝ UI ուղի չկա, միայն հում նույնականացված հարցում։
Audit log
Պարզ ասած՝ ամբողջ հարթակի անվտանգության համար կարևոր գործողությունների մշտական, կեղծելուց պաշտպանված պատմություն — ով է մուտք գործել, ով է փոխել դեր, ով է արխիվացրել կազմակերպություն։ Ոչ ոք, ներառյալ SUPER_ADMIN-ը, չի կարող խմբագրել կամ ջնջել գրառումը գրանցվելուց հետո։
Այս մոդուլի յուրաքանչյուր իրադարձություն (մուտք, դերի փոփոխություն, կազմակերպության կյանքի ցիկլ, impersonation...) գրանցվում է միայն ավելացվող AuditLog-ում AuditService-ի միջոցով (երբեք ուղղակի Prisma-ով — DB trigger-ը արգելափակում է update/delete-ը)։ Դիտման UI-ն (/platform/audit, platform:audit:read) Հարթակի կառավարման էջ է — տես Հարթակի կառավարում → Audit log։
Այս մոդուլի թեստավորում
scripts/e2e/menu/auth.mjs, organizations.mjs և impersonation.mjs (ընդամենը 38 ստուգում) գործարկում են այս մոդուլի հոսքերը սկզբից մինչև վերջ և սահմանում lastVerified-ը վերևում։ Ավտոմատացմամբ չծածկված, արժե ձեռքով ստուգել — տես docs/MANUAL_TESTING.md. Google OAuth, երկու կազմակերպությունների միջև անցում, արխիվացված կազմակերպության վերականգնում, սեփականության փոխանցում, արդեն գոյություն ունեցող օգտատիրոջ կողմից հրավերի ընդունում (ավտոմատացված է միայն բոլորովին նոր օգտատիրոջ սցենարը), և գոյություն ունեցող դերի իրավունքների հավաքածուի խմբագրում (ավտոմատացված է միայն դերի նշանակումը անդամին)։