[{"data":1,"prerenderedAt":16481},["ShallowReactive",2],{"navigation_docs":3,"-web-development-authorization-security-01-authorization-models":5074,"-web-development-authorization-security-01-authorization-models-surround":16478},[4,1707,2040,2512,2693,2819,3026,3148,3198,3255,3289,3415,3492,3506,3645,3939,4016,4749,4924,5017,5070],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"C#","i-devicon-csharp","\u002Fcsharp","01.csharp",[10,13,60,90,120,202,219,253,379,404,457,650,1364,1654,1703],{"title":11,"path":7,"stem":12},"C# та .NET","01.csharp\u002Findex",{"title":14,"icon":15,"path":16,"stem":17,"children":18,"page":59},"Fundamentals","i-lucide-book-open","\u002Fcsharp\u002Ffundamentals","01.csharp\u002F01.fundamentals",[19,23,27,31,35,39,43,47,51,55],{"title":20,"path":21,"stem":22},"Вступ до екосистеми .NET","\u002Fcsharp\u002Ffundamentals\u002Fintroduction-to-ecosystem","01.csharp\u002F01.fundamentals\u002F01.introduction-to-ecosystem",{"title":24,"path":25,"stem":26},"Структура програми на C#","\u002Fcsharp\u002Ffundamentals\u002Fprogram-structure","01.csharp\u002F01.fundamentals\u002F02.program-structure",{"title":28,"path":29,"stem":30},"Змінні та Типи Даних","\u002Fcsharp\u002Ffundamentals\u002Fvariables-data-types","01.csharp\u002F01.fundamentals\u002F03.variables-data-types",{"title":32,"path":33,"stem":34},"Масиви","\u002Fcsharp\u002Ffundamentals\u002Farrays","01.csharp\u002F01.fundamentals\u002F04.arrays",{"title":36,"path":37,"stem":38},"Strings & Text Handling","\u002Fcsharp\u002Ffundamentals\u002Fstrings-text-handling","01.csharp\u002F01.fundamentals\u002F05.strings-text-handling",{"title":40,"path":41,"stem":42},"Дати і Час","\u002Fcsharp\u002Ffundamentals\u002Fdates-time-handling","01.csharp\u002F01.fundamentals\u002F06.dates-time-handling",{"title":44,"path":45,"stem":46},"Потік Керування","\u002Fcsharp\u002Ffundamentals\u002Fcontrol-flow","01.csharp\u002F01.fundamentals\u002F07.control-flow",{"title":48,"path":49,"stem":50},"Методи","\u002Fcsharp\u002Ffundamentals\u002Fmethods","01.csharp\u002F01.fundamentals\u002F08.methods",{"title":52,"path":53,"stem":54},"Основи Відлагодження","\u002Fcsharp\u002Ffundamentals\u002Fdebugging-basics","01.csharp\u002F01.fundamentals\u002F09.debugging-basics",{"title":56,"path":57,"stem":58},"Інтерактивна Консоль (Classic)","\u002Fcsharp\u002Ffundamentals\u002Finteractive-console","01.csharp\u002F01.fundamentals\u002F10.interactive-console",false,{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":59},"OOP","i-lucide-box","\u002Fcsharp\u002Foop","01.csharp\u002F02.oop",[66,70,74,78,82,86],{"title":67,"path":68,"stem":69},"Package Management (Управління Пакетами)","\u002Fcsharp\u002Foop\u002Fpackage-management","01.csharp\u002F02.oop\u002F01.package-management",{"title":71,"path":72,"stem":73},"Класи та Об'єкти","\u002Fcsharp\u002Foop\u002Fclasses-objects","01.csharp\u002F02.oop\u002F02.classes-objects",{"title":75,"path":76,"stem":77},"Властивості та Поля","\u002Fcsharp\u002Foop\u002Fproperties-fields","01.csharp\u002F02.oop\u002F03.properties-fields",{"title":79,"path":80,"stem":81},"Стовпи ООП","\u002Fcsharp\u002Foop\u002Foop-pillars","01.csharp\u002F02.oop\u002F04.oop-pillars",{"title":83,"path":84,"stem":85},"Advanced Types","\u002Fcsharp\u002Foop\u002Fadvanced-types","01.csharp\u002F02.oop\u002F05.advanced-types",{"title":87,"path":88,"stem":89},"Namespaces (Простори Імен)","\u002Fcsharp\u002Foop\u002Fnamespaces","01.csharp\u002F02.oop\u002F06.namespaces",{"title":91,"icon":92,"path":93,"stem":94,"children":95,"page":59},"Advanced Core","i-lucide-zap","\u002Fcsharp\u002Fadvanced-core","01.csharp\u002F03.advanced-core",[96,100,104,108,112,116],{"title":97,"path":98,"stem":99},"Generics (Узагальнення)","\u002Fcsharp\u002Fadvanced-core\u002Fgenerics","01.csharp\u002F03.advanced-core\u002F01.generics",{"title":101,"path":102,"stem":103},"Делегати, Події та Лямбда-вирази","\u002Fcsharp\u002Fadvanced-core\u002Fdelegates-events-lambdas","01.csharp\u002F03.advanced-core\u002F02.delegates-events-lambdas",{"title":105,"path":106,"stem":107},"Interfaces Deep Dive (Інтерфейси: Поглиблений Розгляд)","\u002Fcsharp\u002Fadvanced-core\u002Finterfaces-deep-dive","01.csharp\u002F03.advanced-core\u002F03.interfaces-deep-dive",{"title":109,"path":110,"stem":111},"Обробка Винятків","\u002Fcsharp\u002Fadvanced-core\u002Fexception-handling","01.csharp\u002F03.advanced-core\u002F04.exception-handling",{"title":113,"path":114,"stem":115},"Pattern Matching","\u002Fcsharp\u002Fadvanced-core\u002Fpattern-matching","01.csharp\u002F03.advanced-core\u002F05.pattern-matching",{"title":117,"path":118,"stem":119},"Додаткові Можливості C#","\u002Fcsharp\u002Fadvanced-core\u002Fadditional-features","01.csharp\u002F03.advanced-core\u002F06.additional-features",{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":59},"Architecture Best Practices","i-lucide-building-2","\u002Fcsharp\u002Farchitecture-best-practices","01.csharp\u002F04.architecture-best-practices",[126,130,149,153,157,161,165,169],{"title":127,"path":128,"stem":129},"Software Design Principles (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fsoftware-design-principles","01.csharp\u002F04.architecture-best-practices\u002F01.software-design-principles",{"title":131,"icon":132,"path":133,"stem":134,"children":135,"page":59},"Design Patterns","i-lucide-folder","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns",[136],{"title":137,"icon":132,"path":138,"stem":139,"children":140,"page":59},"Creational","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational",[141,145],{"title":142,"path":143,"stem":144},"Singleton (Одинак)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fsingleton","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F01.singleton",{"title":146,"path":147,"stem":148},"Builder (Будівельник)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fbuilder","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F02.builder",{"title":150,"path":151,"stem":152},"Building Professional CLIs","\u002Fcsharp\u002Farchitecture-best-practices\u002Fbuilding-professional-clis","01.csharp\u002F04.architecture-best-practices\u002F03.building-professional-clis",{"title":154,"path":155,"stem":156},"Validation & Flow Control","\u002Fcsharp\u002Farchitecture-best-practices\u002Fvalidation-flow-control","01.csharp\u002F04.architecture-best-practices\u002F04.validation-flow-control",{"title":158,"path":159,"stem":160},"The Modern .NET Host (Microsoft.Extensions)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fmodern-dotnet-host","01.csharp\u002F04.architecture-best-practices\u002F05.modern-dotnet-host",{"title":162,"path":163,"stem":164},"Data Mapper: Repository та DAO патерни (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part1","01.csharp\u002F04.architecture-best-practices\u002F06.data-mapper-part1",{"title":166,"path":167,"stem":168},"Data Mapper: Repository та DAO патерни (Частина 2)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part2","01.csharp\u002F04.architecture-best-practices\u002F07.data-mapper-part2",{"title":170,"icon":132,"path":171,"stem":172,"children":173,"page":59},"Di Ioc","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc",[174,178,182,186,190,194,198],{"title":175,"path":176,"stem":177},"Проблема залежностей та Інверсія Контролю","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fthe-dependency-problem","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F01.the-dependency-problem",{"title":179,"path":180,"stem":181},"Будуємо власний Service Container","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fbuild-your-own-container","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F02.build-your-own-container",{"title":183,"path":184,"stem":185},"Service Locator: Паттерн та Анти-паттерн","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-locator-pattern","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F03.service-locator-pattern",{"title":187,"path":188,"stem":189},"Паттерни Dependency Injection","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdependency-injection-patterns","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F04.dependency-injection-patterns",{"title":191,"path":192,"stem":193},"Microsoft DI: IServiceCollection та IServiceProvider","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fmicrosoft-di-deep-dive","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F05.microsoft-di-deep-dive",{"title":195,"path":196,"stem":197},"Service Lifetimes та Scopes","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-lifetimes-and-scopes","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F06.service-lifetimes-and-scopes",{"title":199,"path":200,"stem":201},"DI Анти-паттерни та Найкращі Практики","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdi-anti-patterns-and-best-practices","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F07.di-anti-patterns-and-best-practices",{"title":203,"icon":132,"path":204,"stem":205,"children":206,"page":59},"Standard Library","\u002Fcsharp\u002Fstandard-library","01.csharp\u002F05.standard-library",[207,211,215],{"title":208,"path":209,"stem":210},"Collections (Колекції)","\u002Fcsharp\u002Fstandard-library\u002Fcollections","01.csharp\u002F05.standard-library\u002F01.collections",{"title":212,"path":213,"stem":214},"High Performance Types (Високопродуктивні Типи)","\u002Fcsharp\u002Fstandard-library\u002Fhigh-performance-types","01.csharp\u002F05.standard-library\u002F02.high-performance-types",{"title":216,"path":217,"stem":218},"LINQ (Language Integrated Query)","\u002Fcsharp\u002Fstandard-library\u002Flinq","01.csharp\u002F05.standard-library\u002F03.linq",{"title":220,"icon":221,"path":222,"stem":223,"children":224,"page":59},"System Internals Concurrency","i-lucide-server","\u002Fcsharp\u002Fsystem-internals-concurrency","01.csharp\u002F06.system-internals-concurrency",[225,229,233,237,241,245,249],{"title":226,"path":227,"stem":228},"Memory Management","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmemory-management","01.csharp\u002F06.system-internals-concurrency\u002F01.memory-management",{"title":230,"path":231,"stem":232},"Reflection API: System.Type та Метадані","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Freflection-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F02.reflection-fundamentals",{"title":234,"path":235,"stem":236},"Attributes та Dynamic Language Runtime","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fattributes-dynamic","01.csharp\u002F06.system-internals-concurrency\u002F03.attributes-dynamic",{"title":238,"path":239,"stem":240},"Expression Trees: Швидка Альтернатива Рефлексії","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fexpression-trees-compiled","01.csharp\u002F06.system-internals-concurrency\u002F04.expression-trees-compiled",{"title":242,"path":243,"stem":244},"Source Generators: Compile-Time Code Generation","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsource-generators","01.csharp\u002F06.system-internals-concurrency\u002F05.source-generators",{"title":246,"path":247,"stem":248},"Multithreading Fundamentals","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmultithreading-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F06.multithreading-fundamentals",{"title":250,"path":251,"stem":252},"Synchronization Primitives","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsynchronization-primitives","01.csharp\u002F06.system-internals-concurrency\u002F07.synchronization-primitives",{"title":254,"icon":255,"path":256,"stem":257,"children":258,"page":59},"System Programming Windows","i-lucide-cpu","\u002Fcsharp\u002Fsystem-programming-windows","01.csharp\u002F07.system-programming-windows",[259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327,331,335,339,343,347,351,355,359,363,367,371,375],{"title":260,"path":261,"stem":262},"Як Працює Операційна Система","\u002Fcsharp\u002Fsystem-programming-windows\u002Fhow-os-works","01.csharp\u002F07.system-programming-windows\u002F01.how-os-works",{"title":264,"path":265,"stem":266},"Процеси в .NET — API та Запуск","\u002Fcsharp\u002Fsystem-programming-windows\u002Fprocesses-in-dotnet","01.csharp\u002F07.system-programming-windows\u002F02.processes-in-dotnet",{"title":268,"path":269,"stem":270},"Процеси в .NET — IPC та Міжпроцесна Комунікація","\u002Fcsharp\u002Fsystem-programming-windows\u002F02a.processes-ipc","01.csharp\u002F07.system-programming-windows\u002F02a.processes-ipc",{"title":272,"path":273,"stem":274},"Application Domains та Збірки — AppDomain і AssemblyLoadContext","\u002Fcsharp\u002Fsystem-programming-windows\u002Fappdomains-assemblies","01.csharp\u002F07.system-programming-windows\u002F03.appdomains-assemblies",{"title":276,"path":277,"stem":278},"Application Domains та Збірки — Plug-in Система з Hot-Reload","\u002Fcsharp\u002Fsystem-programming-windows\u002F03a.appdomains-plugin-system","01.csharp\u002F07.system-programming-windows\u002F03a.appdomains-plugin-system",{"title":280,"path":281,"stem":282},"Потоки — Основи та API Thread","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-fundamentals","01.csharp\u002F07.system-programming-windows\u002F04.thread-fundamentals",{"title":284,"path":285,"stem":286},"Потоки — Lifecycle, Пріоритети та Безпечне Завершення","\u002Fcsharp\u002Fsystem-programming-windows\u002F04a.thread-lifecycle-priorities","01.csharp\u002F07.system-programming-windows\u002F04a.thread-lifecycle-priorities",{"title":288,"path":289,"stem":290},"Проблеми Спільного Стану — Race Condition та Data Race","\u002Fcsharp\u002Fsystem-programming-windows\u002Fshared-state-problems","01.csharp\u002F07.system-programming-windows\u002F05.shared-state-problems",{"title":292,"path":293,"stem":294},"Проблеми Спільного Стану — Memory Model та volatile","\u002Fcsharp\u002Fsystem-programming-windows\u002F05a.shared-state-memory-model","01.csharp\u002F07.system-programming-windows\u002F05a.shared-state-memory-model",{"title":296,"path":297,"stem":298},"Синхронізація — Monitor, lock та еволюція примітивів","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-fundamentals","01.csharp\u002F07.system-programming-windows\u002F06.synchronization-fundamentals",{"title":300,"path":301,"stem":302},"Синхронізація — Наскрізний Приклад та Deadlock Detection","\u002Fcsharp\u002Fsystem-programming-windows\u002F06a.synchronization-walkthrough","01.csharp\u002F07.system-programming-windows\u002F06a.synchronization-walkthrough",{"title":304,"path":305,"stem":306},"Синхронізація — Mutex, Semaphore та Event-Based Primitives","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-advanced","01.csharp\u002F07.system-programming-windows\u002F07.synchronization-advanced",{"title":308,"path":309,"stem":310},"Синхронізація — Interlocked, Volatile та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002F07a.synchronization-advanced-walkthrough","01.csharp\u002F07.system-programming-windows\u002F07a.synchronization-advanced-walkthrough",{"title":312,"path":313,"stem":314},"Interlocked, CAS та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002Finterlocked-cas-lockfree","01.csharp\u002F07.system-programming-windows\u002F08.interlocked-cas-lockfree",{"title":316,"path":317,"stem":318},"Volatile, Memory Model та Spinning","\u002Fcsharp\u002Fsystem-programming-windows\u002F08a.volatile-memory-model","01.csharp\u002F07.system-programming-windows\u002F08a.volatile-memory-model",{"title":320,"path":321,"stem":322},"ThreadPool — Пул Потоків для Ефективного Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-pool","01.csharp\u002F07.system-programming-windows\u002F09.thread-pool",{"title":324,"path":325,"stem":326},"ThreadPool — Просунуті Сценарії та Внутрішня Будова","\u002Fcsharp\u002Fsystem-programming-windows\u002F09a.thread-pool-advanced","01.csharp\u002F07.system-programming-windows\u002F09a.thread-pool-advanced",{"title":328,"path":329,"stem":330},"Concurrent та Immutable Collections","\u002Fcsharp\u002Fsystem-programming-windows\u002Fconcurrent-collections","01.csharp\u002F07.system-programming-windows\u002F10.concurrent-collections",{"title":332,"path":333,"stem":334},"TPL, Task та Композиція — Від Thread до Task","\u002Fcsharp\u002Fsystem-programming-windows\u002Ftpl-parallel-plinq","01.csharp\u002F07.system-programming-windows\u002F11.tpl-parallel-plinq",{"title":336,"path":337,"stem":338},"Parallel Class та PLINQ — Data Parallelism","\u002Fcsharp\u002Fsystem-programming-windows\u002F11a.tpl-parallel-plinq-advanced","01.csharp\u002F07.system-programming-windows\u002F11a.tpl-parallel-plinq-advanced",{"title":340,"path":341,"stem":342},"Async\u002FAwait — Фундамент Асинхронного Програмування","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-fundamentals","01.csharp\u002F07.system-programming-windows\u002F12.async-fundamentals",{"title":344,"path":345,"stem":346},"SynchronizationContext та ConfigureAwait — Контекст Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-context-configureawait","01.csharp\u002F07.system-programming-windows\u002F13.async-context-configureawait",{"title":348,"path":349,"stem":350},"Async — Просунуті Паттерни","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-advanced","01.csharp\u002F07.system-programming-windows\u002F14.async-advanced",{"title":352,"path":353,"stem":354},"System.Threading.Channels — Async Producer-Consumer","\u002Fcsharp\u002Fsystem-programming-windows\u002Fchannels","01.csharp\u002F07.system-programming-windows\u002F15.channels",{"title":356,"path":357,"stem":358},"Асинхронна Синхронізація","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-synchronization","01.csharp\u002F07.system-programming-windows\u002F16.async-synchronization",{"title":360,"path":361,"stem":362},"Unsafe Code та Вказівники","\u002Fcsharp\u002Fsystem-programming-windows\u002Funsafe-code","01.csharp\u002F07.system-programming-windows\u002F17.unsafe-code",{"title":364,"path":365,"stem":366},"P\u002FInvoke та Windows API — Міст між .NET та Native Code","\u002Fcsharp\u002Fsystem-programming-windows\u002Fpinvoke-winapi","01.csharp\u002F07.system-programming-windows\u002F18.pinvoke-winapi",{"title":368,"path":369,"stem":370},"Реєстр Windows — Центральна База Конфігурації Системи","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-registry","01.csharp\u002F07.system-programming-windows\u002F19.windows-registry",{"title":372,"path":373,"stem":374},"Windows Hooks, Hotkeys та Services — Глибока Інтеграція з ОС","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-hooks-services","01.csharp\u002F07.system-programming-windows\u002F20.windows-hooks-services",{"title":376,"path":377,"stem":378},"Системне Програмування C# (Windows) — 07.system-programming-windows","\u002Fcsharp\u002Fsystem-programming-windows\u002Fimplementation_plan","01.csharp\u002F07.system-programming-windows\u002Fimplementation_plan",{"title":380,"icon":132,"path":381,"stem":382,"children":383,"page":59},"Io","\u002Fcsharp\u002Fio","01.csharp\u002F08.io",[384,388,392,396,400],{"title":385,"path":386,"stem":387},"8.1.1. Основи роботи з файловою системою","\u002Fcsharp\u002Fio\u002Ffile-system-basics","01.csharp\u002F08.io\u002F01.file-system-basics",{"title":389,"path":390,"stem":391},"8.1.2. Потоки (Streams) та Серіалізація Даних","\u002Fcsharp\u002Fio\u002Fstreams-serialization","01.csharp\u002F08.io\u002F02.streams-serialization",{"title":393,"path":394,"stem":395},"8.2.1. JSON Serialization з System.Text.Json","\u002Fcsharp\u002Fio\u002Fjson-serialization","01.csharp\u002F08.io\u002F03.json-serialization",{"title":397,"path":398,"stem":399},"8.2.2. XML Serialization та LINQ to XML","\u002Fcsharp\u002Fio\u002Fxml-serialization","01.csharp\u002F08.io\u002F04.xml-serialization",{"title":401,"path":402,"stem":403},"8.2.3. Binary Serialization: MessagePack та Protocol Buffers","\u002Fcsharp\u002Fio\u002Fbinary-serialization","01.csharp\u002F08.io\u002F05.binary-serialization",{"title":405,"icon":132,"path":406,"stem":407,"children":408,"page":59},"Ado Net","\u002Fcsharp\u002Fado-net","01.csharp\u002F09.ado-net",[409,413,417,421,425,429,433,437,441,445,449,453],{"title":410,"path":411,"stem":412},"9.1. Введення в ADO.NET","\u002Fcsharp\u002Fado-net\u002Fintroduction-to-adonet","01.csharp\u002F09.ado-net\u002F01.introduction-to-adonet",{"title":414,"path":415,"stem":416},"9.2. Клас DbConnection — з'єднання з базою даних","\u002Fcsharp\u002Fado-net\u002Fconnection","01.csharp\u002F09.ado-net\u002F02.connection",{"title":418,"path":419,"stem":420},"9.3. Клас DbCommand — виконання SQL-запитів","\u002Fcsharp\u002Fado-net\u002Fcommand-and-queries","01.csharp\u002F09.ado-net\u002F03.command-and-queries",{"title":422,"path":423,"stem":424},"9.4. Клас DbDataReader — ефективне читання даних","\u002Fcsharp\u002Fado-net\u002Fdatareader","01.csharp\u002F09.ado-net\u002F04.datareader",{"title":426,"path":427,"stem":428},"9.5. Параметризовані запити та захист від SQL Injection","\u002Fcsharp\u002Fado-net\u002Fparameters-and-sql-injection","01.csharp\u002F09.ado-net\u002F05.parameters-and-sql-injection",{"title":430,"path":431,"stem":432},"9.6. Транзакції в ADO.NET","\u002Fcsharp\u002Fado-net\u002Ftransactions","01.csharp\u002F09.ado-net\u002F06.transactions",{"title":434,"path":435,"stem":436},"9.7. DbProviderFactory — провайдер-незалежний код","\u002Fcsharp\u002Fado-net\u002Fprovider-factory","01.csharp\u002F09.ado-net\u002F07.provider-factory",{"title":438,"path":439,"stem":440},"9.8. Асинхронний доступ до даних","\u002Fcsharp\u002Fado-net\u002Fasync-data-access","01.csharp\u002F09.ado-net\u002F08.async-data-access",{"title":442,"path":443,"stem":444},"9.9. Від'єднаний режим: DataSet, DataTable, DataRow","\u002Fcsharp\u002Fado-net\u002Fdisconnected-mode-dataset","01.csharp\u002F09.ado-net\u002F09.disconnected-mode-dataset",{"title":446,"path":447,"stem":448},"9.10. DataAdapter — міст між DataSet та базою даних","\u002Fcsharp\u002Fado-net\u002Fdata-adapter","01.csharp\u002F09.ado-net\u002F10.data-adapter",{"title":450,"path":451,"stem":452},"9.11. Data Mapper та Repository: Архітектура доступу до даних","\u002Fcsharp\u002Fado-net\u002Fdata-mapper-repository","01.csharp\u002F09.ado-net\u002F11.data-mapper-repository",{"title":454,"path":455,"stem":456},"9.12. Identity Map, Unit of Work та Specification Pattern","\u002Fcsharp\u002Fado-net\u002Fadvanced-patterns","01.csharp\u002F09.ado-net\u002F12.advanced-patterns",{"title":458,"icon":255,"path":459,"stem":460,"children":461,"page":59},"Ef Core","\u002Fcsharp\u002Fef-core","01.csharp\u002F10.ef-core",[462,466,470,474,478,482,486,490,494,498,502,506,510,514,518,522,526,532,538,542,546,550,554,558,562,566,570,574,578,582,586,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646],{"title":463,"path":464,"stem":465},"Що таке ORM? Від SQL до об'єктів","\u002Fcsharp\u002Fef-core\u002Fwhat-is-orm","01.csharp\u002F10.ef-core\u002F01.what-is-orm",{"title":467,"path":468,"stem":469},"Перший проєкт — від нуля до CRUD","\u002Fcsharp\u002Fef-core\u002Ffirst-project","01.csharp\u002F10.ef-core\u002F02.first-project",{"title":471,"path":472,"stem":473},"DbContext — Серце EF Core","\u002Fcsharp\u002Fef-core\u002Fdbcontext-deep-dive","01.csharp\u002F10.ef-core\u002F03.dbcontext-deep-dive",{"title":475,"path":476,"stem":477},"Провайдери баз даних — Архітектура та Вибір СУБД","\u002Fcsharp\u002Fef-core\u002Fdatabase-providers","01.csharp\u002F10.ef-core\u002F04.database-providers",{"title":479,"path":480,"stem":481},"Конвенції EF Core — Магія без конфігурації","\u002Fcsharp\u002Fef-core\u002Fconventions","01.csharp\u002F10.ef-core\u002F05.conventions",{"title":483,"path":484,"stem":485},"Fluent API та Data Annotations — Явна конфігурація моделі","\u002Fcsharp\u002Fef-core\u002Ffluent-api-vs-annotations","01.csharp\u002F10.ef-core\u002F06.fluent-api-vs-annotations",{"title":487,"path":488,"stem":489},"Зв'язки — One-to-One та One-to-Many","\u002Fcsharp\u002Fef-core\u002Frelationships-basics","01.csharp\u002F10.ef-core\u002F07.relationships-basics",{"title":491,"path":492,"stem":493},"Зв'язки Advanced — Many-to-Many та Складні Сценарії","\u002Fcsharp\u002Fef-core\u002Frelationships-advanced","01.csharp\u002F10.ef-core\u002F08.relationships-advanced",{"title":495,"path":496,"stem":497},"Властивості — Типи, Конвертери, Компаратори (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part1","01.csharp\u002F10.ef-core\u002F09.property-configuration-part1",{"title":499,"path":500,"stem":501},"Властивості — Value Comparers, Generators, Shadow Properties (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part2","01.csharp\u002F10.ef-core\u002F09.property-configuration-part2",{"title":503,"path":504,"stem":505},"Складні типи — Owned Types та Complex Types (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part1","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part1",{"title":507,"path":508,"stem":509},"Складні типи — Complex Types, Keyless Entities, Порівняння (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part2","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part2",{"title":511,"path":512,"stem":513},"JSON Columns — Складні дані у JSON (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part1","01.csharp\u002F10.ef-core\u002F11.json-columns-part1",{"title":515,"path":516,"stem":517},"JSON Columns — Value Comparers, Індекси, Провайдери (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part2","01.csharp\u002F10.ef-core\u002F11.json-columns-part2",{"title":519,"path":520,"stem":521},"Успадкування — Абстрактні класи та TPH (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finheritance-part1","01.csharp\u002F10.ef-core\u002F12.inheritance-part1",{"title":523,"path":524,"stem":525},"Успадкування — TPT, TPC та Порівняння Стратегій (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finheritance-part2","01.csharp\u002F10.ef-core\u002F12.inheritance-part2",{"title":527,"path":528,"stem":529,"children":530},"Індекси, Обмеження та Схема (Частина 1)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part1","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part1",[531],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"Індекси, Обмеження та Схема (Частина 2)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part2","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part2",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541},"Seed Data — Початкові Дані (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fseeding-part1","01.csharp\u002F10.ef-core\u002F14.seeding-part1",{"title":543,"path":544,"stem":545},"Seed Data — SQL-скрипти, Bogus та Стратегії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fseeding-part2","01.csharp\u002F10.ef-core\u002F14.seeding-part2",{"title":547,"path":548,"stem":549},"Global Query Filters — Глобальні Фільтри (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part1","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part1",{"title":551,"path":552,"stem":553},"Global Query Filters — Підводні камені та Інтеграція (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part2","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part2",{"title":555,"path":556,"stem":557},"LINQ-запити в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part1","01.csharp\u002F10.ef-core\u002F16.linq-queries-part1",{"title":559,"path":560,"stem":561},"LINQ-запити в EF Core (Частина 2)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part2","01.csharp\u002F10.ef-core\u002F16.linq-queries-part2",{"title":563,"path":564,"stem":565},"Завантаження Пов'язаних Даних (Частина 1)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part1","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part1",{"title":567,"path":568,"stem":569},"Завантаження Пов'язаних Даних (Частина 2)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part2","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part2",{"title":571,"path":572,"stem":573},"Raw SQL, Views та Stored Procedures (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part1","01.csharp\u002F10.ef-core\u002F18.raw-sql-part1",{"title":575,"path":576,"stem":577},"Raw SQL — Stored Procedures, DbFunction та Bulk Operations (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part2","01.csharp\u002F10.ef-core\u002F18.raw-sql-part2",{"title":579,"path":580,"stem":581},"Продвинуті Запити — Compiled Queries, Bulk та Оптимізація (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part1","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part1",{"title":583,"path":584,"stem":585},"Продвинуті Запити — Query Tags, Bulk та Interceptors (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part2","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part2",{"title":587,"path":588,"stem":589},"Change Tracker — Відстеження Змін (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part1","01.csharp\u002F10.ef-core\u002F20.change-tracking-part1",{"title":591,"path":592,"stem":593},"Change Tracker — Графи Об'єктів та Disconnected (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part2","01.csharp\u002F10.ef-core\u002F20.change-tracking-part2",{"title":595,"path":596,"stem":597},"Збереження Даних та Транзакції (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part1","01.csharp\u002F10.ef-core\u002F21.saving-data-part1",{"title":599,"path":600,"stem":601},"Збереження Даних — Concurrency та Outbox (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part2","01.csharp\u002F10.ef-core\u002F21.saving-data-part2",{"title":603,"path":604,"stem":605},"Конкурентність та Блокування (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part1","01.csharp\u002F10.ef-core\u002F22.concurrency-part1",{"title":607,"path":608,"stem":609},"Конкурентність — Дедлоки та Queue Processing (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part2","01.csharp\u002F10.ef-core\u002F22.concurrency-part2",{"title":611,"path":612,"stem":613},"Міграції в EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part1","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part1",{"title":615,"path":616,"stem":617},"Міграції в EF Core — Основи (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part2","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part2",{"title":619,"path":620,"stem":621},"Міграції — Просунуті Сценарії (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part1","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part1",{"title":623,"path":624,"stem":625},"Міграції — Просунуті Сценарії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part2","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part2",{"title":627,"path":628,"stem":629},"Управління Схемою та Database-First (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part1","01.csharp\u002F10.ef-core\u002F25.schema-management-part1",{"title":631,"path":632,"stem":633},"Управління Схемою та Database-First (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part2","01.csharp\u002F10.ef-core\u002F25.schema-management-part2",{"title":635,"path":636,"stem":637},"Продуктивність EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fperformance-fundamentals-part1","01.csharp\u002F10.ef-core\u002F26.performance-fundamentals-part1",{"title":639,"path":640,"stem":641},"Interceptors в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part1","01.csharp\u002F10.ef-core\u002F29.interceptors-part1",{"title":643,"path":644,"stem":645},"Interceptors в EF Core — Connection, Transaction та Materialization (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part2","01.csharp\u002F10.ef-core\u002F29.interceptors-part2",{"title":647,"path":648,"stem":649},"План вивчення Entity Framework Core — Повний курс","\u002Fcsharp\u002Fef-core\u002Fimplementation_plan","01.csharp\u002F10.ef-core\u002Fimplementation_plan",{"title":651,"icon":652,"path":653,"stem":654,"children":655,"page":59},"ASP.NET","i-devicon-dotnetcore","\u002Fcsharp\u002Faspnet","01.csharp\u002F11.aspnet",[656,730,791,869,927,941,967,1057,1111,1182,1212,1289,1346],{"title":657,"icon":658,"path":659,"stem":660,"children":661,"page":59},"Minimal API","i-lucide-network","\u002Fcsharp\u002Faspnet\u002Fminimal-api","01.csharp\u002F11.aspnet\u002F01.minimal-api",[662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726],{"title":663,"path":664,"stem":665},"Вступ до ASP.NET та еволюція фреймворку","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fintroduction","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F01.introduction",{"title":667,"path":668,"stem":669},"Перший додаток на ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Ffirst-application","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F02.first-application",{"title":671,"path":672,"stem":673},"WebApplication, Builder та Dependency Injection","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fwebapplication-builder","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F03.webapplication-builder",{"title":675,"path":676,"stem":677},"Конвеєр запитів та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frequest-pipeline-middleware","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F04.request-pipeline-middleware",{"title":679,"path":680,"stem":681},"Маршрутизація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F05.routing-basics",{"title":683,"path":684,"stem":685},"Маршрутизація в ASP.NET Core: Розширені можливості","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F06.routing-advanced",{"title":687,"path":688,"stem":689},"Статичні файли в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-files","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F07.static-files",{"title":691,"path":692,"stem":693},"Статичні Активи: MapStaticAssets (ASP.NET Core 9.0)","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-assets","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F08.static-assets",{"title":695,"path":696,"stem":697},"Конфігурація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-fundamentals","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F09.configuration-fundamentals",{"title":699,"path":700,"stem":701},"Конфігурація: Паттерн Options","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-options","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F10.configuration-options",{"title":703,"path":704,"stem":705},"Логування в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F11.logging-basics",{"title":707,"path":708,"stem":709},"Логування: Serilog та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F12.logging-advanced",{"title":711,"path":712,"stem":713},"Управління станом: HttpContext.Items та Cookies","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstate-management","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F13.state-management",{"title":715,"path":716,"stem":717},"Стан сесії: Sessions","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fsession-state","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F14.session-state",{"title":719,"path":720,"stem":721},"Структура проєкту: від хаосу до архітектури","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fproject-structure","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F15.project-structure",{"title":723,"path":724,"stem":725},"Scalar у Minimal API: повний проєкт і Fluent OpenAPI","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fscalar-openapi-fluent","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F16.scalar-openapi-fluent",{"title":727,"path":728,"stem":729},"Swagger \u002F Swashbuckle у Minimal API: окремий класичний шлях","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fswagger-swashbuckle","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F17.swagger-swashbuckle",{"title":731,"icon":658,"path":732,"stem":733,"children":734,"page":59},"API","\u002Fcsharp\u002Faspnet\u002Fapi","01.csharp\u002F11.aspnet\u002F02.api",[735,739,743,747,751,755,759,763,767,771,775,779,783,787],{"title":736,"path":737,"stem":738},"Що таке API. Клієнт-серверна архітектура","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fwhat-is-api","01.csharp\u002F11.aspnet\u002F02.api\u002F01.what-is-api",{"title":740,"path":741,"stem":742},"Формати даних: JSON, XML, TOML та бінарні формати","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fdata-formats","01.csharp\u002F11.aspnet\u002F02.api\u002F02.data-formats",{"title":744,"path":745,"stem":746},"Парадигми API та концепція REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-paradigms-rest","01.csharp\u002F11.aspnet\u002F02.api\u002F03.api-paradigms-rest",{"title":748,"path":749,"stem":750},"HTTP-методи, статус-коди та заголовки","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fhttp-methods-status-codes","01.csharp\u002F11.aspnet\u002F02.api\u002F04.http-methods-status-codes",{"title":752,"path":753,"stem":754},"Організація HTTP API за принципами REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Frest-organizing","01.csharp\u002F11.aspnet\u002F02.api\u002F05.rest-organizing",{"title":756,"path":757,"stem":758},"Номенклатура URL та CRUD-операції","\u002Fcsharp\u002Faspnet\u002Fapi\u002Furl-nomenclature-crud","01.csharp\u002F11.aspnet\u002F02.api\u002F06.url-nomenclature-crud",{"title":760,"path":761,"stem":762},"Правила дизайну: іменування та стандарти","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-naming","01.csharp\u002F11.aspnet\u002F02.api\u002F07.api-design-naming",{"title":764,"path":765,"stem":766},"Валідація, ліміти та обробка помилок","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-validation","01.csharp\u002F11.aspnet\u002F02.api\u002F08.api-design-validation",{"title":768,"path":769,"stem":770},"Обробка помилок у Minimal API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Ferror-handling-http","01.csharp\u002F11.aspnet\u002F02.api\u002F09.error-handling-http",{"title":772,"path":773,"stem":774},"Ідемпотентність та синхронізація стану","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fidempotency-sync","01.csharp\u002F11.aspnet\u002F02.api\u002F10.idempotency-sync",{"title":776,"path":777,"stem":778},"Пагінація та організація списків","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fpagination-lists","01.csharp\u002F11.aspnet\u002F02.api\u002F11.pagination-lists",{"title":780,"path":781,"stem":782},"Безпека API, кешування та інтернаціоналізація","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fsecurity-auth","01.csharp\u002F11.aspnet\u002F02.api\u002F12.security-auth",{"title":784,"path":785,"stem":786},"Процес проєктування API та документування","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-process","01.csharp\u002F11.aspnet\u002F02.api\u002F13.api-design-process",{"title":788,"path":789,"stem":790},"OpenAPI: контракт, специфікація та документація API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fopenapi","01.csharp\u002F11.aspnet\u002F02.api\u002F14.openapi",{"title":792,"icon":793,"path":794,"stem":795,"children":796,"page":59},"Auth","i-lucide-shield-check","\u002Fcsharp\u002Faspnet\u002Fauth","01.csharp\u002F11.aspnet\u002F03.auth",[797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865],{"title":798,"path":799,"stem":800},"Основи аутентифікації та авторизації","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauth-fundamentals","01.csharp\u002F11.aspnet\u002F03.auth\u002F01.auth-fundamentals",{"title":802,"path":803,"stem":804},"JWT-аутентифікація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fjwt-authentication","01.csharp\u002F11.aspnet\u002F03.auth\u002F02.jwt-authentication",{"title":806,"path":807,"stem":808},"Авторизація: ролі, політики та resource-based доступ","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauthorization-policies","01.csharp\u002F11.aspnet\u002F03.auth\u002F03.authorization-policies",{"title":810,"path":811,"stem":812},"Cookie-аутентифікація та ASP.NET Core Identity","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcookie-auth-identity","01.csharp\u002F11.aspnet\u002F03.auth\u002F04.cookie-auth-identity",{"title":814,"path":815,"stem":816},"JWT + Refresh Tokens (HttpOnly Cookie)","\u002Fcsharp\u002Faspnet\u002Fauth\u002F04b.identity-auth-jwt","01.csharp\u002F11.aspnet\u002F03.auth\u002F04b.identity-auth-jwt",{"title":818,"path":819,"stem":820},"Identity: Підтвердження Email та Скидання Пароля","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-email-confirmation","01.csharp\u002F11.aspnet\u002F03.auth\u002F05.identity-email-confirmation",{"title":822,"path":823,"stem":824},"Identity: Двофакторна Аутентифікація (2FA)","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-two-factor","01.csharp\u002F11.aspnet\u002F03.auth\u002F06.identity-two-factor",{"title":826,"path":827,"stem":828},"Identity: Внутрішня Архітектура та Кастомізація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-internals","01.csharp\u002F11.aspnet\u002F03.auth\u002F07.identity-internals",{"title":830,"path":831,"stem":832},"OAuth 2.0 та зовнішні провайдери","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-external-providers","01.csharp\u002F11.aspnet\u002F03.auth\u002F08.oauth-external-providers",{"title":834,"path":835,"stem":836},"Безпека на практиці: CORS, HTTPS та захист від атак","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fsecurity-hardening","01.csharp\u002F11.aspnet\u002F03.auth\u002F09.security-hardening",{"title":838,"path":839,"stem":840},"Теорія OAuth 2.0: Поняття, Аналогії та Флоу","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-theory","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oauth-theory",{"title":842,"path":843,"stem":844},"OIDC, OAuth 2.0 та Keycloak в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foidc-keycloak","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oidc-keycloak",{"title":846,"path":847,"stem":848},"API Keys аутентифікація в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fapi-keys","01.csharp\u002F11.aspnet\u002F03.auth\u002F11.api-keys",{"title":850,"path":851,"stem":852},"Rate Limiting та Throttling в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frate-limiting","01.csharp\u002F11.aspnet\u002F03.auth\u002F12.rate-limiting",{"title":854,"path":855,"stem":856},"Refresh Token Rotation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frefresh-token-rotation","01.csharp\u002F11.aspnet\u002F03.auth\u002F13.refresh-token-rotation",{"title":858,"path":859,"stem":860},"Certificate Authentication та mTLS в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcertificate-auth","01.csharp\u002F11.aspnet\u002F03.auth\u002F14.certificate-auth",{"title":862,"path":863,"stem":864},"RBAC, ABAC та ReBAC в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frbac-abac-rebac","01.csharp\u002F11.aspnet\u002F03.auth\u002F15.rbac-abac-rebac",{"title":866,"path":867,"stem":868},"Multi-tenancy та ізоляція даних в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fmulti-tenancy","01.csharp\u002F11.aspnet\u002F03.auth\u002F16.multi-tenancy",{"title":870,"icon":871,"path":872,"stem":873,"children":874,"page":59},"Нотифікації","i-lucide-bell","\u002Fcsharp\u002Faspnet\u002Fnotifications","01.csharp\u002F11.aspnet\u002F04.notifications",[875,879,883,887,891,895,899,903,907,911,915,919,923],{"title":876,"path":877,"stem":878},"In-App нотифікації через базу даних","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fin-app-database-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F01.in-app-database-notifications",{"title":880,"path":881,"stem":882},"Polling: Регулярний запит оновлень","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fpolling","01.csharp\u002F11.aspnet\u002F04.notifications\u002F02.polling",{"title":884,"path":885,"stem":886},"Server-Sent Events: Однострімовий push від сервера","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fserver-sent-events","01.csharp\u002F11.aspnet\u002F04.notifications\u002F03.server-sent-events",{"title":888,"path":889,"stem":890},"WebSockets: Двостороннє з'єднання в реальному часі","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fwebsockets","01.csharp\u002F11.aspnet\u002F04.notifications\u002F04.websockets",{"title":892,"path":893,"stem":894},"SignalR: Абстракція над транспортами реального часу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fsignalr","01.csharp\u002F11.aspnet\u002F04.notifications\u002F05.signalr",{"title":896,"path":897,"stem":898},"Background Services: Фонові задачі в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fbackground-services","01.csharp\u002F11.aspnet\u002F04.notifications\u002F06.background-services",{"title":900,"path":901,"stem":902},"Web Push нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fweb-push","01.csharp\u002F11.aspnet\u002F04.notifications\u002F07.web-push",{"title":904,"path":905,"stem":906},"Email нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Femail-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F08.email-notifications",{"title":908,"path":909,"stem":910},"Порівняння підходів: Як вибрати правильну технологію нотифікацій","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fchoosing-the-right-approach","01.csharp\u002F11.aspnet\u002F04.notifications\u002F09.choosing-the-right-approach",{"title":912,"path":913,"stem":914},"Hangfire: Надійне планування фонових задач","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire","01.csharp\u002F11.aspnet\u002F04.notifications\u002F10.hangfire",{"title":916,"path":917,"stem":918},"Практика: Конвертація зображень у WebP через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-image-webp","01.csharp\u002F11.aspnet\u002F04.notifications\u002F11.hangfire-image-webp",{"title":920,"path":921,"stem":922},"Практика: Підготовка відео до HLS-стрімінгу через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-video-hls","01.csharp\u002F11.aspnet\u002F04.notifications\u002F12.hangfire-video-hls",{"title":924,"path":925,"stem":926},"Telegram-нотифікації: від одного повідомлення до масових розсилок і мульти-канального підходу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Ftelegram-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F13.telegram-notifications",{"title":928,"icon":929,"path":930,"stem":931,"children":932,"page":59},"Інтернаціоналізація","i-lucide-languages","\u002Fcsharp\u002Faspnet\u002Fi18n","01.csharp\u002F11.aspnet\u002F05.i18n",[933,937],{"title":934,"path":935,"stem":936},"Інтернаціоналізація (i18n) у Minimal API: від A до Я","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Finternationalization","01.csharp\u002F11.aspnet\u002F05.i18n\u002F01.internationalization",{"title":938,"path":939,"stem":940},"Humanizer: людиномовні рядки у .NET","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Fhumanizer","01.csharp\u002F11.aspnet\u002F05.i18n\u002F02.humanizer",{"title":942,"icon":943,"path":944,"stem":945,"children":946,"page":59},"Кешування","i-lucide-layers","\u002Fcsharp\u002Faspnet\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching",[947,951,955,959,963],{"title":948,"path":949,"stem":950},"Огляд кешування: чотири рівні і коли що обирати","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching\u002F01.caching",{"title":952,"path":953,"stem":954},"IMemoryCache: кеш в оперативній пам'яті","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fmemory-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F02.memory-cache",{"title":956,"path":957,"stem":958},"IDistributedCache і Redis: розподілений кеш","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fdistributed-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F03.distributed-cache",{"title":960,"path":961,"stem":962},"Response Cache: HTTP-кешування через Cache-Control","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fresponse-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F04.response-cache",{"title":964,"path":965,"stem":966},"Output Cache: серверний кеш HTTP-відповідей (.NET 7+)","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Foutput-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F05.output-cache",{"title":968,"icon":969,"path":970,"stem":971,"children":972,"page":59},"Тестування","i-lucide-test-tube","\u002Fcsharp\u002Faspnet\u002Ftesting","01.csharp\u002F11.aspnet\u002F07.testing",[973,977,981,985,989,993,997,1001,1005,1009,1013,1017,1021,1025,1029,1033,1037,1041,1045,1049,1053],{"title":974,"path":975,"stem":976},"Що таке тестування? Від інтуїції до науки","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-is-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F01.what-is-testing",{"title":978,"path":979,"stem":980},"Піраміда тестування — Стратегія, а не Догма","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-pyramid","01.csharp\u002F11.aspnet\u002F07.testing\u002F02.testing-pyramid",{"title":982,"path":983,"stem":984},"Дві Школи Тестування — Лондон проти Детройту","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-schools","01.csharp\u002F11.aspnet\u002F07.testing\u002F03.testing-schools",{"title":986,"path":987,"stem":988},"TDD та BDD — Тести як Дизайн-інструмент","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftdd-and-bdd","01.csharp\u002F11.aspnet\u002F07.testing\u002F04.tdd-and-bdd",{"title":990,"path":991,"stem":992},"Що саме тестувати — Техніки аналізу та Циклomatична складність","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-to-test","01.csharp\u002F11.aspnet\u002F07.testing\u002F05.what-to-test",{"title":994,"path":995,"stem":996},"Тестові Фреймворки — Навіщо вони і що всередині","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftest-frameworks","01.csharp\u002F11.aspnet\u002F07.testing\u002F06.test-frameworks",{"title":998,"path":999,"stem":1000},"xUnit — Факти, Теорії та Lifecycle тестів","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-basics","01.csharp\u002F11.aspnet\u002F07.testing\u002F07.xunit-basics",{"title":1002,"path":1003,"stem":1004},"xUnit Advanced — Fixtures, Кастомізація та Розширення","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F08.xunit-advanced",{"title":1006,"path":1007,"stem":1008},"Moq — Глибоке занурення в мокування","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fmocking-with-moq","01.csharp\u002F11.aspnet\u002F07.testing\u002F09.mocking-with-moq",{"title":1010,"path":1011,"stem":1012},"Тестування Баз Даних — EF Core, SQLite та Testcontainers","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fdatabase-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F10.database-testing",{"title":1014,"path":1015,"stem":1016},"Integration Testing — Частина 1 [Теорія та WebApplicationFactory]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F11.integration-testing",{"title":1018,"path":1019,"stem":1020},"Інтеграційне тестування — Практика","\u002Fcsharp\u002Faspnet\u002Ftesting\u002F11a.integration-testing-practice","01.csharp\u002F11.aspnet\u002F07.testing\u002F11a.integration-testing-practice",{"title":1022,"path":1023,"stem":1024},"Integration Testing — Частина 2 [Просунуті Сценарії та Testcontainers]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F12.integration-testing-advanced",{"title":1026,"path":1027,"stem":1028},"Професійний Postman: Колекції, Змінні та GitHub Інтеграція","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fpostman-professional","01.csharp\u002F11.aspnet\u002F07.testing\u002F13.postman-professional",{"title":1030,"path":1031,"stem":1032},"HttpClient у Тестах Частина 1: Архітектура та MockHttpMessageHandler","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fhttpclient-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F14.httpclient-testing",{"title":1034,"path":1035,"stem":1036},"HttpClient у Тестах Частина 2: WireMock.Net та Resilience","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwiremock-net","01.csharp\u002F11.aspnet\u002F07.testing\u002F15.wiremock-net",{"title":1038,"path":1039,"stem":1040},"Патерни та Анти-патерни Тестування: Test Smells","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-patterns","01.csharp\u002F11.aspnet\u002F07.testing\u002F16.testing-patterns",{"title":1042,"path":1043,"stem":1044},"Просунуті інструменти: Time, Snapshots та Властивості","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fadvanced-testing-tools","01.csharp\u002F11.aspnet\u002F07.testing\u002F17.advanced-testing-tools",{"title":1046,"path":1047,"stem":1048},"Тестування Архітектури з NetArchTest","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Farchitecture-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F18.architecture-testing",{"title":1050,"path":1051,"stem":1052},"Тестування Продуктивності: BenchmarkDotNet, NBomber та k6","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fperformance-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F19.performance-testing",{"title":1054,"path":1055,"stem":1056},"Залишок плану для курсу \"Тестування ASP.NET Minimal API\"","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fremaining_plan","01.csharp\u002F11.aspnet\u002F07.testing\u002Fremaining_plan",{"title":1058,"icon":1059,"path":1060,"stem":1061,"children":1062,"page":59},"Платежі","i-lucide-credit-card","\u002Fcsharp\u002Faspnet\u002Fpayments","01.csharp\u002F11.aspnet\u002F08.payments",[1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103,1107],{"title":1064,"path":1065,"stem":1066},"Основи платіжної інфраструктури","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-fundamentals","01.csharp\u002F11.aspnet\u002F08.payments\u002F01.payment-fundamentals",{"title":1068,"path":1069,"stem":1070},"Методи оплати в Україні","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-methods-ukraine","01.csharp\u002F11.aspnet\u002F08.payments\u002F02.payment-methods-ukraine",{"title":1072,"path":1073,"stem":1074},"PCI DSS та безпека платежів","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpci-dss-security","01.csharp\u002F11.aspnet\u002F08.payments\u002F03.pci-dss-security",{"title":1076,"path":1077,"stem":1078},"Архітектура платіжної підсистеми","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-architecture","01.csharp\u002F11.aspnet\u002F08.payments\u002F04.payment-architecture",{"title":1080,"path":1081,"stem":1082},"Інтеграція LiqPay (ПриватБанк)","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fliqpay-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F05.liqpay-integration",{"title":1084,"path":1085,"stem":1086},"Інтеграція Monobank Acquiring API","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fmonobank-acquiring","01.csharp\u002F11.aspnet\u002F08.payments\u002F06.monobank-acquiring",{"title":1088,"path":1089,"stem":1090},"Інтеграція Stripe","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fstripe-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F07.stripe-integration",{"title":1092,"path":1093,"stem":1094},"Webhooks — глибоке занурення","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fwebhooks-deep-dive","01.csharp\u002F11.aspnet\u002F08.payments\u002F08.webhooks-deep-dive",{"title":1096,"path":1097,"stem":1098},"Підписки та рекурентні платежі","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fsubscriptions-recurring","01.csharp\u002F11.aspnet\u002F08.payments\u002F09.subscriptions-recurring",{"title":1100,"path":1101,"stem":1102},"Повернення коштів та диспути","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Frefunds-disputes","01.csharp\u002F11.aspnet\u002F08.payments\u002F10.refunds-disputes",{"title":1104,"path":1105,"stem":1106},"Тестування платіжних інтеграцій","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Ftesting-payments","01.csharp\u002F11.aspnet\u002F08.payments\u002F11.testing-payments",{"title":1108,"path":1109,"stem":1110},"Чекліст виходу в Production","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fproduction-checklist","01.csharp\u002F11.aspnet\u002F08.payments\u002F12.production-checklist",{"title":1112,"icon":1113,"items":1114,"path":1127,"stem":1128,"children":1129,"page":59},"Популярні бібліотеки","lucide:box",[1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126],"01.fluent-validation","02.mapster","03.erroror-result-pattern","04.serilog","05.mediatr","06.polly","07.health-checks","08.feature-management","09.fluent-email","10.quest-pdf","11.bogus","12.humanizer-guard","\u002Fcsharp\u002Faspnet\u002Flibraries","01.csharp\u002F11.aspnet\u002F09.libraries",[1130,1134,1138,1142,1146,1150,1154,1158,1162,1166,1170,1174,1178],{"title":1131,"path":1132,"stem":1133},"Валідація з FluentValidation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-validation","01.csharp\u002F11.aspnet\u002F09.libraries\u002F01.fluent-validation",{"title":1135,"path":1136,"stem":1137},"Маппінг об","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmapster","01.csharp\u002F11.aspnet\u002F09.libraries\u002F02.mapster",{"title":1139,"path":1140,"stem":1141},"Обробка помилок з ErrorOr та Result Pattern в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ferroror-result-pattern","01.csharp\u002F11.aspnet\u002F09.libraries\u002F03.erroror-result-pattern",{"title":1143,"path":1144,"stem":1145},"Структуроване логування з Serilog в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fserilog","01.csharp\u002F11.aspnet\u002F09.libraries\u002F04.serilog",{"title":1147,"path":1148,"stem":1149},"CQRS та Mediator з MediatR в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmediatr","01.csharp\u002F11.aspnet\u002F09.libraries\u002F05.mediatr",{"title":1151,"path":1152,"stem":1153},"Відмовостійкість з Polly в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fpolly","01.csharp\u002F11.aspnet\u002F09.libraries\u002F06.polly",{"title":1155,"path":1156,"stem":1157},"Health Checks в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F09.libraries\u002F07.health-checks",{"title":1159,"path":1160,"stem":1161},"Feature Management та Feature Flags в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffeature-management","01.csharp\u002F11.aspnet\u002F09.libraries\u002F08.feature-management",{"title":1163,"path":1164,"stem":1165},"Відправка Email з FluentEmail в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-email","01.csharp\u002F11.aspnet\u002F09.libraries\u002F09.fluent-email",{"title":1167,"path":1168,"stem":1169},"Генерація PDF з QuestPDF в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fquest-pdf","01.csharp\u002F11.aspnet\u002F09.libraries\u002F10.quest-pdf",{"title":1171,"path":1172,"stem":1173},"Генерація тестових даних з Bogus в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fbogus","01.csharp\u002F11.aspnet\u002F09.libraries\u002F11.bogus",{"title":1175,"path":1176,"stem":1177},"Humanizer та Guard Clauses в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhumanizer-guard","01.csharp\u002F11.aspnet\u002F09.libraries\u002F12.humanizer-guard",{"title":1179,"path":1180,"stem":1181},"План модуля 10.libraries — Популярні бібліотеки ASP.NET","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fplan","01.csharp\u002F11.aspnet\u002F09.libraries\u002Fplan",{"title":1183,"icon":1184,"path":1185,"stem":1186,"children":1187,"page":59},"Razor Pages","i-lucide-layout-template","\u002Fcsharp\u002Faspnet\u002Frazor-pages","01.csharp\u002F11.aspnet\u002F10.razor-pages",[1188,1192,1196,1200,1204,1208],{"title":1189,"path":1190,"stem":1191},"Від Minimal API до Razor Pages: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ffrom-minimal-api","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F01.from-minimal-api",{"title":1193,"path":1194,"stem":1195},"PageModel: логіка сторінки Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fpage-model","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F02.page-model",{"title":1197,"path":1198,"stem":1199},"Razor синтаксис: шаблонізатор у .cshtml","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Frazor-syntax","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F03.razor-syntax",{"title":1201,"path":1202,"stem":1203},"Tag Helpers: типізований HTML","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ftag-helpers","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F04.tag-helpers",{"title":1205,"path":1206,"stem":1207},"Форми і валідація: повний цикл обробки даних","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fforms-validation","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F05.forms-validation",{"title":1209,"path":1210,"stem":1211},"Практичний проєкт: TaskManager на Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fproject-task-manager","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F06.project-task-manager",{"title":1213,"path":1214,"stem":1215,"children":1216,"page":59},"ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc","01.csharp\u002F11.aspnet\u002F11.mvc",[1217,1221,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269,1273,1277,1281,1285],{"title":1218,"path":1219,"stem":1220},"Патерн MVC: архітектура, що змінила веб","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-pattern","01.csharp\u002F11.aspnet\u002F11.mvc\u002F01.mvc-pattern",{"title":1222,"path":1223,"stem":1224},"Від Razor Pages до MVC: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffrom-razor-pages","01.csharp\u002F11.aspnet\u002F11.mvc\u002F02.from-razor-pages",{"title":1226,"path":1227,"stem":1228},"Controllers та Actions: серце MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fcontrollers-actions","01.csharp\u002F11.aspnet\u002F11.mvc\u002F03.controllers-actions",{"title":1230,"path":1231,"stem":1232},"Маршрутизація в MVC: Convention vs Attribute Routing","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Frouting-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F04.routing-mvc",{"title":1234,"path":1235,"stem":1236},"Model Binding: від HTTP до C#","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmodel-binding","01.csharp\u002F11.aspnet\u002F11.mvc\u002F05.model-binding",{"title":1238,"path":1239,"stem":1240},"Views, ViewData, ViewBag, TempData і ViewModel","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fviews-viewdata-tempdata","01.csharp\u002F11.aspnet\u002F11.mvc\u002F06.views-viewdata-tempdata",{"title":1242,"path":1243,"stem":1244},"Filters: аспектно-орієнтоване програмування в MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffilters","01.csharp\u002F11.aspnet\u002F11.mvc\u002F07.filters",{"title":1246,"path":1247,"stem":1248},"Areas: структурування великих застосунків","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fareas","01.csharp\u002F11.aspnet\u002F11.mvc\u002F08.areas",{"title":1250,"path":1251,"stem":1252},"View Components: повторювані незалежні блоки UI","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fview-components","01.csharp\u002F11.aspnet\u002F11.mvc\u002F09.view-components",{"title":1254,"path":1255,"stem":1256},"Display та Editor Templates","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fdisplay-editor-templates","01.csharp\u002F11.aspnet\u002F11.mvc\u002F10.display-editor-templates",{"title":1258,"path":1259,"stem":1260},"Валідація: IValidatableObject та FluentValidation","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fvalidation-advanced","01.csharp\u002F11.aspnet\u002F11.mvc\u002F11.validation-advanced",{"title":1262,"path":1263,"stem":1264},"HTMX: інтерактивність через HTML-атрибути","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx","01.csharp\u002F11.aspnet\u002F11.mvc\u002F12.htmx",{"title":1266,"path":1267,"stem":1268},"HTMX у ASP.NET Core MVC: серверна інтеграція","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fajax-htmx-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F13.ajax-htmx-mvc",{"title":1270,"path":1271,"stem":1272},"Практичний проєкт: Каталог товарів з HTMX","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F14.htmx-project",{"title":1274,"path":1275,"stem":1276},"Завантаження та обробка файлів","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffile-upload","01.csharp\u002F11.aspnet\u002F11.mvc\u002F15.file-upload",{"title":1278,"path":1279,"stem":1280},"Глобалізація та Локалізація MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fglobalization-localization","01.csharp\u002F11.aspnet\u002F11.mvc\u002F16.globalization-localization",{"title":1282,"path":1283,"stem":1284},"Підсумковий проєкт: Блог-платформа","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F17.mvc-project",{"title":1286,"path":1287,"stem":1288},"План курсу: ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fplan","01.csharp\u002F11.aspnet\u002F11.mvc\u002Fplan",{"title":1290,"path":1291,"stem":1292,"children":1293,"page":59},"Web Api","\u002Fcsharp\u002Faspnet\u002Fweb-api","01.csharp\u002F11.aspnet\u002F12.web-api",[1294,1298,1302,1306,1310,1314,1318,1322,1326,1330,1334,1338,1342],{"title":1295,"path":1296,"stem":1297},"Від Minimal API до Controller-based API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffrom-minimal-api-to-controllers","01.csharp\u002F11.aspnet\u002F12.web-api\u002F01.from-minimal-api-to-controllers",{"title":1299,"path":1300,"stem":1301},"ControllerBase, ActionResult\u003CT> та Response Types","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontroller-base-actionresult","01.csharp\u002F11.aspnet\u002F12.web-api\u002F02.controller-base-actionresult",{"title":1303,"path":1304,"stem":1305},"Content Negotiation - JSON, XML та власні форматери","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontent-negotiation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F03.content-negotiation",{"title":1307,"path":1308,"stem":1309},"Версіонування API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-versioning","01.csharp\u002F11.aspnet\u002F12.web-api\u002F04.api-versioning",{"title":1311,"path":1312,"stem":1313},"ProblemDetails та структурована обробка помилок","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fproblemdetails-error-handling","01.csharp\u002F11.aspnet\u002F12.web-api\u002F05.problemdetails-error-handling",{"title":1315,"path":1316,"stem":1317},"Фільтри у Web API контексті","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffilters-for-api","01.csharp\u002F11.aspnet\u002F12.web-api\u002F06.filters-for-api",{"title":1319,"path":1320,"stem":1321},"Пагінація, фільтрація та сортування","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fpagination-filtering-sorting","01.csharp\u002F11.aspnet\u002F12.web-api\u002F07.pagination-filtering-sorting",{"title":1323,"path":1324,"stem":1325},"HATEOAS та Resource Expansion","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhateoas-resource-expansion","01.csharp\u002F11.aspnet\u002F12.web-api\u002F08.hateoas-resource-expansion",{"title":1327,"path":1328,"stem":1329},"Гібридна архітектура - Minimal API + Controllers","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fminimal-api-vs-controllers-hybrid","01.csharp\u002F11.aspnet\u002F12.web-api\u002F09.minimal-api-vs-controllers-hybrid",{"title":1331,"path":1332,"stem":1333},"Документація API - Swashbuckle, NSwag та генерація клієнтів","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-documentation-generation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F10.api-documentation-generation",{"title":1335,"path":1336,"stem":1337},"Health Checks та моніторинг API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhealth-checks-monitoring","01.csharp\u002F11.aspnet\u002F12.web-api\u002F11.health-checks-monitoring",{"title":1339,"path":1340,"stem":1341},"Підсумковий проєкт - Production-Ready REST API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fweb-api-project","01.csharp\u002F11.aspnet\u002F12.web-api\u002F12.web-api-project",{"title":1343,"path":1344,"stem":1345},"План курсу: ASP.NET Core Web API (Controllers)","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fplan","01.csharp\u002F11.aspnet\u002F12.web-api\u002Fplan",{"title":1347,"icon":1348,"path":1349,"stem":1350,"children":1351,"page":59},"Моніторинг","i-lucide-activity","\u002Fcsharp\u002Faspnet\u002Fmonitoring","01.csharp\u002F11.aspnet\u002F13.monitoring",[1352,1356,1360],{"title":1353,"path":1354,"stem":1355},"Спостережуваність: від console.log до production-систем","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fobservability-intro","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F01.observability-intro",{"title":1357,"path":1358,"stem":1359},"Health Checks: перший рівень observability","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F02.health-checks",{"title":1361,"path":1362,"stem":1363},"Вбудовані метрики .NET 10 та System.Diagnostics.Metrics","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fdotnet-metrics","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F03.dotnet-metrics",{"title":1365,"icon":1366,"path":1367,"stem":1368,"children":1369,"page":59},"Desktop UI","i-lucide-app-window","\u002Fcsharp\u002Fdesktop-ui","01.csharp\u002F12.desktop-ui",[1370,1374,1378,1382,1386,1390,1394,1398,1402,1406,1410,1414,1418,1422,1426,1430,1434,1438,1442,1446,1450,1454,1458,1462,1466,1470,1474,1478,1482,1486,1490,1494,1498,1502,1506,1510,1514,1518,1522,1526,1530,1534,1538,1542,1546,1550,1554,1558,1562,1566,1570,1574,1578,1582,1586,1590,1594,1598,1602,1606,1610,1614,1618,1622,1626,1630,1634,1638,1642,1646,1650],{"title":1371,"path":1372,"stem":1373},"Що таке десктопна розробка?","\u002Fcsharp\u002Fdesktop-ui\u002Fwhat-is-desktop-dev","01.csharp\u002F12.desktop-ui\u002F01.what-is-desktop-dev",{"title":1375,"path":1376,"stem":1377},"Архітектура WPF — як влаштований графічний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-architecture","01.csharp\u002F12.desktop-ui\u002F02.wpf-architecture",{"title":1379,"path":1380,"stem":1381},"Перший WPF-проєкт — від нуля до вікна","\u002Fcsharp\u002Fdesktop-ui\u002Ffirst-wpf-app","01.csharp\u002F12.desktop-ui\u002F03.first-wpf-app",{"title":1383,"path":1384,"stem":1385},"Перший Avalonia-проєкт: WPF для всіх платформ","\u002Fcsharp\u002Fdesktop-ui\u002F03a.first-avalonia-app","01.csharp\u002F12.desktop-ui\u002F03a.first-avalonia-app",{"title":1387,"path":1388,"stem":1389},"XAML: декларативний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-basics","01.csharp\u002F12.desktop-ui\u002F04.xaml-basics",{"title":1391,"path":1392,"stem":1393},"Fluent UI у WPF — сучасний дизайн Windows 11","\u002Fcsharp\u002Fdesktop-ui\u002F04a.wpf-fluent-ui","01.csharp\u002F12.desktop-ui\u002F04a.wpf-fluent-ui",{"title":1395,"path":1396,"stem":1397},"WPF UI — сучасна бібліотека Fluent контролів","\u002Fcsharp\u002Fdesktop-ui\u002F04b.wpf-ui-library","01.csharp\u002F12.desktop-ui\u002F04b.wpf-ui-library",{"title":1399,"path":1400,"stem":1401},"HandyControl — велика бібліотека UI контролів для WPF","\u002Fcsharp\u002Fdesktop-ui\u002F04c.handycontrol-library","01.csharp\u002F12.desktop-ui\u002F04c.handycontrol-library",{"title":1403,"path":1404,"stem":1405},"Простори імен та ресурси XAML","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-namespaces-resources","01.csharp\u002F12.desktop-ui\u002F05.xaml-namespaces-resources",{"title":1407,"path":1408,"stem":1409},"XAML в Avalonia: ключові відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F05a.avalonia-xaml-differences","01.csharp\u002F12.desktop-ui\u002F05a.avalonia-xaml-differences",{"title":1411,"path":1412,"stem":1413},"Розширення розмітки XAML (Markup Extensions)","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-markup-extensions","01.csharp\u002F12.desktop-ui\u002F06.xaml-markup-extensions",{"title":1415,"path":1416,"stem":1417},"Панелі Layout: StackPanel, WrapPanel, DockPanel","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part1","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part1",{"title":1419,"path":1420,"stem":1421},"Grid, Canvas, UniformGrid","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part2","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part2",{"title":1423,"path":1424,"stem":1425},"Просунуті техніки Layout","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-advanced","01.csharp\u002F12.desktop-ui\u002F08.layout-advanced",{"title":1427,"path":1428,"stem":1429},"Адаптивний Layout та найкращі практики","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-responsive","01.csharp\u002F12.desktop-ui\u002F09.layout-responsive",{"title":1431,"path":1432,"stem":1433},"Layout в Avalonia: відмінності та нові можливості","\u002Fcsharp\u002Fdesktop-ui\u002F09a.layout-avalonia","01.csharp\u002F12.desktop-ui\u002F09a.layout-avalonia",{"title":1435,"path":1436,"stem":1437},"Button, Image, ProgressBar та інші базові контроли","\u002Fcsharp\u002Fdesktop-ui\u002Fbasic-controls","01.csharp\u002F12.desktop-ui\u002F10.basic-controls",{"title":1439,"path":1440,"stem":1441},"Контроли в Avalonia: відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F10a.controls-avalonia","01.csharp\u002F12.desktop-ui\u002F10a.controls-avalonia",{"title":1443,"path":1444,"stem":1445},"Текстові контроли — TextBlock, TextBox, RichTextBox","\u002Fcsharp\u002Fdesktop-ui\u002Ftext-controls","01.csharp\u002F12.desktop-ui\u002F11.text-controls",{"title":1447,"path":1448,"stem":1449},"Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker","\u002Fcsharp\u002Fdesktop-ui\u002Fselection-controls","01.csharp\u002F12.desktop-ui\u002F12.selection-controls",{"title":1451,"path":1452,"stem":1453},"Content Model — GroupBox, Expander, TabControl, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fcontent-controls","01.csharp\u002F12.desktop-ui\u002F13.content-controls",{"title":1455,"path":1456,"stem":1457},"UI\u002FUX принципи десктопних застосунків","\u002Fcsharp\u002Fdesktop-ui\u002F13a.ui-ux-principles","01.csharp\u002F12.desktop-ui\u002F13a.ui-ux-principles",{"title":1459,"path":1460,"stem":1461},"Dependency Properties — Концепція та Value Resolution","\u002Fcsharp\u002Fdesktop-ui\u002Fdependency-properties-part1","01.csharp\u002F12.desktop-ui\u002F14.dependency-properties-part1",{"title":1463,"path":1464,"stem":1465},"Avalonia Property System — StyledProperty та DirectProperty","\u002Fcsharp\u002Fdesktop-ui\u002F14a.avalonia-property-system","01.csharp\u002F12.desktop-ui\u002F14a.avalonia-property-system",{"title":1467,"path":1468,"stem":1469},"Attached Properties — Властивості без меж","\u002Fcsharp\u002Fdesktop-ui\u002Fattached-properties","01.csharp\u002F12.desktop-ui\u002F15.attached-properties",{"title":1471,"path":1472,"stem":1473},"Routed Events — Маршрутизація подій у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Frouted-events","01.csharp\u002F12.desktop-ui\u002F16.routed-events",{"title":1475,"path":1476,"stem":1477},"Data Binding — Від Code-Behind до Декларативності","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part1","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part1",{"title":1479,"path":1480,"stem":1481},"INotifyPropertyChanged — Живе оновлення UI","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part2","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part2",{"title":1483,"path":1484,"stem":1485},"Compiled Bindings в Avalonia — Безпека на етапі компіляції","\u002Fcsharp\u002Fdesktop-ui\u002F17a.avalonia-compiled-bindings","01.csharp\u002F12.desktop-ui\u002F17a.avalonia-compiled-bindings",{"title":1487,"path":1488,"stem":1489},"Просунутий Data Binding — ElementName, RelativeSource, MultiBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-advanced","01.csharp\u002F12.desktop-ui\u002F18.data-binding-advanced",{"title":1491,"path":1492,"stem":1493},"Value Converters — Перетворення типів даних у Data Binding","\u002Fcsharp\u002Fdesktop-ui\u002Fvalue-converters","01.csharp\u002F12.desktop-ui\u002F19.value-converters",{"title":1495,"path":1496,"stem":1497},"Data Templates — Візуалізація об'єктів у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-templates","01.csharp\u002F12.desktop-ui\u002F20.data-templates",{"title":1499,"path":1500,"stem":1501},"Collections Binding Part 1 — ObservableCollection та ItemsControl","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part1","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part1",{"title":1503,"path":1504,"stem":1505},"Collections Binding Part 2 — ICollectionView, Filtering, Sorting та Virtualization","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part2","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part2",{"title":1507,"path":1508,"stem":1509},"MVVM Pattern — Від Spaghetti Code до архітектури","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-pattern","01.csharp\u002F12.desktop-ui\u002F22.mvvm-pattern",{"title":1511,"path":1512,"stem":1513},"ViewModel Implementation — Від BaseViewModel до валідації","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-implementation","01.csharp\u002F12.desktop-ui\u002F23.viewmodel-implementation",{"title":1515,"path":1516,"stem":1517},"Commands — Від event handlers до декларативних команд","\u002Fcsharp\u002Fdesktop-ui\u002Fcommands","01.csharp\u002F12.desktop-ui\u002F24.commands",{"title":1519,"path":1520,"stem":1521},"MVVM Toolkit — MVVM без boilerplate через Source Generators","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-toolkit","01.csharp\u002F12.desktop-ui\u002F25.mvvm-toolkit",{"title":1523,"path":1524,"stem":1525},"Messenger Pattern — Комунікація між ViewModel без прямих посилань","\u002Fcsharp\u002Fdesktop-ui\u002Fmessenger-pattern","01.csharp\u002F12.desktop-ui\u002F26.messenger-pattern",{"title":1527,"path":1528,"stem":1529},"Стилі WPF — CSS для десктопу","\u002Fcsharp\u002Fdesktop-ui\u002Fstyles-basics","01.csharp\u002F12.desktop-ui\u002F27.styles-basics",{"title":1531,"path":1532,"stem":1533},"CSS-like стилі Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F27a.avalonia-css-styling","01.csharp\u002F12.desktop-ui\u002F27a.avalonia-css-styling",{"title":1535,"path":1536,"stem":1537},"Control Templates — Частина 1. Концепція та TemplateBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part1","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part1",{"title":1539,"path":1540,"stem":1541},"Control Templates — Частина 2. Named Parts та ContentPresenter","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part2","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part2",{"title":1543,"path":1544,"stem":1545},"Control Themes в Avalonia — нова ера стилізації","\u002Fcsharp\u002Fdesktop-ui\u002F28a.avalonia-control-themes","01.csharp\u002F12.desktop-ui\u002F28a.avalonia-control-themes",{"title":1547,"path":1548,"stem":1549},"Triggers та Visual State Manager у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Ftriggers-visual-states","01.csharp\u002F12.desktop-ui\u002F29.triggers-visual-states",{"title":1551,"path":1552,"stem":1553},"Pseudo-classes в Avalonia — замість WPF Triggers","\u002Fcsharp\u002Fdesktop-ui\u002F29a.avalonia-pseudo-classes","01.csharp\u002F12.desktop-ui\u002F29a.avalonia-pseudo-classes",{"title":1555,"path":1556,"stem":1557},"Теми та ресурсні словники у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fresources-themes","01.csharp\u002F12.desktop-ui\u002F30.resources-themes",{"title":1559,"path":1560,"stem":1561},"Avalonia Themes — Fluent Design та система тематизації","\u002Fcsharp\u002Fdesktop-ui\u002F30a.avalonia-themes-fluent","01.csharp\u002F12.desktop-ui\u002F30a.avalonia-themes-fluent",{"title":1563,"path":1564,"stem":1565},"Контроли колекцій — глибоке занурення","\u002Fcsharp\u002Fdesktop-ui\u002Fcollection-controls","01.csharp\u002F12.desktop-ui\u002F31.collection-controls",{"title":1567,"path":1568,"stem":1569},"DataGrid — колонки та базове відображення","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part1","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part1",{"title":1571,"path":1572,"stem":1573},"DataGrid — сортування, фільтрація, редагування","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part2","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part2",{"title":1575,"path":1576,"stem":1577},"TreeView та GridView","\u002Fcsharp\u002Fdesktop-ui\u002Ftreeview-listview","01.csharp\u002F12.desktop-ui\u002F33.treeview-listview",{"title":1579,"path":1580,"stem":1581},"Меню, Toolbar, ContextMenu, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fmenus-toolbars","01.csharp\u002F12.desktop-ui\u002F34.menus-toolbars",{"title":1583,"path":1584,"stem":1585},"Навігація та керування вікнами. Частина 1: вікна та сторінки","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part1","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part1",{"title":1587,"path":1588,"stem":1589},"Навігація та керування вікнами. Частина 2: MVVM-навігація","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part2","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part2",{"title":1591,"path":1592,"stem":1593},"Avalonia — Навігація та діалоги","\u002Fcsharp\u002Fdesktop-ui\u002F35a.avalonia-navigation-dialogs","01.csharp\u002F12.desktop-ui\u002F35a.avalonia-navigation-dialogs",{"title":1595,"path":1596,"stem":1597},"Діалоги та File Pickers у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdialogs-file-pickers","01.csharp\u002F12.desktop-ui\u002F36.dialogs-file-pickers",{"title":1599,"path":1600,"stem":1601},"UserControl: компонентний підхід у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fuser-controls","01.csharp\u002F12.desktop-ui\u002F37.user-controls",{"title":1603,"path":1604,"stem":1605},"Custom Controls: Lookless Controls у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fcustom-controls","01.csharp\u002F12.desktop-ui\u002F38.custom-controls",{"title":1607,"path":1608,"stem":1609},"Avalonia TemplatedControl — Lookless Controls","\u002Fcsharp\u002Fdesktop-ui\u002F38a.avalonia-templated-controls","01.csharp\u002F12.desktop-ui\u002F38a.avalonia-templated-controls",{"title":1611,"path":1612,"stem":1613},"Анімації у WPF: Storyboard та Easing Functions","\u002Fcsharp\u002Fdesktop-ui\u002Fanimations-transitions","01.csharp\u002F12.desktop-ui\u002F39.animations-transitions",{"title":1615,"path":1616,"stem":1617},"Анімації в Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F39a.avalonia-animations","01.csharp\u002F12.desktop-ui\u002F39a.avalonia-animations",{"title":1619,"path":1620,"stem":1621},"2D Графіка та Мультимедіа у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fmedia-graphics","01.csharp\u002F12.desktop-ui\u002F40.media-graphics",{"title":1623,"path":1624,"stem":1625},"Dependency Injection у WPF та Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Fdi-integration","01.csharp\u002F12.desktop-ui\u002F41.di-integration",{"title":1627,"path":1628,"stem":1629},"SQLite та EF Core у десктопних додатках","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part1","01.csharp\u002F12.desktop-ui\u002F42.data-persistence-part1",{"title":1631,"path":1632,"stem":1633},"Repository Pattern та Unit of Work","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part2","01.csharp\u002F12.desktop-ui\u002F43.data-persistence-part2",{"title":1635,"path":1636,"stem":1637},"Тестування ViewModels","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-testing","01.csharp\u002F12.desktop-ui\u002F44.viewmodel-testing",{"title":1639,"path":1640,"stem":1641},"Avalonia Headless Testing — тестування UI без вікон","\u002Fcsharp\u002Fdesktop-ui\u002F44a.avalonia-headless-testing","01.csharp\u002F12.desktop-ui\u002F44a.avalonia-headless-testing",{"title":1643,"path":1644,"stem":1645},"Кросплатформна розробка з Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-cross-platform","01.csharp\u002F12.desktop-ui\u002F45.avalonia-cross-platform",{"title":1647,"path":1648,"stem":1649},"Пакування та розгортання Avalonia додатків","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F46.avalonia-packaging-deployment",{"title":1651,"path":1652,"stem":1653},"Розгортання WPF застосунків","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F47.wpf-packaging-deployment",{"title":1655,"icon":658,"path":1656,"stem":1657,"children":1658,"page":59},"Network Programming","\u002Fcsharp\u002Fnetwork-programming","01.csharp\u002F13.network-programming",[1659,1663,1667,1671,1675,1679,1683,1687,1691,1695,1699],{"title":1660,"path":1661,"stem":1662},"Основи комп'ютерних мереж","\u002Fcsharp\u002Fnetwork-programming\u002Ffoundations","01.csharp\u002F13.network-programming\u002F01.foundations",{"title":1664,"path":1665,"stem":1666},"Модель OSI та стек TCP\u002FIP","\u002Fcsharp\u002Fnetwork-programming\u002Fosi-model","01.csharp\u002F13.network-programming\u002F02.osi-model",{"title":1668,"path":1669,"stem":1670},"IP-протокол та адресація","\u002Fcsharp\u002Fnetwork-programming\u002Fip-addressing","01.csharp\u002F13.network-programming\u002F03.ip-addressing",{"title":1672,"path":1673,"stem":1674},"UDP — протокол без з'єднання","\u002Fcsharp\u002Fnetwork-programming\u002Fudp","01.csharp\u002F13.network-programming\u002F05.udp",{"title":1676,"path":1677,"stem":1678},"UDP Broadcast та Multicast","\u002Fcsharp\u002Fnetwork-programming\u002Fudp-broadcast-multicast","01.csharp\u002F13.network-programming\u002F06.udp-broadcast-multicast",{"title":1680,"path":1681,"stem":1682},"HTTP — протокол вебу","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-fundamentals","01.csharp\u002F13.network-programming\u002F07.http-fundamentals",{"title":1684,"path":1685,"stem":1686},"HttpListener — вбудований HTTP-сервер .NET","\u002Fcsharp\u002Fnetwork-programming\u002F07a.http-listener","01.csharp\u002F13.network-programming\u002F07a.http-listener",{"title":1688,"path":1689,"stem":1690},"HTTP Advanced — cookies, аутентифікація та HTTPS","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-advanced","01.csharp\u002F13.network-programming\u002F08.http-advanced",{"title":1692,"path":1693,"stem":1694},"SMTP та протоколи електронної пошти","\u002Fcsharp\u002Fnetwork-programming\u002Fsmtp","01.csharp\u002F13.network-programming\u002F09.smtp",{"title":1696,"path":1697,"stem":1698},"WebSocket — повнодуплексний протокол реального часу","\u002Fcsharp\u002Fnetwork-programming\u002Fwebsockets","01.csharp\u002F13.network-programming\u002F10.websockets",{"title":1700,"path":1701,"stem":1702},"TLS\u002FSSL — криптографічний захист мережевих з'єднань","\u002Fcsharp\u002Fnetwork-programming\u002Ftls-ssl","01.csharp\u002F13.network-programming\u002F11.tls-ssl",{"title":1704,"path":1705,"stem":1706},"C# & .NET: The Ultimate Roadmap","\u002Fcsharp\u002Froadmap","01.csharp\u002Froadmap",{"title":1708,"icon":1709,"path":1710,"stem":1711,"children":1712,"page":59},"C++","i-devicon-cplusplus","\u002Fcpp","02.cpp",[1713,1717,1721,1725,1729,1733,1737,1741,1745,1748,1752,1756,1760,1764,1768,1772,1776,1780,1784,1788,1792,1796,1800,1804,1808,1812,1816,1820,1824,1828,1832,1836,1840,1844,1848,1852,1856,1860,1864,1868,1872,1876,1880,1884,1888,1892,1896,1900,1904,1908,1912,1916,1920,1924,1928,1932,1936,1940,1944,1948,1952,1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004,2008,2012,2016,2020,2024,2028,2032,2036],{"title":1714,"path":1715,"stem":1716},"Вступ у програмування та алгоритми","\u002Fcpp\u002Fintro-algorithms","02.cpp\u002F01.intro-algorithms",{"title":1718,"path":1719,"stem":1720},"Code Style: угоди про оформлення коду","\u002Fcpp\u002Fcode-style","02.cpp\u002F02.code-style",{"title":1722,"path":1723,"stem":1724},"Середовище розробки та перший проєкт","\u002Fcpp\u002Fide-setup","02.cpp\u002F03.ide-setup",{"title":1726,"path":1727,"stem":1728},"Вивід даних на екран","\u002Fcpp\u002Fdata-output","02.cpp\u002F04.data-output",{"title":1730,"path":1731,"stem":1732},"Типи даних, змінні та константи","\u002Fcpp\u002Fdata-types-variables","02.cpp\u002F05.data-types-variables",{"title":1734,"path":1735,"stem":1736},"Ввід даних з клавіатури","\u002Fcpp\u002Fdata-input","02.cpp\u002F06.data-input",{"title":1738,"path":1739,"stem":1740},"Оператори, перетворення типів та логічні операції","\u002Fcpp\u002Foperators-type-conversion","02.cpp\u002F07.operators-type-conversion",{"title":1742,"path":1743,"stem":1744},"Цикли","\u002Fcpp\u002Floops","02.cpp\u002F08.loops",{"title":32,"path":1746,"stem":1747},"\u002Fcpp\u002Farrays","02.cpp\u002F09.arrays",{"title":1749,"path":1750,"stem":1751},"Алгоритми сортування та аналіз складності","\u002Fcpp\u002Fsorting","02.cpp\u002F10.sorting",{"title":1753,"path":1754,"stem":1755},"Алгоритми пошуку","\u002Fcpp\u002Fsearching","02.cpp\u002F11.searching",{"title":1757,"path":1758,"stem":1759},"Функції: основи","\u002Fcpp\u002Ffunctions-basics","02.cpp\u002F12.functions-basics",{"title":1761,"path":1762,"stem":1763},"Функції: прототипи, область видимості та додаткові можливості","\u002Fcpp\u002Ffunctions-scope","02.cpp\u002F13.functions-scope",{"title":1765,"path":1766,"stem":1767},"Функції: перевантаження та шаблони","\u002Fcpp\u002Ffunctions-overloading-templates","02.cpp\u002F14.functions-overloading-templates",{"title":1769,"path":1770,"stem":1771},"Вказівники: основи","\u002Fcpp\u002Fpointers-basics","02.cpp\u002F15.pointers-basics",{"title":1773,"path":1774,"stem":1775},"Посилання (References)","\u002Fcpp\u002Freferences","02.cpp\u002F16.references",{"title":1777,"path":1778,"stem":1779},"Вказівники, const і масиви","\u002Fcpp\u002Fpointers-const-arrays","02.cpp\u002F17.pointers-const-arrays",{"title":1781,"path":1782,"stem":1783},"Адресна арифметика","\u002Fcpp\u002Fpointer-arithmetic","02.cpp\u002F18.pointer-arithmetic",{"title":1785,"path":1786,"stem":1787},"Динамічна пам'ять","\u002Fcpp\u002Fdynamic-memory","02.cpp\u002F19.dynamic-memory",{"title":1789,"path":1790,"stem":1791},"Вказівники типу void","\u002Fcpp\u002Fvoid-pointers","02.cpp\u002F20.void-pointers",{"title":1793,"path":1794,"stem":1795},"Вказівники на вказівники","\u002Fcpp\u002Fpointers-to-pointers","02.cpp\u002F21.pointers-to-pointers",{"title":1797,"path":1798,"stem":1799},"Оператор доступу до членів через вказівник (->)","\u002Fcpp\u002Fmember-access-operator","02.cpp\u002F22.member-access-operator",{"title":1801,"path":1802,"stem":1803},"Цикл for-each (Range-based for)","\u002Fcpp\u002Fforeach-loop","02.cpp\u002F23.foreach-loop",{"title":1805,"path":1806,"stem":1807},"Вказівники на функції","\u002Fcpp\u002Ffunction-pointers","02.cpp\u002F24.function-pointers",{"title":1809,"path":1810,"stem":1811},"Лямбда-вирази","\u002Fcpp\u002Flambdas","02.cpp\u002F25.lambdas",{"title":1813,"path":1814,"stem":1815},"Лямбда-захоплення","\u002Fcpp\u002Flambda-captures","02.cpp\u002F26.lambda-captures",{"title":1817,"path":1818,"stem":1819},"Еліпсис","\u002Fcpp\u002Fellipsis","02.cpp\u002F27.ellipsis",{"title":1821,"path":1822,"stem":1823},"Безпечні альтернативи еліпсису","\u002Fcpp\u002F27a.ellipsis","02.cpp\u002F27a.ellipsis",{"title":1825,"path":1826,"stem":1827},"Аргументи командного рядка","\u002Fcpp\u002Fcommand-line-arguments","02.cpp\u002F28.command-line-arguments",{"title":1829,"path":1830,"stem":1831},"Перерахування (enum)","\u002Fcpp\u002Fenum","02.cpp\u002F29.enum",{"title":1833,"path":1834,"stem":1835},"Класи-перерахування (enum class)","\u002Fcpp\u002Fenum-class","02.cpp\u002F30.enum-class",{"title":1837,"path":1838,"stem":1839},"Псевдоніми типів (typedef і using)","\u002Fcpp\u002Ftype-aliases","02.cpp\u002F31.type-aliases",{"title":1841,"path":1842,"stem":1843},"Системи числення та двійкова арифметика","\u002Fcpp\u002Fnumber-systems","02.cpp\u002F32.number-systems",{"title":1845,"path":1846,"stem":1847},"Структури (struct): агрегування даних","\u002Fcpp\u002Fstruct","02.cpp\u002F33.struct",{"title":1849,"path":1850,"stem":1851},"Структури у функціях","\u002Fcpp\u002Fstruct-functions","02.cpp\u002F34.struct-functions",{"title":1853,"path":1854,"stem":1855},"Масиви структур і вкладені структури","\u002Fcpp\u002Fstruct-arrays","02.cpp\u002F35.struct-arrays",{"title":1857,"path":1858,"stem":1859},"Патерни struct та межі застосування","\u002Fcpp\u002Fstruct-patterns","02.cpp\u002F36.struct-patterns",{"title":1861,"path":1862,"stem":1863},"Символи та таблиця ASCII","\u002Fcpp\u002Fascii-characters","02.cpp\u002F37.ascii-characters",{"title":1865,"path":1866,"stem":1867},"Unicode та кодування UTF","\u002Fcpp\u002Funicode-utf","02.cpp\u002F38.unicode-utf",{"title":1869,"path":1870,"stem":1871},"C-style рядки","\u002Fcpp\u002Fc-strings","02.cpp\u002F39.c-strings",{"title":1873,"path":1874,"stem":1875},"Вступ до std::string","\u002Fcpp\u002Fstd-string-intro","02.cpp\u002F40.std-string-intro",{"title":1877,"path":1878,"stem":1879},"Довжина, ємність та доступ до символів std::string","\u002Fcpp\u002Fstd-string-capacity-access","02.cpp\u002F41.std-string-capacity-access",{"title":1881,"path":1882,"stem":1883},"Модифікація std::string: присвоювання, додавання, вставка, видалення та заміна","\u002Fcpp\u002Fstd-string-modification","02.cpp\u002F42.std-string-modification",{"title":1885,"path":1886,"stem":1887},"Пошук у std::string: find, npos та практичні патерни","\u002Fcpp\u002Fstd-string-search","02.cpp\u002F43.std-string-search",{"title":1889,"path":1890,"stem":1891},"std::string_view: невласницький погляд на рядок без копіювання","\u002Fcpp\u002Fstd-string-view","02.cpp\u002F44.std-string-view",{"title":1893,"path":1894,"stem":1895},"Об'єднання (union): один блок пам'яті, кілька інтерпретацій","\u002Fcpp\u002Funion","02.cpp\u002F45.union",{"title":1897,"path":1898,"stem":1899},"Організація коду: файли, препроцесор, простори імен","\u002Fcpp\u002Fmultifile-programs","02.cpp\u002F46.multifile-programs",{"title":1901,"path":1902,"stem":1903},"Робота з файлами: C-стиль (stdio.h)","\u002Fcpp\u002Fc-style-files","02.cpp\u002F47.c-style-files",{"title":1905,"path":1906,"stem":1907},"Робота з файлами: C++-стиль (fstream)","\u002Fcpp\u002Fcpp-style-files","02.cpp\u002F48.cpp-style-files",{"title":1909,"path":1910,"stem":1911},"Введення в ООП: від процедур до об'єктів","\u002Fcpp\u002Foop-intro","02.cpp\u002F49.oop-intro",{"title":1913,"path":1914,"stem":1915},"Класи, об'єкти та методи","\u002Fcpp\u002Fclasses-objects-methods","02.cpp\u002F50.classes-objects-methods",{"title":1917,"path":1918,"stem":1919},"Специфікатори доступу та інкапсуляція","\u002Fcpp\u002Faccess-specifiers-encapsulation","02.cpp\u002F51.access-specifiers-encapsulation",{"title":1921,"path":1922,"stem":1923},"Конструктори: гарантована ініціалізація об'єктів","\u002Fcpp\u002Fconstructors","02.cpp\u002F52.constructors",{"title":1925,"path":1926,"stem":1927},"Списки ініціалізації та делегуючі конструктори","\u002Fcpp\u002Finit-lists-delegating","02.cpp\u002F53.init-lists-delegating",{"title":1929,"path":1930,"stem":1931},"Деструктори та ідіома RAII","\u002Fcpp\u002Fdestructors-raii","02.cpp\u002F54.destructors-raii",{"title":1933,"path":1934,"stem":1935},"Прихований покажчик this","\u002Fcpp\u002Fthis-pointer","02.cpp\u002F55.this-pointer",{"title":1937,"path":1938,"stem":1939},"Розподіл класу на заголовковий файл та файл реалізації","\u002Fcpp\u002Fclass-header-source","02.cpp\u002F56.class-header-source",{"title":1941,"path":1942,"stem":1943},"Класи та const","\u002Fcpp\u002Fconst-classes","02.cpp\u002F57.const-classes",{"title":1945,"path":1946,"stem":1947},"Статичні члени класу","\u002Fcpp\u002Fstatic-members","02.cpp\u002F58.static-members",{"title":1949,"path":1950,"stem":1951},"Конструктор копіювання та запобігання копіюванню","\u002Fcpp\u002Fcopy-constructor","02.cpp\u002F59.copy-constructor",{"title":1953,"path":1954,"stem":1955},"Дружні функції та класи","\u002Fcpp\u002Ffriend-functions-classes","02.cpp\u002F60.friend-functions-classes",{"title":1957,"path":1958,"stem":1959},"Анонімні об'єкти та вкладені типи","\u002Fcpp\u002Fanonymous-objects-nested-types","02.cpp\u002F61.anonymous-objects-nested-types",{"title":1961,"path":1962,"stem":1963},"Вимірювання часу виконання: RAII-таймер","\u002Fcpp\u002Ftiming-raii-timer","02.cpp\u002F62.timing-raii-timer",{"title":1965,"path":1966,"stem":1967},"Перевантаження операторів: основи та арифметика","\u002Fcpp\u002Foperator-overloading-basics","02.cpp\u002F63.operator-overloading-basics",{"title":1969,"path":1970,"stem":1971},"Перевантаження операторів: методи класу та спеціальні оператори","\u002Fcpp\u002Foperator-overloading-methods","02.cpp\u002F64.operator-overloading-methods",{"title":1973,"path":1974,"stem":1975},"Приведення типів, explicit та delete","\u002Fcpp\u002Ftypecast-explicit-delete","02.cpp\u002F65.typecast-explicit-delete",{"title":1977,"path":1978,"stem":1979},"Глибоке копіювання та оператор присвоювання","\u002Fcpp\u002Fdeep-copy-assignment","02.cpp\u002F66.deep-copy-assignment",{"title":1981,"path":1982,"stem":1983},"Зв'язки між об'єктами: композиція та агрегація","\u002Fcpp\u002Fcomposition-aggregation","02.cpp\u002F67.composition-aggregation",{"title":1985,"path":1986,"stem":1987},"Асоціація та залежність між об","\u002Fcpp\u002Fassociation-dependency","02.cpp\u002F68.association-dependency",{"title":1989,"path":1990,"stem":1991},"Контейнерні класи та `std::initializer_list`","\u002Fcpp\u002Fcontainer-classes-initializer-list","02.cpp\u002F69.container-classes-initializer-list",{"title":1993,"path":1994,"stem":1995},"Конструктори, деструктори та порядок ініціалізації в ієрархіях","\u002Fcpp\u002Finheritance-constructors-destructors","02.cpp\u002F71.inheritance-constructors-destructors",{"title":1997,"path":1998,"stem":1999},"Специфікатор `protected` та види наслідування","\u002Fcpp\u002Finheritance-access-specifiers","02.cpp\u002F72.inheritance-access-specifiers",{"title":2001,"path":2002,"stem":2003},"Перевизначення методів та приховування імен","\u002Fcpp\u002Fmethod-overriding-hiding","02.cpp\u002F73.method-overriding-hiding",{"title":2005,"path":2006,"stem":2007},"Множинне наслідування та проблема ромба","\u002Fcpp\u002Fmultiple-inheritance-diamond","02.cpp\u002F74.multiple-inheritance-diamond",{"title":2009,"path":2010,"stem":2011},"Вказівники на базовий клас та віртуальні функції","\u002Fcpp\u002Fvirtual-functions-polymorphism","02.cpp\u002F75.virtual-functions-polymorphism",{"title":2013,"path":2014,"stem":2015},"Специфікатори override, final та віртуальні деструктори","\u002Fcpp\u002Foverride-final-virtual-destructors","02.cpp\u002F76.override-final-virtual-destructors",{"title":2017,"path":2018,"stem":2019},"Внутрішні механізми поліморфізму: vtable, vptr та зв'язування","\u002Fcpp\u002Fvirtual-table-binding","02.cpp\u002F77.virtual-table-binding",{"title":2021,"path":2022,"stem":2023},"Абстрактні класи та чисті віртуальні функції","\u002Fcpp\u002Fabstract-classes-interfaces","02.cpp\u002F78.abstract-classes-interfaces",{"title":2025,"path":2026,"stem":2027},"Зрізка об'єктів, віртуальне наслідування та поліморфний вивід","\u002Fcpp\u002Fslicing-virtual-base-io","02.cpp\u002F79.slicing-virtual-base-io",{"title":2029,"path":2030,"stem":2031},"Динамічне приведення типів (`dynamic_cast`) та RTTI","\u002Fcpp\u002Fdynamic-cast-rtti","02.cpp\u002F80.dynamic-cast-rtti",{"title":2033,"path":2034,"stem":2035},"Шаблони функцій: узагальнене програмування","\u002Fcpp\u002Ffunction-templates","02.cpp\u002F81.function-templates",{"title":2037,"path":2038,"stem":2039},"Шаблони класів та NTTP-параметри","\u002Fcpp\u002Fclass-templates-nttp","02.cpp\u002F82.class-templates-nttp",{"title":2041,"icon":2042,"path":2043,"stem":2044,"children":2045,"page":59},"JavaScript","i-devicon-javascript","\u002Fjavascript","03.javascript",[2046,2072,2126,2148,2452,2490,2508],{"title":2047,"icon":2048,"path":2049,"stem":2050,"children":2051,"page":59},"Events","i-lucide-mouse-pointer-click","\u002Fjavascript\u002Fevents","03.javascript\u002F01.events",[2052,2056,2060,2064,2068],{"title":2053,"path":2054,"stem":2055},"Вступ до подій браузера","\u002Fjavascript\u002Fevents\u002Fintro","03.javascript\u002F01.events\u002F01.intro",{"title":2057,"path":2058,"stem":2059},"Бульбашковий механізм (Bubbling) та занурення (Capturing)","\u002Fjavascript\u002Fevents\u002Fbubbling-capturing","03.javascript\u002F01.events\u002F02.bubbling-capturing",{"title":2061,"path":2062,"stem":2063},"Делегування подій (Event Delegation)","\u002Fjavascript\u002Fevents\u002Fdelegate-events","03.javascript\u002F01.events\u002F03.delegate-events",{"title":2065,"path":2066,"stem":2067},"Типові дії браузера та preventDefault()","\u002Fjavascript\u002Fevents\u002Fprevent-default","03.javascript\u002F01.events\u002F04.prevent-default",{"title":2069,"path":2070,"stem":2071},"Запуск користувацьких подій (Custom Events)","\u002Fjavascript\u002Fevents\u002Fcustom-events","03.javascript\u002F01.events\u002F05.custom-events",{"title":2073,"icon":2074,"path":2075,"stem":2076,"children":2077,"page":59},"Network","i-lucide-globe","\u002Fjavascript\u002Fnetwork","03.javascript\u002F02.network",[2078,2082,2086,2090,2094,2098,2102,2106,2110,2114,2118,2122],{"title":2079,"path":2080,"stem":2081},"Fetch API - Сучасний підхід до HTTP-запитів","\u002Fjavascript\u002Fnetwork\u002F01-fetch-api","03.javascript\u002F02.network\u002F01-fetch-api",{"title":2083,"path":2084,"stem":2085},"FormData - Робота з формами та файлами","\u002Fjavascript\u002Fnetwork\u002F02-formdata","03.javascript\u002F02.network\u002F02-formdata",{"title":2087,"path":2088,"stem":2089},"Відстеження прогресу завантаження","\u002Fjavascript\u002Fnetwork\u002F03-download-progress","03.javascript\u002F02.network\u002F03-download-progress",{"title":2091,"path":2092,"stem":2093},"Переривання fetch-запитів","\u002Fjavascript\u002Fnetwork\u002F04-abort-requests","03.javascript\u002F02.network\u002F04-abort-requests",{"title":2095,"path":2096,"stem":2097},"CORS - Запити між різними джерелами","\u002Fjavascript\u002Fnetwork\u002F05-cors","03.javascript\u002F02.network\u002F05-cors",{"title":2099,"path":2100,"stem":2101},"Fetch API - Повний довідник опцій","\u002Fjavascript\u002Fnetwork\u002F06-fetch-options","03.javascript\u002F02.network\u002F06-fetch-options",{"title":2103,"path":2104,"stem":2105},"URL Objects - Робота з посиланнями","\u002Fjavascript\u002Fnetwork\u002F07-url-objects","03.javascript\u002F02.network\u002F07-url-objects",{"title":2107,"path":2108,"stem":2109},"XMLHttpRequest - AJAX та низькорівневі запити","\u002Fjavascript\u002Fnetwork\u002F08-xmlhttprequest","03.javascript\u002F02.network\u002F08-xmlhttprequest",{"title":2111,"path":2112,"stem":2113},"Відновлюване завантаження файлів","\u002Fjavascript\u002Fnetwork\u002F09-resumable-upload","03.javascript\u002F02.network\u002F09-resumable-upload",{"title":2115,"path":2116,"stem":2117},"Cookies, document.cookie та світ після \"Cookiepocalypse\"","\u002Fjavascript\u002Fnetwork\u002F10-cookies","03.javascript\u002F02.network\u002F10-cookies",{"title":2119,"path":2120,"stem":2121},"js-cookie: Керування Cookies без Болю","\u002Fjavascript\u002Fnetwork\u002F11-js-cookie","03.javascript\u002F02.network\u002F11-js-cookie",{"title":2123,"path":2124,"stem":2125},"Axios: Потужний HTTP-клієнт для JavaScript","\u002Fjavascript\u002Fnetwork\u002F12-axios","03.javascript\u002F02.network\u002F12-axios",{"title":2127,"icon":2128,"path":2129,"stem":2130,"children":2131,"page":59},"Bom","i-lucide-monitor","\u002Fjavascript\u002Fbom","03.javascript\u002F03.bom",[2132,2136,2140,2144],{"title":2133,"path":2134,"stem":2135},"LocalStorage, SessionStorage та patterns збереження даних","\u002Fjavascript\u002Fbom\u002F01-localstorage","03.javascript\u002F03.bom\u002F01-localstorage",{"title":2137,"path":2138,"stem":2139},"Location Object - Керування адресою сторінки","\u002Fjavascript\u002Fbom\u002F02-location-object","03.javascript\u002F03.bom\u002F02-location-object",{"title":2141,"path":2142,"stem":2143},"History API - Керування історією браузера","\u002Fjavascript\u002Fbom\u002F03-history-api","03.javascript\u002F03.bom\u002F03-history-api",{"title":2145,"path":2146,"stem":2147},"Navigator Object - Ідентифікація та Можливості Пристрою","\u002Fjavascript\u002Fbom\u002F04-navigator-object","03.javascript\u002F03.bom\u002F04-navigator-object",{"title":2149,"icon":2150,"path":2151,"stem":2152,"children":2153},"React","i-devicon-react","\u002Fjavascript\u002Freact","03.javascript\u002F04.react\u002Findex",[2154,2155,2159,2163,2167,2171,2234,2269,2421],{"title":2149,"path":2151,"stem":2152},{"title":2156,"path":2157,"stem":2158},"Робота з Формами в React","\u002Fjavascript\u002Freact\u002Freact-forms","03.javascript\u002F04.react\u002F01.react-forms",{"title":2160,"path":2161,"stem":2162},"React Hook Form: Професійна Робота з Формами","\u002Fjavascript\u002Freact\u002Freact-hook-form","03.javascript\u002F04.react\u002F02.react-hook-form",{"title":2164,"path":2165,"stem":2166},"React Hook Form: Глибоке Розуміння Архітектури та Оптимізації","\u002Fjavascript\u002Freact\u002Freact-hook-form-new","03.javascript\u002F04.react\u002F02.react-hook-form-new",{"title":2168,"path":2169,"stem":2170},"Axios та React: Професійна Архітектура Запитів","\u002Fjavascript\u002Freact\u002Fdata-fetching-axios","03.javascript\u002F04.react\u002F03.data-fetching-axios",{"title":2172,"icon":132,"path":2173,"stem":2174,"children":2175},"Tanstack Query","\u002Fjavascript\u002Freact\u002Ftanstack-query","03.javascript\u002F04.react\u002F04.tanstack-query\u002Findex",[2176,2178,2182,2186,2190,2194,2198,2202,2206,2210,2214,2218,2222,2226,2230],{"title":2177,"path":2173,"stem":2174},"TanStack Query: Майстерність Керування Станом Сервера",{"title":2179,"path":2180,"stem":2181},"Парадигма Server State: Чому useEffect недостатньо","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-state-paradigm","03.javascript\u002F04.react\u002F04.tanstack-query\u002F01.server-state-paradigm",{"title":2183,"path":2184,"stem":2185},"Встановлення та Налаштування: Фундамент","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Finstallation-and-devtools","03.javascript\u002F04.react\u002F04.tanstack-query\u002F02.installation-and-devtools",{"title":2187,"path":2188,"stem":2189},"Основи Запитів та Магія Ключів","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fquery-basics-and-keys","03.javascript\u002F04.react\u002F04.tanstack-query\u002F03.query-basics-and-keys",{"title":2191,"path":2192,"stem":2193},"Синхронізація Даних: Життєвий Цикл Запиту","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fdata-synchronization","03.javascript\u002F04.react\u002F04.tanstack-query\u002F04.data-synchronization",{"title":2195,"path":2196,"stem":2197},"Мутації та Інвалідація: Зміна Даних","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fmutations-and-invalidation","03.javascript\u002F04.react\u002F04.tanstack-query\u002F05.mutations-and-invalidation",{"title":2199,"path":2200,"stem":2201},"Оптимістичні Оновлення: Швидше за Світло","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Foptimistic-updates","03.javascript\u002F04.react\u002F04.tanstack-query\u002F06.optimistic-updates",{"title":2203,"path":2204,"stem":2205},"Пагінація та Infinite Scroll","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fpagination-and-load-more","03.javascript\u002F04.react\u002F04.tanstack-query\u002F07.pagination-and-load-more",{"title":2207,"path":2208,"stem":2209},"Просунуті Патерни та Оптимізація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F04.tanstack-query\u002F08.advanced-patterns",{"title":2211,"path":2212,"stem":2213},"Архітектура та Best Practices","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Farchitecture-and-best-practices","03.javascript\u002F04.react\u002F04.tanstack-query\u002F09.architecture-and-best-practices",{"title":2215,"path":2216,"stem":2217},"Server-Side Rendering (SSR) та Гідратація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-side-rendering","03.javascript\u002F04.react\u002F04.tanstack-query\u002F10.server-side-rendering",{"title":2219,"path":2220,"stem":2221},"Стратегії Тестування","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Ftesting-strategies","03.javascript\u002F04.react\u002F04.tanstack-query\u002F11.testing-strategies",{"title":2223,"path":2224,"stem":2225},"Аутентифікація та Обробка Помилок","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fauthentication-and-errors","03.javascript\u002F04.react\u002F04.tanstack-query\u002F12.authentication-and-errors",{"title":2227,"path":2228,"stem":2229},"React Suspense та Майбутнє","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Freact-suspense","03.javascript\u002F04.react\u002F04.tanstack-query\u002F13.react-suspense",{"title":2231,"path":2232,"stem":2233},"Глибоке Занурення в Продуктивність","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fperformance-deep-dive","03.javascript\u002F04.react\u002F04.tanstack-query\u002F14.performance-deep-dive",{"title":2235,"icon":2150,"path":2236,"stem":2237,"children":2238},"React Router","\u002Fjavascript\u002Freact\u002Freact-router","03.javascript\u002F04.react\u002F05.react-router\u002Findex",[2239,2241,2245,2249,2253,2257,2261,2265],{"title":2240,"path":2236,"stem":2237},"React Router: Навігаційна система сучасного вебу",{"title":2242,"path":2243,"stem":2244},"Налаштування та Базовий Роутинг","\u002Fjavascript\u002Freact\u002Freact-router\u002Fsetup-and-basic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F01.setup-and-basic-routing",{"title":2246,"path":2247,"stem":2248},"Динамічна Навігація","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnavigation-and-links","03.javascript\u002F04.react\u002F05.react-router\u002F02.navigation-and-links",{"title":2250,"path":2251,"stem":2252},"Вкладені Маршрути та Макети","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnested-routes-and-layouts","03.javascript\u002F04.react\u002F05.react-router\u002F03.nested-routes-and-layouts",{"title":2254,"path":2255,"stem":2256},"Динамічні Маршрути та Параметри","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdynamic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F04.dynamic-routing",{"title":2258,"path":2259,"stem":2260},"Data APIs: Loaders та Actions","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdata-loading","03.javascript\u002F04.react\u002F05.react-router\u002F05.data-loading",{"title":2262,"path":2263,"stem":2264},"Просунуті Патерни","\u002Fjavascript\u002Freact\u002Freact-router\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F05.react-router\u002F06.advanced-patterns",{"title":2266,"path":2267,"stem":2268},"Legacy Routing: Компонентний підхід","\u002Fjavascript\u002Freact\u002Freact-router\u002Flegacy-routing","03.javascript\u002F04.react\u002F05.react-router\u002F07.legacy-routing",{"title":2270,"icon":132,"path":2271,"stem":2272,"children":2273},"Redux","\u002Fjavascript\u002Freact\u002Fredux","03.javascript\u002F04.react\u002F06.redux\u002Findex",[2274,2276,2292,2321,2330,2351,2367,2396],{"title":2275,"path":2271,"stem":2272},"Redux: Еволюція управління станом",{"title":14,"icon":15,"path":2277,"stem":2278,"children":2279,"page":59},"\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals",[2280,2284,2288],{"title":2281,"path":2282,"stem":2283},"Вступ до State Management","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fintro-state-management","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F01.intro-state-management",{"title":2285,"path":2286,"stem":2287},"Філософія Redux та Три Принципи","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fredux-philosophy","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F02.redux-philosophy",{"title":2289,"path":2290,"stem":2291},"Чисті функції та Іммутабельність","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fpure-functions-immutability","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F03.pure-functions-immutability",{"title":2293,"icon":132,"path":2294,"stem":2295,"children":2296,"page":59},"Classic Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux",[2297,2301,2305,2309,2313,2317],{"title":2298,"path":2299,"stem":2300},"Створення Store (Classic Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fstore-setup","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F01.store-setup",{"title":2302,"path":2303,"stem":2304},"Actions, Constants та Action Creators","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Factions-constants","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F02.actions-constants",{"title":2306,"path":2307,"stem":2308},"Логіка Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freducers","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F03.reducers",{"title":2310,"path":2311,"stem":2312},"Комбінування Reducers (Root Reducer)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fdata-flow","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F04.data-flow",{"title":2314,"path":2315,"stem":2316},"Підключення до React (React-Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freact-redux-connection","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F05.react-redux-connection",{"title":2318,"path":2319,"stem":2320},"Middleware та Асинхронність (Redux Thunk)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fmiddleware-thunk","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F06.middleware-thunk",{"title":2322,"icon":132,"path":2323,"stem":2324,"children":2325,"page":59},"Transition To Rtk","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk",[2326],{"title":2327,"path":2328,"stem":2329},"Проблеми класичного Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk\u002Fproblems-with-classic","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk\u002F01.problems-with-classic",{"title":2331,"icon":132,"path":2332,"stem":2333,"children":2334,"page":59},"Redux Toolkit","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit",[2335,2339,2343,2347],{"title":2336,"path":2337,"stem":2338},"Налаштування Store з configureStore","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fconfigure-store","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F01.configure-store",{"title":2340,"path":2341,"stem":2342},"createSlice: Революція в Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fcreate-slice","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F02.create-slice",{"title":2344,"path":2345,"stem":2346},"Асинхронність з createAsyncThunk","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fasync-thunks","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F03.async-thunks",{"title":2348,"path":2349,"stem":2350},"04. Entity Adapter: Керування нормалізованим станом","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fentity-adapter","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F04.entity-adapter",{"title":2352,"icon":92,"path":2353,"stem":2354,"children":2355,"page":59},"Advanced","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced",[2356,2360,2364],{"title":2357,"path":2358,"stem":2359},"Мемоізація та Селектори: Повний Гайд по Reselect","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Fselectors-reselect","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F01.selectors-reselect",{"title":2361,"path":2362,"stem":2363},"RTK Query: Архітектура Серверного Кешу","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Frtk-query-intro","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F02.rtk-query-intro",{"title":2211,"path":2365,"stem":2366},"\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Farchitecture-best-practices","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F03.architecture-best-practices",{"title":2368,"icon":132,"path":2369,"stem":2370,"children":2371,"page":59},"Project Kanban","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban",[2372,2376,2380,2384,2388,2392],{"title":2373,"path":2374,"stem":2375},"Проєкт: Kanban Board (Trello Clone)","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fproject-overview","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F01.project-overview",{"title":2377,"path":2378,"stem":2379},"Налаштування та Типізація","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fsetup-and-types","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F02.setup-and-types",{"title":2381,"path":2382,"stem":2383},"Board Slice: Серце Дошки","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fboard-slice","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F03.board-slice",{"title":2385,"path":2386,"stem":2387},"Логіка Drag & Drop","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fdrag-and-drop-logic","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F04.drag-and-drop-logic",{"title":2389,"path":2390,"stem":2391},"Інтеграція з RTK Query","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Frtk-query-integration","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F05.rtk-query-integration",{"title":2393,"path":2394,"stem":2395},"Optimistic Updates","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Foptimistic-updates","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F06.optimistic-updates",{"title":2397,"icon":132,"path":2398,"stem":2399,"children":2400,"page":59},"Testing","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting","03.javascript\u002F04.react\u002F06.redux\u002F07.testing",[2401,2405,2409,2413,2417],{"title":2402,"path":2403,"stem":2404},"Тестування Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Fintro-testing","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F01.intro-testing",{"title":2406,"path":2407,"stem":2408},"Тестування Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-reducers","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F02.testing-reducers",{"title":2410,"path":2411,"stem":2412},"Тестування Селекторів","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-selectors","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F03.testing-selectors",{"title":2414,"path":2415,"stem":2416},"Тестування Компонентів (Integration)","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-components","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F04.testing-components",{"title":2418,"path":2419,"stem":2420},"Тестування Async Thunks","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-thunks","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F05.testing-thunks",{"title":2422,"icon":132,"path":2423,"stem":2424,"children":2425},"Ui Libraries","\u002Fjavascript\u002Freact\u002Fui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002Findex",[2426,2428,2432,2436,2440,2444,2448],{"title":2427,"path":2423,"stem":2424},"UI Бібліотеки в React",{"title":2429,"path":2430,"stem":2431},"Вступ до UI Бібліотек: Навіщо Винаходити Велосипед Двічі?","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fintroduction-to-ui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002F01.introduction-to-ui-libraries",{"title":2433,"path":2434,"stem":2435},"Філософія shadcn\u002Fui: \"Not a Component Library\"","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-philosophy","03.javascript\u002F04.react\u002F07.ui-libraries\u002F02.shadcn-philosophy",{"title":2437,"path":2438,"stem":2439},"Установка та Налаштування shadcn\u002Fui","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-installation","03.javascript\u002F04.react\u002F07.ui-libraries\u002F03.shadcn-installation",{"title":2441,"path":2442,"stem":2443},"Базові Компоненти shadcn\u002Fui: Фундамент Інтерфейсу","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-basics","03.javascript\u002F04.react\u002F07.ui-libraries\u002F04.shadcn-components-basics",{"title":2445,"path":2446,"stem":2447},"Компоненти Форм: Побудова Інтерактивних Form","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-forms","03.javascript\u002F04.react\u002F07.ui-libraries\u002F05.shadcn-components-forms",{"title":2449,"path":2450,"stem":2451},"Складні Компоненти: Dialog, Dropdown, Table та Command","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-advanced","03.javascript\u002F04.react\u002F07.ui-libraries\u002F06.shadcn-components-advanced",{"title":2453,"icon":2454,"path":2455,"stem":2456,"children":2457,"page":59},"TypeScript","i-devicon-typescript","\u002Fjavascript\u002Ftypescript","03.javascript\u002F05.typescript",[2458,2462,2466,2470,2474,2478,2482,2486],{"title":2459,"path":2460,"stem":2461},"TypeScript: Броня для вашого коду","\u002Fjavascript\u002Ftypescript\u002Fintro-and-basic-types","03.javascript\u002F05.typescript\u002F01.intro-and-basic-types",{"title":2463,"path":2464,"stem":2465},"Майстерність Моделювання Даних: Інтерфейси та Просунуті Типи","\u002Fjavascript\u002Ftypescript\u002Finterfaces-and-advanced-types","03.javascript\u002F05.typescript\u002F02.interfaces-and-advanced-types",{"title":2467,"path":2468,"stem":2469},"Алхімія Типів: Generics та Utility Types","\u002Fjavascript\u002Ftypescript\u002Fgenerics-and-utilities","03.javascript\u002F05.typescript\u002F03.generics-and-utilities",{"title":2471,"path":2472,"stem":2473},"Архітектура та Шаблони: Класи в TypeScript","\u002Fjavascript\u002Ftypescript\u002Fclasses-and-oop","03.javascript\u002F05.typescript\u002F04.classes-and-oop",{"title":2475,"path":2476,"stem":2477},"Продакшн та Екосистема: Advanced Config & Workflow","\u002Fjavascript\u002Ftypescript\u002Fadvanced-patterns-and-config","03.javascript\u002F05.typescript\u002F05.advanced-patterns-and-config",{"title":2479,"path":2480,"stem":2481},"TypeScript у світі React","\u002Fjavascript\u002Ftypescript\u002Freact-basics","03.javascript\u002F05.typescript\u002F06.react-basics",{"title":2483,"path":2484,"stem":2485},"React + TypeScript: Продвинуті патерни","\u002Fjavascript\u002Ftypescript\u002Freact-advanced","03.javascript\u002F05.typescript\u002F07.react-advanced",{"title":2487,"path":2488,"stem":2489},"React + TypeScript: Екосистема та бібліотеки","\u002Fjavascript\u002Ftypescript\u002Freact-ecosystem","03.javascript\u002F05.typescript\u002F08.react-ecosystem",{"title":2491,"icon":2492,"path":2493,"stem":2494,"children":2495,"page":59},"Асинхронність","i-lucide-refresh-cw","\u002Fjavascript\u002Fasync-programming","03.javascript\u002F06.async-programming",[2496,2500,2504],{"title":2497,"path":2498,"stem":2499},"Event Loop: серце асинхронності в JavaScript","\u002Fjavascript\u002Fasync-programming\u002Fevent-loop-fundamentals","03.javascript\u002F06.async-programming\u002F01.event-loop-fundamentals",{"title":2501,"path":2502,"stem":2503},"Task Queue та Microtask Queue: пріоритети виконання","\u002Fjavascript\u002Fasync-programming\u002Ftask-queues","03.javascript\u002F06.async-programming\u002F02.task-queues",{"title":2505,"path":2506,"stem":2507},"Асинхронні патерни: від Callbacks до Async\u002FAwait","\u002Fjavascript\u002Fasync-programming\u002Fasync-patterns","03.javascript\u002F06.async-programming\u002F03.async-patterns",{"title":2509,"path":2510,"stem":2511},"Atomic Design","\u002Fjavascript\u002Fatomic-design","03.javascript\u002F2.atomic-design",{"title":2513,"icon":2514,"path":2515,"stem":2516,"children":2517,"page":59},"Java","i-devicon-java","\u002Fjava","04.java",[2518,2521,2524,2528,2532,2536,2540],{"title":162,"path":2519,"stem":2520},"\u002Fjava\u002Fdata-mapper-part1","04.java\u002F01.data-mapper-part1",{"title":166,"path":2522,"stem":2523},"\u002Fjava\u002Fdata-mapper-part2","04.java\u002F02.data-mapper-part2",{"title":2525,"path":2526,"stem":2527},"Service Layer: Організація бізнес-логіки","\u002Fjava\u002Fservice-layer","04.java\u002F03.service-layer",{"title":2529,"path":2530,"stem":2531},"Rich Domain Model та State Pattern","\u002Fjava\u002Frich-domain-model","04.java\u002F04.rich-domain-model",{"title":2533,"path":2534,"stem":2535},"Патерни для складної бізнес-логіки","\u002Fjava\u002Fbusiness-logic-patterns","04.java\u002F05.business-logic-patterns",{"title":2537,"path":2538,"stem":2539},"Обробка помилок та валідація","\u002Fjava\u002Ferror-handling-validation","04.java\u002F06.error-handling-validation",{"title":2541,"path":2542,"stem":2543,"children":2544,"page":59},"Проектування баз даних","\u002Fjava\u002Fpr2","04.java\u002Fpr2",[2545,2549,2553,2557,2561,2565,2569,2573,2577,2581,2585,2589,2593,2597,2601,2605,2609,2613,2617,2621,2625,2629,2633,2637,2641,2645,2649,2653,2657,2661,2665,2669,2673,2677,2681,2685,2689],{"title":2546,"path":2547,"stem":2548},"Концептуальне моделювання: Мистецтво розуміння предметної області","\u002Fjava\u002Fpr2\u002Fconceptual-modeling","04.java\u002Fpr2\u002F01.conceptual-modeling",{"title":2550,"path":2551,"stem":2552},"Логічне моделювання: Від бізнес-ідей до структур даних","\u002Fjava\u002Fpr2\u002Flogical-modeling","04.java\u002Fpr2\u002F02.logical-modeling",{"title":2554,"path":2555,"stem":2556},"Нормалізація: Гігієна даних та боротьба з аномаліями","\u002Fjava\u002Fpr2\u002Fnormalization","04.java\u002Fpr2\u002F03.normalization",{"title":2558,"path":2559,"stem":2560},"Фізична схема: Від абстракції до DDL","\u002Fjava\u002Fpr2\u002Fphysical-schema","04.java\u002Fpr2\u002F04.physical-schema",{"title":2562,"path":2563,"stem":2564},"Архітектурна класифікація таблиць","\u002Fjava\u002Fpr2\u002Ftable-classification","04.java\u002Fpr2\u002F05.table-classification",{"title":2566,"path":2567,"stem":2568},"Database Migrations: Версіонування схеми з Flyway","\u002Fjava\u002Fpr2\u002Fdatabase-migrations","04.java\u002Fpr2\u002F06.database-migrations",{"title":2570,"path":2571,"stem":2572},"А що, якби це була не реляційна БД?","\u002Fjava\u002Fpr2\u002Fbeyond-relational","04.java\u002Fpr2\u002F07.beyond-relational",{"title":2574,"path":2575,"stem":2576},"Object-Relational Impedance Mismatch: Два світи, що не хочуть дружити","\u002Fjava\u002Fpr2\u002Fimpedance-mismatch","04.java\u002Fpr2\u002F09.impedance-mismatch",{"title":2578,"path":2579,"stem":2580},"JDBC: Перший контакт із базою даних","\u002Fjava\u002Fpr2\u002Fjdbc-fundamentals","04.java\u002Fpr2\u002F10.jdbc-fundamentals",{"title":2582,"path":2583,"stem":2584},"Якість коду: Spotless, SpotBugs та SonarQube","\u002Fjava\u002Fpr2\u002F10a.code-quality","04.java\u002Fpr2\u002F10a.code-quality",{"title":2586,"path":2587,"stem":2588},"Connection Pool: Патерн Object Pool для JDBC-з'єднань","\u002Fjava\u002Fpr2\u002Fconnection-pool","04.java\u002Fpr2\u002F11.connection-pool",{"title":2590,"path":2591,"stem":2592},"Row Data Gateway: Об'єкт як обгортка рядка таблиці","\u002Fjava\u002Fpr2\u002Frow-data-gateway","04.java\u002Fpr2\u002F12.row-data-gateway",{"title":2594,"path":2595,"stem":2596},"Table Data Gateway: Фасад таблиці як архітектурний відступ","\u002Fjava\u002Fpr2\u002Ftable-data-gateway","04.java\u002Fpr2\u002F13.table-data-gateway",{"title":2598,"path":2599,"stem":2600},"Repository + Data Mapper: Правильна шарова архітектура з JDBC","\u002Fjava\u002Fpr2\u002Frepository-data-mapper","04.java\u002Fpr2\u002F14.repository-data-mapper",{"title":2602,"path":2603,"stem":2604},"Identity Map: Кешування сутностей у рамках сесії","\u002Fjava\u002Fpr2\u002Fidentity-map","04.java\u002Fpr2\u002F15.identity-map",{"title":2606,"path":2607,"stem":2608},"Unit of Work: Відстеження змін і координація JDBC-транзакцій","\u002Fjava\u002Fpr2\u002Funit-of-work","04.java\u002Fpr2\u002F16.unit-of-work",{"title":2610,"path":2611,"stem":2612},"Strategy: Замінювані SQL-стратегії для підтримки різних СУБД","\u002Fjava\u002Fpr2\u002Fstrategy-sql","04.java\u002Fpr2\u002F17.strategy-sql",{"title":2614,"path":2615,"stem":2616},"Proxy: Lazy Loading для One-To-Many колекцій","\u002Fjava\u002Fpr2\u002Fproxy-lazy-loading","04.java\u002Fpr2\u002F18.proxy-lazy-loading",{"title":2618,"path":2619,"stem":2620},"Generic Repository через Java Reflection: анотації та динамічний SQL","\u002Fjava\u002Fpr2\u002Fgeneric-repository-reflection","04.java\u002Fpr2\u002F19.generic-repository-reflection",{"title":2622,"path":2623,"stem":2624},"Specification Pattern: Композиція бізнес-правил для складних запитів","\u002Fjava\u002Fpr2\u002Fspecification-pattern","04.java\u002Fpr2\u002F20.specification-pattern",{"title":2626,"path":2627,"stem":2628},"Розширені можливості Specification Pattern: підзапити, агрегації та гібридний підхід","\u002Fjava\u002Fpr2\u002F20a.advanced-specifications","04.java\u002Fpr2\u002F20a.advanced-specifications",{"title":2630,"path":2631,"stem":2632},"Асинхронність у JDBC: Від блокуючих викликів до CompletableFuture","\u002Fjava\u002Fpr2\u002Fasynchronous-jdbc","04.java\u002Fpr2\u002F21.asynchronous-jdbc",{"title":2634,"path":2635,"stem":2636},"Інтеграційне тестування JDBC-репозиторіїв: Embedded H2 та патерн AAA","\u002Fjava\u002Fpr2\u002Fintegration-testing-h2","04.java\u002Fpr2\u002F22.integration-testing-h2",{"title":2638,"path":2639,"stem":2640},"Testcontainers: Тестування з реальною PostgreSQL у Docker-контейнерах","\u002Fjava\u002Fpr2\u002Fintegration-testing-testcontainers","04.java\u002Fpr2\u002F23.integration-testing-testcontainers",{"title":2642,"path":2643,"stem":2644},"Google Guice: Впровадження залежностей у JavaFX-проєкті","\u002Fjava\u002Fpr2\u002Fdependency-injection-guice","04.java\u002Fpr2\u002F24.dependency-injection-guice",{"title":2646,"path":2647,"stem":2648},"JavaFX: Основи побудови графічних інтерфейсів","\u002Fjava\u002Fpr2\u002Fjavafx-fundamentals","04.java\u002Fpr2\u002F25.javafx-fundamentals",{"title":2650,"path":2651,"stem":2652},"Properties та Bindings: Реактивність у JavaFX","\u002Fjava\u002Fpr2\u002Fjavafx-properties-bindings","04.java\u002Fpr2\u002F26.javafx-properties-bindings",{"title":2654,"path":2655,"stem":2656},"MVC vs MVP vs MVVM: Еволюція архітектурних патернів UI","\u002Fjava\u002Fpr2\u002Fui-architecture-patterns","04.java\u002Fpr2\u002F27.ui-architecture-patterns",{"title":2658,"path":2659,"stem":2660},"MVVM на практиці: Побудова ViewModel","\u002Fjava\u002Fpr2\u002Fmvvm-viewmodel-implementation","04.java\u002Fpr2\u002F28.mvvm-viewmodel-implementation",{"title":2662,"path":2663,"stem":2664},"View та Controller: Зв'язування з ViewModel через FXML","\u002Fjava\u002Fpr2\u002Fmvvm-view-controller","04.java\u002Fpr2\u002F29.mvvm-view-controller",{"title":2666,"path":2667,"stem":2668},"Інтеграція MVVM з Guice: Автоматична ін'єкція залежностей","\u002Fjava\u002Fpr2\u002Fmvvm-guice-integration","04.java\u002Fpr2\u002F30.mvvm-guice-integration",{"title":2670,"path":2671,"stem":2672},"Валідація та обробка помилок у MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-validation-error-handling","04.java\u002Fpr2\u002F31.mvvm-validation-error-handling",{"title":2674,"path":2675,"stem":2676},"Навігація та управління екранами у JavaFX MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-navigation-screen-management","04.java\u002Fpr2\u002F32.mvvm-navigation-screen-management",{"title":2678,"path":2679,"stem":2680},"Тестування JavaFX MVVM-додатків","\u002Fjava\u002Fpr2\u002Fmvvm-testing","04.java\u002Fpr2\u002F33.mvvm-testing",{"title":2682,"path":2683,"stem":2684},"Стилізація та теми у JavaFX: CSS та User Experience","\u002Fjava\u002Fpr2\u002Fjavafx-styling-themes","04.java\u002Fpr2\u002F34.javafx-styling-themes",{"title":2686,"path":2687,"stem":2688},"AtlantaFX: Сучасні теми для JavaFX додатків","\u002Fjava\u002Fpr2\u002Fatlantafx-modern-themes","04.java\u002Fpr2\u002F35.atlantafx-modern-themes",{"title":2690,"path":2691,"stem":2692},"Пакування та розповсюдження JavaFX-додатків","\u002Fjava\u002Fpr2\u002Fjar-packaging-distribution","04.java\u002Fpr2\u002F36.jar-packaging-distribution",{"title":2694,"icon":2695,"path":2696,"stem":2697,"children":2698,"page":59},"Python","i-devicon-python","\u002Fpython","05.python",[2699,2703,2706,2710,2714,2718,2722,2726,2730,2734,2738,2742,2746,2750,2754,2815],{"title":2700,"path":2701,"stem":2702},"Модулі, Пакети та Віртуальні Середовища","\u002Fpython\u002Fmodules-packages-venv","05.python\u002F00.modules-packages-venv",{"title":71,"path":2704,"stem":2705},"\u002Fpython\u002Fclasses-objects","05.python\u002F01.classes-objects",{"title":2707,"path":2708,"stem":2709},"Інкапсуляція, Керування Доступом та Властивості","\u002Fpython\u002Fencapsulation","05.python\u002F02.encapsulation",{"title":2711,"path":2712,"stem":2713},"Наслідування, MRO та суперсила super()","\u002Fpython\u002Finheritance-mro","05.python\u002F03.inheritance-mro",{"title":2715,"path":2716,"stem":2717},"Абстракція — ABC проти Статичних Протоколів (PEP 544)","\u002Fpython\u002Fabstraction-protocols","05.python\u002F04.abstraction-protocols",{"title":2719,"path":2720,"stem":2721},"Магічні методи (Dunder) та Емуляція протоколів","\u002Fpython\u002Fdunder-methods","05.python\u002F05.dunder-methods",{"title":2723,"path":2724,"stem":2725},"Декоратори та Керування життєвим циклом методів","\u002Fpython\u002Fdecorators-static-class","05.python\u002F06.decorators-static-class",{"title":2727,"path":2728,"stem":2729},"Дескриптори — Магія доступу до атрибутів","\u002Fpython\u002Fdescriptors","05.python\u002F07.descriptors",{"title":2731,"path":2732,"stem":2733},"Метакласи — Динамічне створення класів під капотом CPython","\u002Fpython\u002Fmetaclasses","05.python\u002F08.metaclasses",{"title":2735,"path":2736,"stem":2737},"Dataclasses, NamedTuple та сучасні контейнери Python","\u002Fpython\u002Fmodern-containers","05.python\u002F09.modern-containers",{"title":2739,"path":2740,"stem":2741},"GIL та модель конкурентності CPython — фундамент перед потоками і процесами","\u002Fpython\u002Fgil-concurrency-intro","05.python\u002F11.gil-concurrency-intro",{"title":2743,"path":2744,"stem":2745},"Threading — конкурентність для I\u002FO-bound задач","\u002Fpython\u002Fthreading","05.python\u002F12.threading",{"title":2747,"path":2748,"stem":2749},"Multiprocessing — справжній паралелізм для CPU-bound задач","\u002Fpython\u002Fmultiprocessing","05.python\u002F13.multiprocessing",{"title":2751,"path":2752,"stem":2753},"asyncio — кооперативна конкурентність та event loop","\u002Fpython\u002Fasyncio","05.python\u002F14.asyncio",{"title":2755,"icon":92,"path":2756,"stem":2757,"children":2758,"page":59},"FastAPI","\u002Fpython\u002Ffastapi","05.python\u002Ffastapi",[2759,2763,2767,2771,2775,2779,2783,2787,2791,2795,2799,2803,2807,2811],{"title":2760,"path":2761,"stem":2762},"Глибокий Typing та Pydantic v2 — від анотацій до валідації","\u002Fpython\u002Ffastapi\u002Ftyping-pydantic","05.python\u002Ffastapi\u002F15.typing-pydantic",{"title":2764,"path":2765,"stem":2766},"WSGI, ASGI та Python Web-екосистема","\u002Fpython\u002Ffastapi\u002Fwsgi-asgi-ecosystem","05.python\u002Ffastapi\u002F16.wsgi-asgi-ecosystem",{"title":2768,"path":2769,"stem":2770},"FastAPI: Перший додаток, Uvicorn та OpenAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-intro","05.python\u002Ffastapi\u002F17.fastapi-intro",{"title":2772,"path":2773,"stem":2774},"Маршрутизація, параметри запитів та APIRouter","\u002Fpython\u002Ffastapi\u002Ffastapi-routing-params","05.python\u002Ffastapi\u002F18.fastapi-routing-params",{"title":2776,"path":2777,"stem":2778},"Pydantic v2 у FastAPI — схеми, валідація та серіалізація","\u002Fpython\u002Ffastapi\u002Ffastapi-pydantic-schemas","05.python\u002Ffastapi\u002F19.fastapi-pydantic-schemas",{"title":2780,"path":2781,"stem":2782},"Dependency Injection — серце архітектури FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-dependency-injection","05.python\u002Ffastapi\u002F20.fastapi-dependency-injection",{"title":2784,"path":2785,"stem":2786},"Обробка помилок, Middleware та CORS у FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-errors-middleware","05.python\u002Ffastapi\u002F21.fastapi-errors-middleware",{"title":2788,"path":2789,"stem":2790},"SQLAlchemy 2.0 — ORM, Core та Async Engine","\u002Fpython\u002Ffastapi\u002Fsqlalchemy-orm","05.python\u002Ffastapi\u002F22.sqlalchemy-orm",{"title":2792,"path":2793,"stem":2794},"Alembic — міграції бази даних","\u002Fpython\u002Ffastapi\u002Falembic-migrations","05.python\u002Ffastapi\u002F23.alembic-migrations",{"title":2796,"path":2797,"stem":2798},"Repository Pattern та Clean Architecture у FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-repository-clean-arch","05.python\u002Ffastapi\u002F24.fastapi-repository-clean-arch",{"title":2800,"path":2801,"stem":2802},"Автентифікація та авторизація — JWT, OAuth2, RBAC","\u002Fpython\u002Ffastapi\u002Ffastapi-auth-security","05.python\u002Ffastapi\u002F25.fastapi-auth-security",{"title":2804,"path":2805,"stem":2806},"Тестування FastAPI — pytest, httpx, fixtures","\u002Fpython\u002Ffastapi\u002Ffastapi-testing","05.python\u002Ffastapi\u002F26.fastapi-testing",{"title":2808,"path":2809,"stem":2810},"Async на повну — Background Tasks, WebSockets, SSE та Celery","\u002Fpython\u002Ffastapi\u002Ffastapi-async-advanced","05.python\u002Ffastapi\u002F27.fastapi-async-advanced",{"title":2812,"path":2813,"stem":2814},"Deployment — Docker, CI\u002FCD, Monitoring","\u002Fpython\u002Ffastapi\u002Ffastapi-deployment","05.python\u002Ffastapi\u002F28.fastapi-deployment",{"title":2816,"path":2817,"stem":2818},"[object Object]","\u002Fpython\u002Foop-plan","05.python\u002Foop-plan",{"title":2820,"icon":2821,"path":2822,"stem":2823,"children":2824,"page":59},"Бази даних","i-lucide-database","\u002Fdatabases","06.databases",[2825,2855,2878,2915,2944,2962,2996,3008,3017],{"title":2826,"icon":2827,"path":2828,"stem":2829,"children":2830,"page":59},"Intro","i-lucide-play","\u002Fdatabases\u002Fintro","06.databases\u002F01.intro",[2831,2835,2839,2843,2847,2851],{"title":2832,"path":2833,"stem":2834},"Введення в теорію баз даних","\u002Fdatabases\u002Fintro\u002Fintroduction-to-databases","06.databases\u002F01.intro\u002F01.introduction-to-databases",{"title":2836,"path":2837,"stem":2838},"Реляційна модель даних","\u002Fdatabases\u002Fintro\u002Frelational-model-theory","06.databases\u002F01.intro\u002F02.relational-model-theory",{"title":2840,"path":2841,"stem":2842},"ER-моделювання","\u002Fdatabases\u002Fintro\u002Fer-modeling","06.databases\u002F01.intro\u002F03.er-modeling",{"title":2844,"path":2845,"stem":2846},"Логічне проектування БД","\u002Fdatabases\u002Fintro\u002Flogical-schema","06.databases\u002F01.intro\u002F04.logical-schema",{"title":2848,"path":2849,"stem":2850},"Класифікація таблиць","\u002Fdatabases\u002Fintro\u002Ftable-classification","06.databases\u002F01.intro\u002F05.table-classification",{"title":2852,"path":2853,"stem":2854},"PlantUML для баз даних","\u002Fdatabases\u002Fintro\u002Fplantuml-diagrams","06.databases\u002F01.intro\u002F06.plantuml-diagrams",{"title":2856,"icon":2821,"path":2857,"stem":2858,"children":2859,"page":59},"MS SQL Server Start","\u002Fdatabases\u002Fms-sql-server-start","06.databases\u002F02.ms-sql-server-start",[2860,2864,2870,2874],{"title":2861,"path":2862,"stem":2863},"Типи даних у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fdata-types","06.databases\u002F02.ms-sql-server-start\u002F01.data-types",{"title":2865,"path":2866,"stem":2867,"children":2868},"Індекси у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-indexes","06.databases\u002F02.ms-sql-server-start\u002F02.sql-indexes",[2869],{"title":2865,"path":2866,"stem":2867},{"title":2871,"path":2872,"stem":2873},"Системні бази даних MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsystem-databases","06.databases\u002F02.ms-sql-server-start\u002F03.system-databases",{"title":2875,"path":2876,"stem":2877},"Огляд мови SQL та запитів","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-queries-overview","06.databases\u002F02.ms-sql-server-start\u002F04.sql-queries-overview",{"title":2879,"icon":2821,"path":2880,"stem":2881,"children":2882,"page":59},"SQL","\u002Fdatabases\u002Fsql","06.databases\u002F03.sql",[2883,2887,2891,2895,2899,2903,2907,2911],{"title":2884,"path":2885,"stem":2886},"Налаштування демонстраційної бази даних","\u002Fdatabases\u002Fsql\u002Fsample-database-setup","06.databases\u002F03.sql\u002F00.sample-database-setup",{"title":2888,"path":2889,"stem":2890},"DDL - Створення таблиць (CREATE TABLE)","\u002Fdatabases\u002Fsql\u002Fddl-create-table","06.databases\u002F03.sql\u002F01.ddl-create-table",{"title":2892,"path":2893,"stem":2894},"DDL - Зміна та видалення таблиць (ALTER, DROP)","\u002Fdatabases\u002Fsql\u002Fddl-alter-drop-table","06.databases\u002F03.sql\u002F02.ddl-alter-drop-table",{"title":2896,"path":2897,"stem":2898},"SELECT запити - Основи","\u002Fdatabases\u002Fsql\u002Fselect-queries-fundamentals","06.databases\u002F03.sql\u002F03.select-queries-fundamentals",{"title":2900,"path":2901,"stem":2902},"SELECT запити - Розширені можливості","\u002Fdatabases\u002Fsql\u002Fselect-queries-advanced","06.databases\u002F03.sql\u002F04.select-queries-advanced",{"title":2904,"path":2905,"stem":2906},"INSERT запити - Додавання даних","\u002Fdatabases\u002Fsql\u002Finsert-queries","06.databases\u002F03.sql\u002F05.insert-queries",{"title":2908,"path":2909,"stem":2910},"UPDATE та DELETE запити","\u002Fdatabases\u002Fsql\u002Fupdate-delete-queries","06.databases\u002F03.sql\u002F06.update-delete-queries",{"title":2912,"path":2913,"stem":2914},"Транзакції в SQL","\u002Fdatabases\u002Fsql\u002Ftransactions","06.databases\u002F03.sql\u002F07.transactions",{"title":2916,"icon":2821,"path":2917,"stem":2918,"children":2919,"page":59},"Multi Table Databases","\u002Fdatabases\u002Fmulti-table-databases","06.databases\u002F04.multi-table-databases",[2920,2924,2928,2932,2936,2940],{"title":2921,"path":2922,"stem":2923},"Зв'язки та нормалізація БД","\u002Fdatabases\u002Fmulti-table-databases\u002Frelationships-and-normalization","06.databases\u002F04.multi-table-databases\u002F00.relationships-and-normalization",{"title":2925,"path":2926,"stem":2927},"INNER JOIN - З'єднання таблиць","\u002Fdatabases\u002Fmulti-table-databases\u002Finner-join","06.databases\u002F04.multi-table-databases\u002F01.inner-join",{"title":2929,"path":2930,"stem":2931},"OUTER JOINs - LEFT, RIGHT, FULL","\u002Fdatabases\u002Fmulti-table-databases\u002Fouter-joins","06.databases\u002F04.multi-table-databases\u002F02.outer-joins",{"title":2933,"path":2934,"stem":2935},"CROSS та SELF JOINs","\u002Fdatabases\u002Fmulti-table-databases\u002Fcross-self-joins","06.databases\u002F04.multi-table-databases\u002F03.cross-self-joins",{"title":2937,"path":2938,"stem":2939},"Підзапити (Subqueries)","\u002Fdatabases\u002Fmulti-table-databases\u002Fsubqueries","06.databases\u002F04.multi-table-databases\u002F04.subqueries",{"title":2941,"path":2942,"stem":2943},"Агрегації з JOIN","\u002Fdatabases\u002Fmulti-table-databases\u002Faggregations-with-joins","06.databases\u002F04.multi-table-databases\u002F05.aggregations-with-joins",{"title":2945,"icon":2946,"path":2947,"stem":2948,"children":2949,"page":59},"Aggregate Functions","i-lucide-calculator","\u002Fdatabases\u002Faggregate-functions","06.databases\u002F05.aggregate-functions",[2950,2954,2958],{"title":2951,"path":2952,"stem":2953},"Функції агрегування в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fintroduction-aggregate-functions","06.databases\u002F05.aggregate-functions\u002F01.introduction-aggregate-functions",{"title":2955,"path":2956,"stem":2957},"Групування даних в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fgrouping-data","06.databases\u002F05.aggregate-functions\u002F02.grouping-data",{"title":2959,"path":2960,"stem":2961},"Підзапити з агрегатними функціями","\u002Fdatabases\u002Faggregate-functions\u002Fsubqueries-aggregates","06.databases\u002F05.aggregate-functions\u002F03.subqueries-aggregates",{"title":2963,"icon":2964,"path":2965,"stem":2966,"children":2967,"page":59},"Тригери та зберігаємі процедури","i-lucide-database-zap","\u002Fdatabases\u002Ftriggers-stored-procedures","06.databases\u002F07.triggers-stored-procedures",[2968,2972,2976,2980,2984,2988,2992],{"title":2969,"path":2970,"stem":2971},"DML-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fdml-triggers","06.databases\u002F07.triggers-stored-procedures\u002F01.dml-triggers",{"title":2973,"path":2974,"stem":2975},"DDL-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fddl-triggers","06.databases\u002F07.triggers-stored-procedures\u002F02.ddl-triggers",{"title":2977,"path":2978,"stem":2979},"Transact-SQL розширення","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransact-sql-extensions","06.databases\u002F07.triggers-stored-procedures\u002F03.transact-sql-extensions",{"title":2981,"path":2982,"stem":2983},"Транзакції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransactions","06.databases\u002F07.triggers-stored-procedures\u002F04.transactions",{"title":2985,"path":2986,"stem":2987},"Зберігаємі процедури","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fstored-procedures","06.databases\u002F07.triggers-stored-procedures\u002F05.stored-procedures",{"title":2989,"path":2990,"stem":2991},"Користувацькі функції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fuser-defined-functions","06.databases\u002F07.triggers-stored-procedures\u002F06.user-defined-functions",{"title":2993,"path":2994,"stem":2995},"Безпека баз даних","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fsecurity","06.databases\u002F07.triggers-stored-procedures\u002F08.security",{"title":2993,"icon":793,"path":2997,"stem":2998,"children":2999,"page":59},"\u002Fdatabases\u002Fsecurity","06.databases\u002F08.security",[3000,3004],{"title":3001,"path":3002,"stem":3003},"Вступ до безпеки баз даних","\u002Fdatabases\u002Fsecurity\u002Fintroduction","06.databases\u002F08.security\u002F01.introduction",{"title":3005,"path":3006,"stem":3007},"Системні представлення та метадані","\u002Fdatabases\u002Fsecurity\u002Fsystem-views","06.databases\u002F08.security\u002F02.system-views",{"title":3009,"icon":3010,"path":3011,"stem":3012,"children":3013,"page":59},"Резервне копіювання та відновлення","i-lucide-database-backup","\u002Fdatabases\u002Fbackup-recovery","06.databases\u002F09.backup-recovery",[3014],{"title":3009,"path":3015,"stem":3016},"\u002Fdatabases\u002Fbackup-recovery\u002Fbackup-restore","06.databases\u002F09.backup-recovery\u002F01.backup-restore",{"title":3018,"icon":3019,"path":3020,"stem":3021,"children":3022,"page":59},"Повнотекстовий пошук","i-lucide-search","\u002Fdatabases\u002Ffull-text-search","06.databases\u002F10.full-text-search",[3023],{"title":3018,"path":3024,"stem":3025},"\u002Fdatabases\u002Ffull-text-search\u002Ffull-text-search","06.databases\u002F10.full-text-search\u002F01.full-text-search",{"title":3027,"icon":3028,"path":3029,"stem":3030,"children":3031,"page":59},"Tools","i-lucide-wrench","\u002Ftools","07.tools",[3032,3108],{"title":3033,"icon":3034,"path":3035,"stem":3036,"children":3037},"Docker","i-simple-icons-docker","\u002Ftools\u002Fdocker","07.tools\u002F01.docker\u002Findex",[3038,3040,3044,3048,3052,3056,3060,3064,3068,3072,3076,3080,3084,3088,3092,3096,3100,3104],{"title":3039,"path":3035,"stem":3036},"Docker: від нуля до production",{"title":3041,"path":3042,"stem":3043},"Контейнеризація — від проблеми до рішення","\u002Ftools\u002Fdocker\u002Fcontainerization-concept","07.tools\u002F01.docker\u002F01.containerization-concept",{"title":3045,"path":3046,"stem":3047},"Docker — що це і навіщо?","\u002Ftools\u002Fdocker\u002Fdocker-what-and-why","07.tools\u002F01.docker\u002F02.docker-what-and-why",{"title":3049,"path":3050,"stem":3051},"Архітектура Docker Engine","\u002Ftools\u002Fdocker\u002Fdocker-architecture","07.tools\u002F01.docker\u002F03.docker-architecture",{"title":3053,"path":3054,"stem":3055},"Встановлення Docker","\u002Ftools\u002Fdocker\u002Finstallation","07.tools\u002F01.docker\u002F04.installation",{"title":3057,"path":3058,"stem":3059},"Перший контейнер — docker run","\u002Ftools\u002Fdocker\u002Ffirst-container","07.tools\u002F01.docker\u002F05.first-container",{"title":3061,"path":3062,"stem":3063},"Життєвий цикл контейнера","\u002Ftools\u002Fdocker\u002Fcontainer-lifecycle","07.tools\u002F01.docker\u002F06.container-lifecycle",{"title":3065,"path":3066,"stem":3067},"Docker Images — фундаментальні концепції","\u002Ftools\u002Fdocker\u002Fdocker-images-fundamentals","07.tools\u002F01.docker\u002F07.docker-images-fundamentals",{"title":3069,"path":3070,"stem":3071},"Dockerfile — основи","\u002Ftools\u002Fdocker\u002Fdockerfile-basics","07.tools\u002F01.docker\u002F08.dockerfile-basics",{"title":3073,"path":3074,"stem":3075},"Dockerfile — просунуті техніки","\u002Ftools\u002Fdocker\u002Fdockerfile-advanced","07.tools\u002F01.docker\u002F09.dockerfile-advanced",{"title":3077,"path":3078,"stem":3079},"Build Context та кешування шарів","\u002Ftools\u002Fdocker\u002Fbuild-context-and-cache","07.tools\u002F01.docker\u002F10.build-context-and-cache",{"title":3081,"path":3082,"stem":3083},"Реєстри Docker-образів","\u002Ftools\u002Fdocker\u002Fimage-registries","07.tools\u002F01.docker\u002F11.image-registries",{"title":3085,"path":3086,"stem":3087},"Контейнеризація .NET додатків","\u002Ftools\u002Fdocker\u002Fdotnet-containerization","07.tools\u002F01.docker\u002F12.dotnet-containerization",{"title":3089,"path":3090,"stem":3091},"Томи та збереження даних","\u002Ftools\u002Fdocker\u002Fvolumes-and-data","07.tools\u002F01.docker\u002F13.volumes-and-data",{"title":3093,"path":3094,"stem":3095},"Основи мережі в Docker","\u002Ftools\u002Fdocker\u002Fnetworking-basics","07.tools\u002F01.docker\u002F14.networking-basics",{"title":3097,"path":3098,"stem":3099},"Змінні оточення та конфігурація","\u002Ftools\u002Fdocker\u002Fenvironment-and-configuration","07.tools\u002F01.docker\u002F15.environment-and-configuration",{"title":3101,"path":3102,"stem":3103},"Docker Compose — оркестрація контейнерів","\u002Ftools\u002Fdocker\u002Fdocker-compose-basics","07.tools\u002F01.docker\u002F16.docker-compose-basics",{"title":3105,"path":3106,"stem":3107},"Docker Compose — Multi-Service застосунки","\u002Ftools\u002Fdocker\u002Fcompose-multi-service","07.tools\u002F01.docker\u002F17.compose-multi-service",{"title":3109,"icon":3110,"path":3111,"stem":3112,"children":3113},"Kubernetes","simple-icons:kubernetes","\u002Ftools\u002Fkubernetes","07.tools\u002F02.kubernetes\u002Findex",[3114,3116,3120,3124,3128,3132,3136,3140,3144],{"title":3115,"path":3111,"stem":3112},"Kubernetes: від розробки до production",{"title":3117,"path":3118,"stem":3119},"Kubernetes — коли Docker Compose більше не вистачає","\u002Ftools\u002Fkubernetes\u002Fwhy-kubernetes","07.tools\u002F02.kubernetes\u002F01.why-kubernetes",{"title":3121,"path":3122,"stem":3123},"Архітектура Kubernetes — анатомія кластера","\u002Ftools\u002Fkubernetes\u002Fkubernetes-architecture","07.tools\u002F02.kubernetes\u002F02.kubernetes-architecture",{"title":3125,"path":3126,"stem":3127},"Локальне середовище — minikube, kind та k3s","\u002Ftools\u002Fkubernetes\u002Flocal-environment","07.tools\u002F02.kubernetes\u002F03.local-environment",{"title":3129,"path":3130,"stem":3131},"Pod — атомарна одиниця Kubernetes","\u002Ftools\u002Fkubernetes\u002Fpods-and-containers","07.tools\u002F02.kubernetes\u002F04.pods-and-containers",{"title":3133,"path":3134,"stem":3135},"Патерни використання Pod","\u002Ftools\u002Fkubernetes\u002Fpod-patterns","07.tools\u002F02.kubernetes\u002F05.pod-patterns",{"title":3137,"path":3138,"stem":3139},"Deployment — декларативне управління Pod","\u002Ftools\u002Fkubernetes\u002Fdeployment-basics","07.tools\u002F02.kubernetes\u002F06.deployment-basics",{"title":3141,"path":3142,"stem":3143},"Rolling Updates та управління життєвим циклом Deployment","\u002Ftools\u002Fkubernetes\u002Fdeployment-rolling-updates","07.tools\u002F02.kubernetes\u002F07.deployment-rolling-updates",{"title":3145,"path":3146,"stem":3147},"Service — мережева абстракція для Pod","\u002Ftools\u002Fkubernetes\u002Fservices-networking","07.tools\u002F02.kubernetes\u002F08.services-networking",{"title":3149,"icon":3150,"path":3151,"stem":3152,"children":3153,"page":59},"Software Engineering","i-lucide-code-2","\u002Fsoftware-engineering","09.software-engineering",[3154,3158,3162,3166,3170,3174,3178,3182,3186,3190,3194],{"title":3155,"path":3156,"stem":3157},"1. Аналіз предметної області. Експертні знання та складність","\u002Fsoftware-engineering\u002Fintro-subdomains","09.software-engineering\u002F01.intro-subdomains",{"title":3159,"path":3160,"stem":3161},"2. Обмежені контексти. Інтеграція обмежених контекстів","\u002Fsoftware-engineering\u002Fintegrating-limited-contexts","09.software-engineering\u002F02.integrating-limited-contexts",{"title":3163,"path":3164,"stem":3165},"3. Реалізація простої бізнес-логіки","\u002Fsoftware-engineering\u002Fsimple","09.software-engineering\u002F03.simple",{"title":3167,"path":3168,"stem":3169},"4. Опрацювання складної бізнес-логіки","\u002Fsoftware-engineering\u002Fcomplex-business-logic","09.software-engineering\u002F04.complex-business-logic",{"title":3171,"path":3172,"stem":3173},"5. Моделювання фактора часу. Подієво-орієнтована архітектура.","\u002Fsoftware-engineering\u002Fmodelling-the-time-factor","09.software-engineering\u002F05.modelling-the-time-factor",{"title":3175,"path":3176,"stem":3177},"6. Архітектурні патерни","\u002Fsoftware-engineering\u002Farchitectural-patterns","09.software-engineering\u002F06.architectural-patterns",{"title":3179,"path":3180,"stem":3181},"Паттерни взаємодії","\u002Fsoftware-engineering\u002Fpatterns-of-interaction","09.software-engineering\u002F07.patterns-of-interaction",{"title":3183,"path":3184,"stem":3185},"Евристика проєктування","\u002Fsoftware-engineering\u002Fdesign-heuristics","09.software-engineering\u002F08.design-heuristics",{"title":3187,"path":3188,"stem":3189},"Еволюція проєктних рішень","\u002Fsoftware-engineering\u002Fevolution-of-design-solutions","09.software-engineering\u002F09.evolution-of-design-solutions",{"title":3191,"path":3192,"stem":3193},"EventStorming","\u002Fsoftware-engineering\u002Feventstorming","09.software-engineering\u002F10.eventstorming",{"title":3195,"path":3196,"stem":3197},"DDD на практиці","\u002Fsoftware-engineering\u002Fddd-in-practice","09.software-engineering\u002F11.ddd-in-practice",{"title":3199,"icon":943,"path":3200,"stem":3201,"children":3202,"page":59},"DDD","\u002Fddd","10.ddd",[3203,3207,3211,3215,3219,3223,3227,3231,3235,3239,3243,3247,3251],{"title":3204,"path":3205,"stem":3206},"Аналіз предметної області","\u002Fddd\u002Fdomain-analysis","10.ddd\u002F01.domain-analysis",{"title":3208,"path":3209,"stem":3210},"Експертні знання про предметну область","\u002Fddd\u002Fdomain-expert-knowledge","10.ddd\u002F02.domain-expert-knowledge",{"title":3212,"path":3213,"stem":3214},"Як осмислити складність предметної області","\u002Fddd\u002Fmanaging-domain-complexity","10.ddd\u002F03.managing-domain-complexity",{"title":3216,"path":3217,"stem":3218},"Інтеграція обмежених контекстів","\u002Fddd\u002Fbounded-context-integration","10.ddd\u002F04.bounded-context-integration",{"title":3220,"path":3221,"stem":3222},"Реалізація простої бізнес-логіки","\u002Fddd\u002Fsimple-business-logic","10.ddd\u002F05.simple-business-logic",{"title":3224,"path":3225,"stem":3226},"Обробка складної бізнес-логіки","\u002Fddd\u002Fcomplex-business-logic","10.ddd\u002F06.complex-business-logic",{"title":3228,"path":3229,"stem":3230},"Моделювання фактора часу","\u002Fddd\u002Ftime-modeling","10.ddd\u002F07.time-modeling",{"title":3232,"path":3233,"stem":3234},"Глава 8. Архітектурні Патерни","\u002Fddd\u002Farchitectural-patterns","10.ddd\u002F08.architectural-patterns",{"title":3236,"path":3237,"stem":3238},"Глава 9. Патерни Взаємодії","\u002Fddd\u002Finteraction-patterns","10.ddd\u002F09.interaction-patterns",{"title":3240,"path":3241,"stem":3242},"Глава 10. Проектні Евристики","\u002Fddd\u002Fdesign-heuristics","10.ddd\u002F10.design-heuristics",{"title":3244,"path":3245,"stem":3246},"Глава 11. Еволюція Проектних Рішень","\u002Fddd\u002Fevolution-of-design-decisions","10.ddd\u002F11.evolution-of-design-decisions",{"title":3248,"path":3249,"stem":3250},"Глава 12. EventStorming","\u002Fddd\u002Fevent-storming","10.ddd\u002F12.event-storming",{"title":3252,"path":3253,"stem":3254},"Глава 13. DDD на Практиці","\u002Fddd\u002Fddd-in-practice","10.ddd\u002F13.ddd-in-practice",{"title":3256,"icon":3257,"path":3258,"stem":3259,"children":3260,"page":59},"Media Streaming","i-lucide-video","\u002Fmedia-streaming","11.media-streaming",[3261,3265,3269,3273,3277,3281,3285],{"title":3262,"path":3263,"stem":3264},"01. Магія Стрімінгу: Що відбувається, коли ви натискаєте \"Play\"","\u002Fmedia-streaming\u002Fintroduction","11.media-streaming\u002F01.introduction",{"title":3266,"path":3267,"stem":3268},"02. Анатомія Медіа: Кодеки, Контейнери та Стиснення","\u002Fmedia-streaming\u002Faudio-video-anatomy","11.media-streaming\u002F02.audio-video-anatomy",{"title":3270,"path":3271,"stem":3272},"03. The Gym: FFmpeg Deep Dive","\u002Fmedia-streaming\u002Fffmpeg-gym","11.media-streaming\u002F03.ffmpeg-gym",{"title":3274,"path":3275,"stem":3276},"04. HLS Protocol: HTTP Live Streaming у Деталях","\u002Fmedia-streaming\u002Fhls-protocol","11.media-streaming\u002F04.hls-protocol",{"title":3278,"path":3279,"stem":3280},"05. DASH Protocol: Відкритий Стандарт","\u002Fmedia-streaming\u002Fdash-protocol","11.media-streaming\u002F05.dash-protocol",{"title":3282,"path":3283,"stem":3284},"06. Масштабування: CDN та Adaptive Bitrate","\u002Fmedia-streaming\u002Fcdn-and-adaptive-bitrate","11.media-streaming\u002F06.cdn-and-adaptive-bitrate",{"title":3286,"path":3287,"stem":3288},"07. Війна із Затримкою (Latency)","\u002Fmedia-streaming\u002Frealtime-latency","11.media-streaming\u002F07.realtime-latency",{"title":3290,"icon":3291,"path":3292,"stem":3293,"children":3294,"page":59},"HTML & CSS","i-devicon-html5","\u002Fhtml-css","12.html-css",[3295,3299,3303,3307,3311,3315,3319,3323,3327,3331,3335,3339,3343,3347,3351,3355,3359,3363,3367,3371,3375,3379,3383,3387,3391,3395,3399,3403,3407,3411],{"title":3296,"path":3297,"stem":3298},"Вступ до HTML. Структура документа","\u002Fhtml-css\u002Fintro-html-structure","12.html-css\u002F01.intro-html-structure",{"title":3300,"path":3301,"stem":3302},"Форматування тексту в HTML","\u002Fhtml-css\u002Fhtml-text-formatting","12.html-css\u002F02.html-text-formatting",{"title":3304,"path":3305,"stem":3306},"Посилання та зображення в HTML","\u002Fhtml-css\u002Fhtml-links-images","12.html-css\u002F03.html-links-images",{"title":3308,"path":3309,"stem":3310},"Списки та таблиці в HTML","\u002Fhtml-css\u002Fhtml-lists-tables","12.html-css\u002F04.html-lists-tables",{"title":3312,"path":3313,"stem":3314},"Форми в HTML","\u002Fhtml-css\u002Fhtml-forms","12.html-css\u002F05.html-forms",{"title":3316,"path":3317,"stem":3318},"Семантичні елементи HTML5","\u002Fhtml-css\u002Fhtml-semantic-elements","12.html-css\u002F06.html-semantic-elements",{"title":3320,"path":3321,"stem":3322},"Мультимедіа та розширені елементи HTML","\u002Fhtml-css\u002Fhtml-multimedia-advanced","12.html-css\u002F07.html-multimedia-advanced",{"title":3324,"path":3325,"stem":3326},"Мікророзмітка та SEO в HTML","\u002Fhtml-css\u002Fhtml-microdata-seo","12.html-css\u002F08.html-microdata-seo",{"title":3328,"path":3329,"stem":3330},"Вступ до CSS. Селектори та специфічність","\u002Fhtml-css\u002Fcss-intro-selectors","12.html-css\u002F09.css-intro-selectors",{"title":3332,"path":3333,"stem":3334},"Блокова модель CSS. Відступи. Box Sizing","\u002Fhtml-css\u002Fcss-box-model","12.html-css\u002F10.css-box-model",{"title":3336,"path":3337,"stem":3338},"Розміри у CSS: повний довідник одиниць і ключових слів","\u002Fhtml-css\u002F10a.css-sizing","12.html-css\u002F10a.css-sizing",{"title":3340,"path":3341,"stem":3342},"Типографіка в CSS. Шрифти та текст","\u002Fhtml-css\u002Fcss-typography","12.html-css\u002F11.css-typography",{"title":3344,"path":3345,"stem":3346},"Кольори та фони в CSS","\u002Fhtml-css\u002Fcss-colors-backgrounds","12.html-css\u002F12.css-colors-backgrounds",{"title":3348,"path":3349,"stem":3350},"Тіні та фільтри в CSS","\u002Fhtml-css\u002F12b.css-shadows-filters","12.html-css\u002F12b.css-shadows-filters",{"title":3352,"path":3353,"stem":3354},"CSS Flexbox: Фундамент гнучких макетів","\u002Fhtml-css\u002Fcss-flexbox-fundamentals","12.html-css\u002F13.css-flexbox-fundamentals",{"title":3356,"path":3357,"stem":3358},"CSS Flexbox: Вирівнювання та Позиціонування","\u002Fhtml-css\u002Fcss-flexbox-alignment-sizing-and-patterns","12.html-css\u002F14.css-flexbox-alignment-sizing-and-patterns",{"title":3360,"path":3361,"stem":3362},"CSS Grid. Двовимірний макет. Частина 1","\u002Fhtml-css\u002Fcss-layout-grid","12.html-css\u002F15.css-layout-grid",{"title":3364,"path":3365,"stem":3366},"CSS Grid. Двовимірний макет. Частина 2","\u002Fhtml-css\u002Fcss-layout-grid-advanced","12.html-css\u002F16.css-layout-grid-advanced",{"title":3368,"path":3369,"stem":3370},"Позиціонування в CSS. Z-index. Stacking Context","\u002Fhtml-css\u002Fcss-positioning","12.html-css\u002F17.css-positioning",{"title":3372,"path":3373,"stem":3374},"CSS Анімації та Переходи","\u002Fhtml-css\u002Fcss-animations-transitions","12.html-css\u002F18.css-animations-transitions",{"title":3376,"path":3377,"stem":3378},"Адаптивний дизайн. Media Queries. Частина 1","\u002Fhtml-css\u002Fcss-responsive-media-queries","12.html-css\u002F19.css-responsive-media-queries",{"title":3380,"path":3381,"stem":3382},"Адаптивний дизайн. Частина 2: clamp(), Container Queries, @layer","\u002Fhtml-css\u002Fcss-responsive-advanced","12.html-css\u002F20.css-responsive-advanced",{"title":3384,"path":3385,"stem":3386},"CSS Custom Properties. Методології. Сучасний CSS","\u002Fhtml-css\u002Fcss-variables-methodologies","12.html-css\u002F21.css-variables-methodologies",{"title":3388,"path":3389,"stem":3390},"Сучасний CSS 2023–2025: Нові можливості","\u002Fhtml-css\u002Fcss-modern-features","12.html-css\u002F22.css-modern-features",{"title":3392,"path":3393,"stem":3394},"CSS Nesting, @layer, @scope та @property: нативний препроцесор","\u002Fhtml-css\u002F22a.css-nesting-modern-syntax","12.html-css\u002F22a.css-nesting-modern-syntax",{"title":3396,"path":3397,"stem":3398},"CSS для форм та інтерактивних станів","\u002Fhtml-css\u002Fcss-forms-interactive-states","12.html-css\u002F23.css-forms-interactive-states",{"title":3400,"path":3401,"stem":3402},"Доступність у CSS (CSS Accessibility)","\u002Fhtml-css\u002Fcss-accessibility","12.html-css\u002F24.css-accessibility",{"title":3404,"path":3405,"stem":3406},"CSS-функції та сучасні sizing primitives","\u002Fhtml-css\u002Fcss-functions-sizing","12.html-css\u002F25.css-functions-sizing",{"title":3408,"path":3409,"stem":3410},"Rendering Pipeline і CSS Performance","\u002Fhtml-css\u002Fcss-rendering-performance","12.html-css\u002F26.css-rendering-performance",{"title":3412,"path":3413,"stem":3414},"CSS Best Practices: типові ситуації та правильні рішення","\u002Fhtml-css\u002Fcss-best-practices","12.html-css\u002F27.css-best-practices",{"title":3416,"path":3417,"stem":3418,"children":3419,"page":59},"AWS","\u002Faws","13.aws",[3420,3424,3428,3432,3436,3440,3444,3448,3452,3456,3460,3464,3468,3472,3476,3480,3484,3488],{"title":3421,"path":3422,"stem":3423},"Реєстрація AWS акаунту та студентські програми","\u002Faws\u002Faccount-registration","13.aws\u002F00.account-registration",{"title":3425,"path":3426,"stem":3427},"Вступ до хмарних обчислень та AWS","\u002Faws\u002Fintroduction-to-cloud","13.aws\u002F01.introduction-to-cloud",{"title":3429,"path":3430,"stem":3431},"AWS IAM — Identity and Access Management","\u002Faws\u002Fiam","13.aws\u002F02.iam",{"title":3433,"path":3434,"stem":3435},"AWS IAM CLI — Довідник команд","\u002Faws\u002F02a.iam-doc","13.aws\u002F02a.iam-doc",{"title":3437,"path":3438,"stem":3439},"Docker та контейнеризація в AWS — ECR, ECS та Fargate","\u002Faws\u002Fdocker-ecs","13.aws\u002F03.docker-ecs",{"title":3441,"path":3442,"stem":3443},"AWS ECR \u002F ECS CLI — Довідник команд","\u002Faws\u002F03a.docker-ecs-doc","13.aws\u002F03a.docker-ecs-doc",{"title":3445,"path":3446,"stem":3447},"Amazon EC2 — Elastic Compute Cloud","\u002Faws\u002Fec2","13.aws\u002F04.ec2",{"title":3449,"path":3450,"stem":3451},"AWS EC2 CLI — Довідник команд","\u002Faws\u002F04a.ec2-doc","13.aws\u002F04a.ec2-doc",{"title":3453,"path":3454,"stem":3455},"Elastic Load Balancing та Auto Scaling","\u002Faws\u002Falb-asg","13.aws\u002F05.alb-asg",{"title":3457,"path":3458,"stem":3459},"Amazon S3 — Simple Storage Service","\u002Faws\u002Fs3","13.aws\u002F06.s3",{"title":3461,"path":3462,"stem":3463},"Amazon CloudFront — Content Delivery Network","\u002Faws\u002Fcloudfront","13.aws\u002F07.cloudfront",{"title":3465,"path":3466,"stem":3467},"Amazon RDS — Relational Database Service","\u002Faws\u002Frds","13.aws\u002F08.rds",{"title":3469,"path":3470,"stem":3471},"Amazon DynamoDB — NoSQL Database","\u002Faws\u002Fdynamodb","13.aws\u002F09.dynamodb",{"title":3473,"path":3474,"stem":3475},"AWS Lambda та Serverless Compute","\u002Faws\u002Flambda","13.aws\u002F10.lambda",{"title":3477,"path":3478,"stem":3479},"Amazon Bedrock - Foundation Models, RAG та Agents","\u002Faws\u002Fbedrock","13.aws\u002F22.bedrock",{"title":3481,"path":3482,"stem":3483},"Amazon Rekognition - Комп'ютерний зір","\u002Faws\u002Frekognition","13.aws\u002F23.rekognition",{"title":3485,"path":3486,"stem":3487},"Amazon Textract - Інтелектуальний аналіз документів","\u002Faws\u002Ftextract","13.aws\u002F24.textract",{"title":3489,"path":3490,"stem":3491},"Amazon Polly, Transcribe, Comprehend та Translate","\u002Faws\u002Faudio-nlp-services","13.aws\u002F25.audio-nlp-services",{"title":3493,"path":3494,"stem":3495,"children":3496,"page":59},"Ai Development","\u002Fai-development","14.ai-development",[3497],{"title":3498,"path":3499,"stem":3500,"children":3501,"page":59},"Foundations","\u002Fai-development\u002Ffoundations","14.ai-development\u002F00.foundations",[3502],{"title":3503,"path":3504,"stem":3505},"Модуль 0.1. Що таке Large Language Model (LLM)","\u002Fai-development\u002Ffoundations\u002Fwhat-is-llm","14.ai-development\u002F00.foundations\u002F01.what-is-llm",{"title":3507,"path":3508,"stem":3509,"children":3510,"page":59},"React Native","\u002Freact-native","15.react-native",[3511,3532],{"title":3512,"path":3513,"stem":3514,"children":3515,"page":59},"Version1","\u002Freact-native\u002Fversion1","15.react-native\u002Fversion1",[3516,3520,3524,3528],{"title":3517,"path":3518,"stem":3519},"Що таке React Native","\u002Freact-native\u002Fversion1\u002Fwhat-is-react-native","15.react-native\u002Fversion1\u002F01.what-is-react-native",{"title":3521,"path":3522,"stem":3523},"Як влаштований React Native «під капотом»","\u002Freact-native\u002Fversion1\u002Freact-native-architecture","15.react-native\u002Fversion1\u002F02.react-native-architecture",{"title":3525,"path":3526,"stem":3527},"Від React до React Native: ключові відмінності","\u002Freact-native\u002Fversion1\u002Freact-native-vs-react","15.react-native\u002Fversion1\u002F03.react-native-vs-react",{"title":3529,"path":3530,"stem":3531},"View та Text — фундаментальні будівельні блоки","\u002Freact-native\u002Fversion1\u002Fview-and-text","15.react-native\u002Fversion1\u002F04.view-and-text",{"title":3533,"path":3534,"stem":3535,"children":3536,"page":59},"Version2","\u002Freact-native\u002Fversion2","15.react-native\u002Fversion2",[3537,3541,3545,3549,3553,3557,3561,3565,3569,3573,3577,3581,3585,3589,3593,3597,3601,3605,3609,3613,3617,3621,3625,3629,3633,3637,3641],{"title":3538,"path":3539,"stem":3540},"React Native — навіщо він потрібен","\u002Freact-native\u002Fversion2\u002Fwhy-react-native","15.react-native\u002Fversion2\u002F01.why-react-native",{"title":3542,"path":3543,"stem":3544},"Налаштування середовища розробки","\u002Freact-native\u002Fversion2\u002Fenvironment-setup","15.react-native\u002Fversion2\u002F02.environment-setup",{"title":3546,"path":3547,"stem":3548},"Expo і класичний React Native — два шляхи одного фреймворку","\u002Freact-native\u002Fversion2\u002Fexpo-vs-cli-landscape","15.react-native\u002Fversion2\u002F03.expo-vs-cli-landscape",{"title":3550,"path":3551,"stem":3552},"Середовище Expo — перший запуск","\u002Freact-native\u002Fversion2\u002Fexpo-setup-and-tooling","15.react-native\u002Fversion2\u002F04.expo-setup-and-tooling",{"title":3554,"path":3555,"stem":3556},"Структура проєкту та перші UI-примітиви","\u002Freact-native\u002Fversion2\u002Fproject-structure-and-conventions","15.react-native\u002Fversion2\u002F05.project-structure-and-conventions",{"title":3558,"path":3559,"stem":3560},"Базові компоненти React Native","\u002Freact-native\u002Fversion2\u002Fcore-components","15.react-native\u002Fversion2\u002F06.core-components",{"title":3562,"path":3563,"stem":3564},"Flexbox і layout у React Native","\u002Freact-native\u002Fversion2\u002Fflexbox-and-layout","15.react-native\u002Fversion2\u002F07.flexbox-and-layout",{"title":3566,"path":3567,"stem":3568},"StyleSheet і теми (light \u002F dark)","\u002Freact-native\u002Fversion2\u002Fstylesheet-and-theming","15.react-native\u002Fversion2\u002F08.stylesheet-and-theming",{"title":3570,"path":3571,"stem":3572},"Списки та віртуалізація","\u002Freact-native\u002Fversion2\u002Flists-and-virtualization","15.react-native\u002Fversion2\u002F09.lists-and-virtualization",{"title":3574,"path":3575,"stem":3576},"Форми, ввід і валідація","\u002Freact-native\u002Fversion2\u002Fforms-input-validation","15.react-native\u002Fversion2\u002F10.forms-input-validation",{"title":3578,"path":3579,"stem":3580},"Основи Expo Router","\u002Freact-native\u002Fversion2\u002Fexpo-router-basics","15.react-native\u002Fversion2\u002F11.expo-router-basics",{"title":3582,"path":3583,"stem":3584},"Вкладені навігатори та модалки","\u002Freact-native\u002Fversion2\u002Fnested-navigators-and-modals","15.react-native\u002Fversion2\u002F12.nested-navigators-and-modals",{"title":3586,"path":3587,"stem":3588},"Deep linking і параметри маршрутів","\u002Freact-native\u002Fversion2\u002Fdeep-linking-and-params","15.react-native\u002Fversion2\u002F13.deep-linking-and-params",{"title":3590,"path":3591,"stem":3592},"Робота з мережею та життєвий цикл застосунку","\u002Freact-native\u002Fversion2\u002Fnetworking-and-app-lifecycle","15.react-native\u002Fversion2\u002F14.networking-and-app-lifecycle",{"title":3594,"path":3595,"stem":3596},"Redux Toolkit на мобільних платформах","\u002Freact-native\u002Fversion2\u002Fredux-toolkit-on-mobile","15.react-native\u002Fversion2\u002F15.redux-toolkit-on-mobile",{"title":3598,"path":3599,"stem":3600},"RTK Query на мобільних платформах","\u002Freact-native\u002Fversion2\u002Frtk-query-mobile","15.react-native\u002Fversion2\u002F16.rtk-query-mobile",{"title":3602,"path":3603,"stem":3604},"Автентифікація та Безпечне Зберігання","\u002Freact-native\u002Fversion2\u002Fauth-secure-storage","15.react-native\u002Fversion2\u002F18.auth-secure-storage",{"title":3606,"path":3607,"stem":3608},"Локальне сховище — AsyncStorage, MMKV, SQLite","\u002Freact-native\u002Fversion2\u002Flocal-storage-mmkv-sqlite","15.react-native\u002Fversion2\u002F19.local-storage-mmkv-sqlite",{"title":3610,"path":3611,"stem":3612},"Офлайн-First і синхронізація","\u002Freact-native\u002Fversion2\u002Foffline-first-sync","15.react-native\u002Fversion2\u002F20.offline-first-sync",{"title":3614,"path":3615,"stem":3616},"Камера, медіа та файлова система","\u002Freact-native\u002Fversion2\u002Fcamera-media-filesystem","15.react-native\u002Fversion2\u002F21.camera-media-filesystem",{"title":3618,"path":3619,"stem":3620},"Карти та геолокація","\u002Freact-native\u002Fversion2\u002Fmaps-and-location","15.react-native\u002Fversion2\u002F22.maps-and-location",{"title":3622,"path":3623,"stem":3624},"Жести та дотики","\u002Freact-native\u002Fversion2\u002Fgestures-and-touch","15.react-native\u002Fversion2\u002F23.gestures-and-touch",{"title":3626,"path":3627,"stem":3628},"Анімації з Reanimated","\u002Freact-native\u002Fversion2\u002Freanimated-animations","15.react-native\u002Fversion2\u002F24.reanimated-animations",{"title":3630,"path":3631,"stem":3632},"Push і локальні сповіщення","\u002Freact-native\u002Fversion2\u002Fpush-and-local-notifications","15.react-native\u002Fversion2\u002F25.push-and-local-notifications",{"title":3634,"path":3635,"stem":3636},"Інтернаціоналізація та доступність","\u002Freact-native\u002Fversion2\u002Faccessibility-and-i18n","15.react-native\u002Fversion2\u002F26.accessibility-and-i18n",{"title":3638,"path":3639,"stem":3640},"EAS Build та профілі збірки","\u002Freact-native\u002Fversion2\u002Feas-build-and-profiles","15.react-native\u002Fversion2\u002F29.eas-build-and-profiles",{"title":3642,"path":3643,"stem":3644},"Публікація в App Store та Google Play","\u002Freact-native\u002Fversion2\u002Fapp-store-play-release","15.react-native\u002Fversion2\u002F30.app-store-play-release",{"title":3646,"path":3647,"stem":3648,"children":3649,"page":59},"Ai Python","\u002Fai-python","16.ai-python",[3650,3659,3668,3677,3706,3732,3757,3790,3807,3820,3829,3842,3851,3872,3885,3906],{"title":3651,"path":3652,"stem":3653,"children":3654,"page":59},"Intro To Ai","\u002Fai-python\u002Fintro-to-ai","16.ai-python\u002F01.intro-to-ai",[3655],{"title":3656,"path":3657,"stem":3658},"Вступ до штучного інтелекту та машинного навчання","\u002Fai-python\u002Fintro-to-ai\u002Fintro-to-ai","16.ai-python\u002F01.intro-to-ai\u002F01.intro-to-ai",{"title":3660,"path":3661,"stem":3662,"children":3663,"page":59},"Jupyter Notebook","\u002Fai-python\u002Fjupyter-notebook","16.ai-python\u002F02.jupyter-notebook",[3664],{"title":3665,"path":3666,"stem":3667},"Знайомство з Jupyter Notebook та JupyterLab","\u002Fai-python\u002Fjupyter-notebook\u002Fjupyter-notebook","16.ai-python\u002F02.jupyter-notebook\u002F02.jupyter-notebook",{"title":3669,"path":3670,"stem":3671,"children":3672,"page":59},"Numpy Pandas","\u002Fai-python\u002Fnumpy-pandas","16.ai-python\u002F03.numpy-pandas",[3673],{"title":3674,"path":3675,"stem":3676},"Робота з даними з використанням NumPy і pandas","\u002Fai-python\u002Fnumpy-pandas\u002Fnumpy-pandas","16.ai-python\u002F03.numpy-pandas\u002F03.numpy-pandas",{"title":3678,"path":3679,"stem":3680,"children":3681,"page":59},"Statistics Basics","\u002Fai-python\u002Fstatistics-basics","16.ai-python\u002F04.statistics-basics",[3682,3686,3690,3694,3698,3702],{"title":3683,"path":3684,"stem":3685},"Випадкові величини та їх типи","\u002Fai-python\u002Fstatistics-basics\u002Frandom-variables","16.ai-python\u002F04.statistics-basics\u002F01.random-variables",{"title":3687,"path":3688,"stem":3689},"Міри центральної тенденції","\u002Fai-python\u002Fstatistics-basics\u002Fcentral-tendency","16.ai-python\u002F04.statistics-basics\u002F02.central-tendency",{"title":3691,"path":3692,"stem":3693},"Міри варіації (розсіювання)","\u002Fai-python\u002Fstatistics-basics\u002Fvariability","16.ai-python\u002F04.statistics-basics\u002F03.variability",{"title":3695,"path":3696,"stem":3697},"Розподіли випадкових величин","\u002Fai-python\u002Fstatistics-basics\u002Fdistributions","16.ai-python\u002F04.statistics-basics\u002F04.distributions",{"title":3699,"path":3700,"stem":3701},"Кореляція та взаємозв'язки","\u002Fai-python\u002Fstatistics-basics\u002Fcorrelation","16.ai-python\u002F04.statistics-basics\u002F05.correlation",{"title":3703,"path":3704,"stem":3705},"Викиди та аномалії","\u002Fai-python\u002Fstatistics-basics\u002Foutliers","16.ai-python\u002F04.statistics-basics\u002F06.outliers",{"title":3707,"path":3708,"stem":3709,"children":3710},"Візуалізація даних за допомогою matplotlib","\u002Fai-python\u002Fdata-visualization","16.ai-python\u002F05.data-visualization\u002Findex",[3711,3712,3716,3720,3724,3728],{"title":3707,"path":3708,"stem":3709},{"title":3713,"path":3714,"stem":3715},"Основи matplotlib — Figure, Axes та перший графік","\u002Fai-python\u002Fdata-visualization\u002Fmatplotlib-basics","16.ai-python\u002F05.data-visualization\u002F01.matplotlib-basics",{"title":3717,"path":3718,"stem":3719},"Візуалізація розподілів — гістограми та box plots","\u002Fai-python\u002Fdata-visualization\u002Fdistributions","16.ai-python\u002F05.data-visualization\u002F02.distributions",{"title":3721,"path":3722,"stem":3723},"Візуалізація залежностей — scatter plots та кореляція","\u002Fai-python\u002Fdata-visualization\u002Frelationships","16.ai-python\u002F05.data-visualization\u002F03.relationships",{"title":3725,"path":3726,"stem":3727},"Візуалізація категоріальних даних — bar charts та pie charts","\u002Fai-python\u002Fdata-visualization\u002Fcategorical","16.ai-python\u002F05.data-visualization\u002F04.categorical",{"title":3729,"path":3730,"stem":3731},"Композиції та стилізація — subplots та багатопанельні дашборди","\u002Fai-python\u002Fdata-visualization\u002Fsubplots-styling","16.ai-python\u002F05.data-visualization\u002F05.subplots-styling",{"title":3733,"path":3734,"stem":3735,"children":3736,"page":59},"Linear Regression","\u002Fai-python\u002Flinear-regression","16.ai-python\u002F06.linear-regression",[3737,3741,3745,3749,3753],{"title":3738,"path":3739,"stem":3740},"Регресійна задача та лінійна регресія з однією змінною","\u002Fai-python\u002Flinear-regression\u002Fregression-task","16.ai-python\u002F06.linear-regression\u002F01.regression-task",{"title":3742,"path":3743,"stem":3744},"Метрики якості регресії — як оцінити модель","\u002Fai-python\u002Flinear-regression\u002Fquality-metrics","16.ai-python\u002F06.linear-regression\u002F02.quality-metrics",{"title":3746,"path":3747,"stem":3748},"Градієнтний спуск — як модель навчається","\u002Fai-python\u002Flinear-regression\u002Fgradient-descent","16.ai-python\u002F06.linear-regression\u002F03.gradient-descent",{"title":3750,"path":3751,"stem":3752},"Множинна лінійна регресія — модель з багатьма ознаками","\u002Fai-python\u002Flinear-regression\u002Fmultiple-regression","16.ai-python\u002F06.linear-regression\u002F04.multiple-regression",{"title":3754,"path":3755,"stem":3756},"Практичні завдання та резюме модуля","\u002Fai-python\u002Flinear-regression\u002Fpractice","16.ai-python\u002F06.linear-regression\u002F05.practice",{"title":3758,"path":3759,"stem":3760,"children":3761,"page":59},"Practical Regression","\u002Fai-python\u002Fpractical-regression","16.ai-python\u002F07.practical-regression",[3762,3766,3770,3774,3778,3782,3786],{"title":3763,"path":3764,"stem":3765},"Знайомство з scikit-learn","\u002Fai-python\u002Fpractical-regression\u002Fintro-scikit-learn","16.ai-python\u002F07.practical-regression\u002F01.intro-scikit-learn",{"title":3767,"path":3768,"stem":3769},"Exploratory Data Analysis датасету Housing Prices","\u002Fai-python\u002Fpractical-regression\u002Fhousing-dataset-eda","16.ai-python\u002F07.practical-regression\u002F02.housing-dataset-eda",{"title":3771,"path":3772,"stem":3773},"Попередня обробка даних (Data Preprocessing)","\u002Fai-python\u002Fpractical-regression\u002Fdata-preprocessing","16.ai-python\u002F07.practical-regression\u002F03.data-preprocessing",{"title":3775,"path":3776,"stem":3777},"Train\u002FTest Split та перша повноцінна модель","\u002Fai-python\u002Fpractical-regression\u002Ftrain-test-split","16.ai-python\u002F07.practical-regression\u002F04.train-test-split",{"title":3779,"path":3780,"stem":3781},"Перенавчання та недонавчання","\u002Fai-python\u002Fpractical-regression\u002Foverfitting-underfitting","16.ai-python\u002F07.practical-regression\u002F05.overfitting-underfitting",{"title":3783,"path":3784,"stem":3785},"Крос-валідація (Cross-Validation)","\u002Fai-python\u002Fpractical-regression\u002Fcross-validation","16.ai-python\u002F07.practical-regression\u002F06.cross-validation",{"title":3787,"path":3788,"stem":3789},"Гіперпараметри та їх оптимізація","\u002Fai-python\u002Fpractical-regression\u002Fhyperparameter-tuning","16.ai-python\u002F07.practical-regression\u002F07.hyperparameter-tuning",{"title":3791,"path":3792,"stem":3793,"children":3794,"page":59},"Polynomial Regression","\u002Fai-python\u002Fpolynomial-regression","16.ai-python\u002F08.polynomial-regression",[3795,3799,3803],{"title":3796,"path":3797,"stem":3798},"Нелінійні залежності та поліноміальна регресія","\u002Fai-python\u002Fpolynomial-regression\u002Fnonlinear-patterns","16.ai-python\u002F08.polynomial-regression\u002F01.nonlinear-patterns",{"title":3800,"path":3801,"stem":3802},"Регуляризація в регресії — Ridge та Lasso","\u002Fai-python\u002Fpolynomial-regression\u002Fregularization-methods","16.ai-python\u002F08.polynomial-regression\u002F02.regularization-methods",{"title":3804,"path":3805,"stem":3806},"Практика — поліноміальна регресія та регуляризація на Housing Prices","\u002Fai-python\u002Fpolynomial-regression\u002Fhousing-prices-practice","16.ai-python\u002F08.polynomial-regression\u002F03.housing-prices-practice",{"title":3808,"path":3809,"stem":3810,"children":3811,"page":59},"Decision Trees Random Forest","\u002Fai-python\u002Fdecision-trees-random-forest","16.ai-python\u002F09.decision-trees-random-forest",[3812,3816],{"title":3813,"path":3814,"stem":3815},"Дерева рішень — інтерпретабельні моделі машинного навчання","\u002Fai-python\u002Fdecision-trees-random-forest\u002Fdecision-trees","16.ai-python\u002F09.decision-trees-random-forest\u002F01.decision-trees",{"title":3817,"path":3818,"stem":3819},"Random Forest — ансамблі дерев рішень","\u002Fai-python\u002Fdecision-trees-random-forest\u002Frandom-forest","16.ai-python\u002F09.decision-trees-random-forest\u002F02.random-forest",{"title":3821,"path":3822,"stem":3823,"children":3824,"page":59},"Gradient Boosting","\u002Fai-python\u002Fgradient-boosting","16.ai-python\u002F10.gradient-boosting",[3825],{"title":3826,"path":3827,"stem":3828},"Градієнтний бустинг та XGBoost — послідовне виправлення помилок","\u002Fai-python\u002Fgradient-boosting\u002Fgradient-boosting-xgboost","16.ai-python\u002F10.gradient-boosting\u002F01.gradient-boosting-xgboost",{"title":3830,"path":3831,"stem":3832,"children":3833,"page":59},"Logistic Regression Classification","\u002Fai-python\u002Flogistic-regression-classification","16.ai-python\u002F11.logistic-regression-classification",[3834,3838],{"title":3835,"path":3836,"stem":3837},"Вступ до класифікації та логістична регресія","\u002Fai-python\u002Flogistic-regression-classification\u002Fclassification-basics","16.ai-python\u002F11.logistic-regression-classification\u002F01.classification-basics",{"title":3839,"path":3840,"stem":3841},"Метрики якості класифікації — Confusion Matrix, Precision, Recall, F1","\u002Fai-python\u002Flogistic-regression-classification\u002Fclassification-metrics","16.ai-python\u002F11.logistic-regression-classification\u002F02.classification-metrics",{"title":3843,"path":3844,"stem":3845,"children":3846,"page":59},"Neural Networks Basics","\u002Fai-python\u002Fneural-networks-basics","16.ai-python\u002F12.neural-networks-basics",[3847],{"title":3848,"path":3849,"stem":3850},"Вступ до нейронних мереж — від персептрона до багатошарових мереж","\u002Fai-python\u002Fneural-networks-basics\u002Fperceptron-to-mlp","16.ai-python\u002F12.neural-networks-basics\u002F01.perceptron-to-mlp",{"title":3852,"path":3853,"stem":3854,"children":3855,"page":59},"Pytorch Intro","\u002Fai-python\u002Fpytorch-intro","16.ai-python\u002F13.pytorch-intro",[3856,3860,3864,3868],{"title":3857,"path":3858,"stem":3859},"Тензори та автоматичне диференціювання в PyTorch","\u002Fai-python\u002Fpytorch-intro\u002Ftensors-and-autograd","16.ai-python\u002F13.pytorch-intro\u002F01.tensors-and-autograd",{"title":3861,"path":3862,"stem":3863},"Побудова та тренування нейронних мереж у PyTorch","\u002Fai-python\u002Fpytorch-intro\u002Fbuilding-and-training","16.ai-python\u002F13.pytorch-intro\u002F02.building-and-training",{"title":3865,"path":3866,"stem":3867},"Робота з даними та регуляризація в PyTorch","\u002Fai-python\u002Fpytorch-intro\u002Fdata-and-regularization","16.ai-python\u002F13.pytorch-intro\u002F03.data-and-regularization",{"title":3869,"path":3870,"stem":3871},"Просунуті теми PyTorch — GPU, оптимізація та deployment","\u002Fai-python\u002Fpytorch-intro\u002Fadvanced-topics","16.ai-python\u002F13.pytorch-intro\u002F04.advanced-topics",{"title":3873,"path":3874,"stem":3875,"children":3876,"page":59},"Activation Functions Heart Disease","\u002Fai-python\u002Factivation-functions-heart-disease","16.ai-python\u002F14.activation-functions-heart-disease",[3877,3881],{"title":3878,"path":3879,"stem":3880},"Функції активації та побудова нейронної мережі для передбачення вад серця","\u002Fai-python\u002Factivation-functions-heart-disease\u002Fheart-disease-prediction","16.ai-python\u002F14.activation-functions-heart-disease\u002F01.heart-disease-prediction",{"title":3882,"path":3883,"stem":3884},"Бонус — Повний приклад Student Performance Prediction","\u002Fai-python\u002Factivation-functions-heart-disease\u002Fstudent-performance-bonus","16.ai-python\u002F14.activation-functions-heart-disease\u002F02.student-performance-bonus",{"title":3886,"path":3887,"stem":3888,"children":3889,"page":59},"Cnn Image Classification","\u002Fai-python\u002Fcnn-image-classification","16.ai-python\u002F15.cnn-image-classification",[3890,3894,3898,3902],{"title":3891,"path":3892,"stem":3893},"Основи згорткових нейронних мереж — чому не MLP?","\u002Fai-python\u002Fcnn-image-classification\u002Fcnn-fundamentals","16.ai-python\u002F15.cnn-image-classification\u002F01.cnn-fundamentals",{"title":3895,"path":3896,"stem":3897},"Практична імплементація CNN для класифікації MNIST","\u002Fai-python\u002Fcnn-image-classification\u002Fmnist-classification","16.ai-python\u002F15.cnn-image-classification\u002F02.mnist-classification",{"title":3899,"path":3900,"stem":3901},"Глибші CNN та аугментація даних для CIFAR-10","\u002Fai-python\u002Fcnn-image-classification\u002Fcifar10-and-data-augmentation","16.ai-python\u002F15.cnn-image-classification\u002F03.cifar10-and-data-augmentation",{"title":3903,"path":3904,"stem":3905},"Transfer Learning та візуалізація внутрішніх представлень CNN","\u002Fai-python\u002Fcnn-image-classification\u002Ftransfer-learning-and-visualization","16.ai-python\u002F15.cnn-image-classification\u002F04.transfer-learning-and-visualization",{"title":3907,"path":3908,"stem":3909,"children":3910,"page":59},"Batching Normalization Deep Networks","\u002Fai-python\u002Fbatching-normalization-deep-networks","16.ai-python\u002F16.batching-normalization-deep-networks",[3911,3915,3919,3923,3927,3931,3935],{"title":3912,"path":3913,"stem":3914},"Mini-batch Gradient Descent та ефективна обробка даних","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fmini-batch-gradient-descent","16.ai-python\u002F16.batching-normalization-deep-networks\u002F01.mini-batch-gradient-descent",{"title":3916,"path":3917,"stem":3918},"Ініціалізація ваг — фундамент стабільного навчання","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fweight-initialization","16.ai-python\u002F16.batching-normalization-deep-networks\u002F02.weight-initialization",{"title":3920,"path":3921,"stem":3922},"Batch Normalization — прорив у глибокому навчанні","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fbatch-normalization","16.ai-python\u002F16.batching-normalization-deep-networks\u002F03.batch-normalization",{"title":3924,"path":3925,"stem":3926},"Dropout та комбіновані стратегії регуляризації","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fdropout-and-regularization","16.ai-python\u002F16.batching-normalization-deep-networks\u002F04.dropout-and-regularization",{"title":3928,"path":3929,"stem":3930},"Проєктування глибоких мереж — від теорії до практики","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Fdeep-networks-architectures","16.ai-python\u002F16.batching-normalization-deep-networks\u002F05.deep-networks-architectures",{"title":3932,"path":3933,"stem":3934},"Планування learning rate — коли та як зменшувати крок навчання","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Flearning-rate-scheduling","16.ai-python\u002F16.batching-normalization-deep-networks\u002F06.learning-rate-scheduling",{"title":3936,"path":3937,"stem":3938},"Підсумковий проєкт — побудова сучасного класифікатора зображень","\u002Fai-python\u002Fbatching-normalization-deep-networks\u002Ffinal-project-deep-classifier","16.ai-python\u002F16.batching-normalization-deep-networks\u002F07.final-project-deep-classifier",{"title":3940,"icon":658,"path":3941,"stem":3942,"children":3943,"page":59},"Клієнт-серверна архітектура","\u002Fclient-server-architecture","17.client-server-architecture",[3944,3948,3952,3956,3960,3964,3968,3972,3976,3980,3984,3988,3992,3996,4000,4004,4008,4012],{"title":3945,"path":3946,"stem":3947},"Архітектура клієнт-серверних систем та основи Go","\u002Fclient-server-architecture\u002Fclient-server-architecture-and-go","17.client-server-architecture\u002F01.client-server-architecture-and-go",{"title":3949,"path":3950,"stem":3951},"Система типів та модель пам’яті мови Go","\u002Fclient-server-architecture\u002Ftype-system-and-memory-model","17.client-server-architecture\u002F02.type-system-and-memory-model",{"title":3953,"path":3954,"stem":3955},"Інтерфейси та модель конкурентності мови Go","\u002Fclient-server-architecture\u002Finterfaces-and-concurrency-model","17.client-server-architecture\u002F03.interfaces-and-concurrency-model",{"title":3957,"path":3958,"stem":3959},"Сокетне програмування та протокол TCP у Go","\u002Fclient-server-architecture\u002Ftcp-socket-programming","17.client-server-architecture\u002F04.tcp-socket-programming",{"title":3961,"path":3962,"stem":3963},"Протокол UDP та датаграмна передача даних","\u002Fclient-server-architecture\u002Fudp-datagram-transmission","17.client-server-architecture\u002F05.udp-datagram-transmission",{"title":3965,"path":3966,"stem":3967},"Криптографічний захист каналів зв","\u002Fclient-server-architecture\u002Ftls-cryptographic-channel-protection","17.client-server-architecture\u002F06.tls-cryptographic-channel-protection",{"title":3969,"path":3970,"stem":3971},"Прикладні мережеві протоколи DNS та SMTP","\u002Fclient-server-architecture\u002Fdns-smtp-application-protocols","17.client-server-architecture\u002F07.dns-smtp-application-protocols",{"title":3973,"path":3974,"stem":3975},"Протокол HTTP та стандартний вебсервер Go","\u002Fclient-server-architecture\u002Fhttp-protocol-and-web-server","17.client-server-architecture\u002F08.http-protocol-and-web-server",{"title":3977,"path":3978,"stem":3979},"Проєктування REST API та маршрутизація засобами Chi","\u002Fclient-server-architecture\u002Frest-api-design-and-chi-routing","17.client-server-architecture\u002F09.rest-api-design-and-chi-routing",{"title":3981,"path":3982,"stem":3983},"Лекція 10. Шарувата архітектура та конвеєри обробки запитів","\u002Fclient-server-architecture\u002Flayered-architecture-and-middleware-pipelines","17.client-server-architecture\u002F10.layered-architecture-and-middleware-pipelines",{"title":3985,"path":3986,"stem":3987},"Лекція 11. Архітектура та маршрутизація фреймворку Gin","\u002Fclient-server-architecture\u002Fgin-framework-architecture-and-routing","17.client-server-architecture\u002F11.gin-framework-architecture-and-routing",{"title":3989,"path":3990,"stem":3991},"Лекція 12. Валідація даних, безпека та документування у Gin","\u002Fclient-server-architecture\u002Fdata-validation-security-and-documentation-in-gin","17.client-server-architecture\u002F12.data-validation-security-and-documentation-in-gin",{"title":3993,"path":3994,"stem":3995},"Лекція 13. Взаємодія з реляційними СУБД та технології ORM","\u002Fclient-server-architecture\u002Frelational-databases-and-orm","17.client-server-architecture\u002F13.relational-databases-and-orm",{"title":3997,"path":3998,"stem":3999},"Потокова передача даних та протокол WebSocket","\u002Fclient-server-architecture\u002Fstreaming-data-and-websockets","17.client-server-architecture\u002F14.streaming-data-and-websockets",{"title":4001,"path":4002,"stem":4003},"Міжсервісна взаємодія на основі протоколу gRPC","\u002Fclient-server-architecture\u002Fgrpc-inter-service-communication","17.client-server-architecture\u002F15.grpc-inter-service-communication",{"title":4005,"path":4006,"stem":4007},"Асинхронний обмін повідомленнями та протоколи черг","\u002Fclient-server-architecture\u002Fasynchronous-message-exchange-and-queue-protocols","17.client-server-architecture\u002F16.asynchronous-message-exchange-and-queue-protocols",{"title":4009,"path":4010,"stem":4011},"Протоколи потокового медіа та технологія WebRTC","\u002Fclient-server-architecture\u002Fstreaming-media-protocols-and-webrtc","17.client-server-architecture\u002F17.streaming-media-protocols-and-webrtc",{"title":4013,"path":4014,"stem":4015},"Моніторинг, безпека та контейнеризація застосунків","\u002Fclient-server-architecture\u002Fmonitoring-security-and-containerization","17.client-server-architecture\u002F18.monitoring-security-and-containerization",{"title":4017,"icon":2074,"path":4018,"stem":4019,"children":4020,"page":59},"Розробка WEB-застосувань","\u002Fweb-development","18.web-development",[4021,4066,4104,4133,4162,4219,4269,4363,4429,4511,4544,4572,4614,4660,4703],{"title":4022,"icon":658,"path":4023,"stem":4024,"children":4025,"page":59},"Архітектура комп'ютерних мереж та мережеві протоколи","\u002Fweb-development\u002Fnetwork-architecture-and-protocols","18.web-development\u002F01.network-architecture-and-protocols",[4026,4030,4034,4038,4042,4046,4050,4054,4058,4062],{"title":4027,"path":4028,"stem":4029},"Еволюція веброзробки та модель клієнт-сервер","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fweb-evolution-client-server","18.web-development\u002F01.network-architecture-and-protocols\u002F01.web-evolution-client-server",{"title":4031,"path":4032,"stem":4033},"Еталонна модель OSI","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fosi-model","18.web-development\u002F01.network-architecture-and-protocols\u002F02.osi-model",{"title":4035,"path":4036,"stem":4037},"Стек протоколів TCP\u002FIP","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Ftcp-ip-stack","18.web-development\u002F01.network-architecture-and-protocols\u002F03.tcp-ip-stack",{"title":4039,"path":4040,"stem":4041},"IP-адресація, порти та сокети","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fip-addressing-ports-sockets","18.web-development\u002F01.network-architecture-and-protocols\u002F04.ip-addressing-ports-sockets",{"title":4043,"path":4044,"stem":4045},"Протоколи TCP та UDP","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Ftcp-udp-protocols","18.web-development\u002F01.network-architecture-and-protocols\u002F05.tcp-udp-protocols",{"title":4047,"path":4048,"stem":4049},"Система доменних імен DNS","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fdns-system","18.web-development\u002F01.network-architecture-and-protocols\u002F06.dns-system",{"title":4051,"path":4052,"stem":4053},"Протокол SMTP та поштові протоколи","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fsmtp-email-protocols","18.web-development\u002F01.network-architecture-and-protocols\u002F07.smtp-email-protocols",{"title":4055,"path":4056,"stem":4057},"Протокол WebSocket","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fwebsocket-protocol","18.web-development\u002F01.network-architecture-and-protocols\u002F08.websocket-protocol",{"title":4059,"path":4060,"stem":4061},"Протокол SSH","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fssh-protocol","18.web-development\u002F01.network-architecture-and-protocols\u002F09.ssh-protocol",{"title":4063,"path":4064,"stem":4065},"Огляд сучасних серверних технологій","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fmodern-backend-technologies","18.web-development\u002F01.network-architecture-and-protocols\u002F10.modern-backend-technologies",{"title":4067,"icon":4068,"path":4069,"stem":4070,"children":4071,"page":59},"Протокол HTTP та захищена передача даних HTTPS","i-lucide-lock","\u002Fweb-development\u002Fhttp-and-https","18.web-development\u002F02.http-and-https",[4072,4076,4080,4084,4088,4092,4096,4100],{"title":4073,"path":4074,"stem":4075},"Вступ до протоколу HTTP та еволюція веб-технологій","\u002Fweb-development\u002Fhttp-and-https\u002Fintroduction-and-evolution","18.web-development\u002F02.http-and-https\u002F01.introduction-and-evolution",{"title":4077,"path":4078,"stem":4079},"Анатомія HTTP-запиту","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-request-structure","18.web-development\u002F02.http-and-https\u002F02.http-request-structure",{"title":4081,"path":4082,"stem":4083},"Анатомія HTTP-відповіді","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-response-structure","18.web-development\u002F02.http-and-https\u002F03.http-response-structure",{"title":4085,"path":4086,"stem":4087},"Методи HTTP та їхня семантика","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-methods","18.web-development\u002F02.http-and-https\u002F04.http-methods",{"title":4089,"path":4090,"stem":4091},"Коди статусу HTTP та їхнє призначення","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-status-codes","18.web-development\u002F02.http-and-https\u002F05.http-status-codes",{"title":4093,"path":4094,"stem":4095},"HTTP-заголовки та їхнє призначення","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-headers","18.web-development\u002F02.http-and-https\u002F06.http-headers",{"title":4097,"path":4098,"stem":4099},"CORS та механізми безпеки HTTP","\u002Fweb-development\u002Fhttp-and-https\u002Fcors-and-security","18.web-development\u002F02.http-and-https\u002F07.cors-and-security",{"title":4101,"path":4102,"stem":4103},"HTTPS та криптографічні основи TLS","\u002Fweb-development\u002Fhttp-and-https\u002Fhttps-and-tls","18.web-development\u002F02.http-and-https\u002F08.https-and-tls",{"title":4105,"icon":2454,"path":4106,"stem":4107,"children":4108,"page":59},"Система типів мови TypeScript","\u002Fweb-development\u002Ftypescript-type-system","18.web-development\u002F03.typescript-type-system",[4109,4113,4117,4121,4125,4129],{"title":4110,"path":4111,"stem":4112},"Знайомство з TypeScript Compiler","\u002Fweb-development\u002Ftypescript-type-system\u002Fintroduction-compiler-config","18.web-development\u002F03.typescript-type-system\u002F01.introduction-compiler-config",{"title":4114,"path":4115,"stem":4116},"Примітивні типи даних: string, number, boolean","\u002Fweb-development\u002Ftypescript-type-system\u002Fprimitive-special-types","18.web-development\u002F03.typescript-type-system\u002F02.primitive-special-types",{"title":4118,"path":4119,"stem":4120},"Масиви, кортежі та об","\u002Fweb-development\u002Ftypescript-type-system\u002Farrays-tuples-objects","18.web-development\u002F03.typescript-type-system\u002F03.arrays-tuples-objects",{"title":4122,"path":4123,"stem":4124},"Псевдоніми типів, Union типи, Intersection типи та літеральні типи","\u002Fweb-development\u002Ftypescript-type-system\u002Funion-intersection-literals","18.web-development\u002F03.typescript-type-system\u002F04.union-intersection-literals",{"title":4126,"path":4127,"stem":4128},"Type Narrowing (звуження типів)","\u002Fweb-development\u002Ftypescript-type-system\u002Ftype-narrowing","18.web-development\u002F03.typescript-type-system\u002F05.type-narrowing",{"title":4130,"path":4131,"stem":4132},"Типізація функцій","\u002Fweb-development\u002Ftypescript-type-system\u002Ffunctions-typing","18.web-development\u002F03.typescript-type-system\u002F06.functions-typing",{"title":4134,"icon":2454,"path":4135,"stem":4136,"children":4137,"page":59},"Розширені засоби мови TypeScript","\u002Fweb-development\u002Ftypescript-advanced","18.web-development\u002F04.typescript-advanced",[4138,4142,4146,4150,4154,4158],{"title":4139,"path":4140,"stem":4141},"Interfaces та Classes","\u002Fweb-development\u002Ftypescript-advanced\u002Finterfaces-classes","18.web-development\u002F04.typescript-advanced\u002F01.interfaces-classes",{"title":4143,"path":4144,"stem":4145},"Основи Generic типів","\u002Fweb-development\u002Ftypescript-advanced\u002Fgenerics-fundamentals","18.web-development\u002F04.typescript-advanced\u002F02.generics-fundamentals",{"title":4147,"path":4148,"stem":4149},"Enums та Decorators","\u002Fweb-development\u002Ftypescript-advanced\u002Fenums-decorators","18.web-development\u002F04.typescript-advanced\u002F03.enums-decorators",{"title":4151,"path":4152,"stem":4153},"Utility Types","\u002Fweb-development\u002Ftypescript-advanced\u002Futility-types","18.web-development\u002F04.typescript-advanced\u002F04.utility-types",{"title":4155,"path":4156,"stem":4157},"Mapped та Conditional Types","\u002Fweb-development\u002Ftypescript-advanced\u002Fmapped-conditional-types","18.web-development\u002F04.typescript-advanced\u002F05.mapped-conditional-types",{"title":4159,"path":4160,"stem":4161},"Модулі та Strict Mode","\u002Fweb-development\u002Ftypescript-advanced\u002Fmodules-strict-mode","18.web-development\u002F04.typescript-advanced\u002F06.modules-strict-mode",{"title":4163,"icon":4164,"path":4165,"stem":4166,"children":4167,"page":59},"Платформа Node.js як середовище виконання","i-devicon-nodejs","\u002Fweb-development\u002Fnodejs-platform","18.web-development\u002F05.nodejs-platform",[4168,4172,4176,4180,4184,4188,4192,4196,4200,4204,4208,4211,4215],{"title":4169,"path":4170,"stem":4171},"Що таке Node.js та його архітектура","\u002Fweb-development\u002Fnodejs-platform\u002Fwhat-is-nodejs","18.web-development\u002F05.nodejs-platform\u002F01.what-is-nodejs",{"title":4173,"path":4174,"stem":4175},"Event Loop — серце Node.js","\u002Fweb-development\u002Fnodejs-platform\u002Fevent-loop","18.web-development\u002F05.nodejs-platform\u002F02.event-loop",{"title":4177,"path":4178,"stem":4179},"Модульні системи: CommonJS vs ES Modules","\u002Fweb-development\u002Fnodejs-platform\u002Fmodule-systems","18.web-development\u002F05.nodejs-platform\u002F03.module-systems",{"title":4181,"path":4182,"stem":4183},"npm та package.json","\u002Fweb-development\u002Fnodejs-platform\u002Fnpm-package-json","18.web-development\u002F05.nodejs-platform\u002F04.npm-package-json",{"title":4185,"path":4186,"stem":4187},"Глобальні об\\","\u002Fweb-development\u002Fnodejs-platform\u002Fglobal-objects","18.web-development\u002F05.nodejs-platform\u002F05.global-objects",{"title":4189,"path":4190,"stem":4191},"Вбудований модуль fs (File System)","\u002Fweb-development\u002Fnodejs-platform\u002Fbuilt-in-modules-fs","18.web-development\u002F05.nodejs-platform\u002F06.built-in-modules-fs",{"title":4193,"path":4194,"stem":4195},"Вбудований модуль path","\u002Fweb-development\u002Fnodejs-platform\u002Fbuilt-in-modules-path","18.web-development\u002F05.nodejs-platform\u002F07.built-in-modules-path",{"title":4197,"path":4198,"stem":4199},"Вбудований модуль http","\u002Fweb-development\u002Fnodejs-platform\u002Fbuilt-in-modules-http","18.web-development\u002F05.nodejs-platform\u002F08.built-in-modules-http",{"title":4201,"path":4202,"stem":4203},"Streams — потоки даних у Node.js","\u002Fweb-development\u002Fnodejs-platform\u002Fstreams","18.web-development\u002F05.nodejs-platform\u002F09.streams",{"title":4205,"path":4206,"stem":4207},"Вбудований модуль util (Utilities)","\u002Fweb-development\u002Fnodejs-platform\u002Fbuilt-in-modules-util","18.web-development\u002F05.nodejs-platform\u002F10.built-in-modules-util",{"title":3097,"path":4209,"stem":4210},"\u002Fweb-development\u002Fnodejs-platform\u002Fenvironment-variables","18.web-development\u002F05.nodejs-platform\u002F11.environment-variables",{"title":4212,"path":4213,"stem":4214},"Інструменти налагодження та розробки","\u002Fweb-development\u002Fnodejs-platform\u002Fdebugging-tools","18.web-development\u002F05.nodejs-platform\u002F12.debugging-tools",{"title":4216,"path":4217,"stem":4218},"Продуктивність та Best Practices","\u002Fweb-development\u002Fnodejs-platform\u002Fperformance-best-practices","18.web-development\u002F05.nodejs-platform\u002F13.performance-best-practices",{"title":4220,"icon":4221,"path":4222,"stem":4223,"children":4224,"page":59},"Асинхронне програмування у Node.js","i-lucide-clock","\u002Fweb-development\u002Fasync-programming-nodejs","18.web-development\u002F06.async-programming-nodejs",[4225,4229,4233,4237,4241,4245,4249,4253,4257,4261,4265],{"title":4226,"path":4227,"stem":4228},"Синхронний vs асинхронний код","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fsync-vs-async","18.web-development\u002F06.async-programming-nodejs\u002F01.sync-vs-async",{"title":4230,"path":4231,"stem":4232},"Callbacks — перша парадигма асинхронності","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fcallbacks","18.web-development\u002F06.async-programming-nodejs\u002F02.callbacks",{"title":4234,"path":4235,"stem":4236},"Promises — стандарт асинхронності","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fpromises","18.web-development\u002F06.async-programming-nodejs\u002F03.promises",{"title":4238,"path":4239,"stem":4240},"Promise комбінатори","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fpromise-combinators","18.web-development\u002F06.async-programming-nodejs\u002F04.promise-combinators",{"title":4242,"path":4243,"stem":4244},"Async\u002FAwait — синтаксичний цукор над Promises","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fasync-await","18.web-development\u002F06.async-programming-nodejs\u002F05.async-await",{"title":4246,"path":4247,"stem":4248},"Паралельне vs послідовне виконання","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fparallel-vs-sequential","18.web-development\u002F06.async-programming-nodejs\u002F06.parallel-vs-sequential",{"title":4250,"path":4251,"stem":4252},"EventEmitter — подієва модель Node.js","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fevent-emitter","18.web-development\u002F06.async-programming-nodejs\u002F07.event-emitter",{"title":4254,"path":4255,"stem":4256},"Worker Threads — багатопотоковість у Node.js","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fworker-threads","18.web-development\u002F06.async-programming-nodejs\u002F08.worker-threads",{"title":4258,"path":4259,"stem":4260},"Child Processes — запуск зовнішніх процесів","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fchild-processes","18.web-development\u002F06.async-programming-nodejs\u002F09.child-processes",{"title":4262,"path":4263,"stem":4264},"Обробка помилок у асинхронному коді","\u002Fweb-development\u002Fasync-programming-nodejs\u002Ferror-handling","18.web-development\u002F06.async-programming-nodejs\u002F10.error-handling",{"title":4266,"path":4267,"stem":4268},"Порівняння Node.js фреймворків","\u002Fweb-development\u002Fasync-programming-nodejs\u002Fnodejs-frameworks","18.web-development\u002F06.async-programming-nodejs\u002F11.nodejs-frameworks",{"title":4270,"icon":4271,"path":4272,"stem":4273,"children":4274,"page":59},"Тема 7. Фреймворк NestJS. Контролери та маршрутизація","i-lucide-route","\u002Fweb-development\u002Fnestjs-controllers-routing","18.web-development\u002F07.nestjs-controllers-routing",[4275,4279,4283,4287,4291,4295,4299,4303,4307,4311,4315,4319,4323,4327,4331,4335,4339,4343,4347,4351,4355,4359],{"title":4276,"path":4277,"stem":4278},"Філософія та архітектура NestJS","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fnestjs-philosophy","18.web-development\u002F07.nestjs-controllers-routing\u002F01.nestjs-philosophy",{"title":4280,"path":4281,"stem":4282},"Три стовпи архітектури: модулі, контролери, провайдери","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fthree-pillars","18.web-development\u002F07.nestjs-controllers-routing\u002F02.three-pillars",{"title":4284,"path":4285,"stem":4286},"Інверсія керування (IoC) та ін","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fioc-and-di","18.web-development\u002F07.nestjs-controllers-routing\u002F03.ioc-and-di",{"title":4288,"path":4289,"stem":4290},"Встановлення NestJS CLI та створення проєкту","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fnestjs-cli-setup","18.web-development\u002F07.nestjs-controllers-routing\u002F04.nestjs-cli-setup",{"title":4292,"path":4293,"stem":4294},"Структура проєкту NestJS та конвенції","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fproject-structure","18.web-development\u002F07.nestjs-controllers-routing\u002F05.project-structure",{"title":4296,"path":4297,"stem":4298},"Контролери: основи маршрутизації","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fcontrollers-basics","18.web-development\u002F07.nestjs-controllers-routing\u002F06.controllers-basics",{"title":4300,"path":4301,"stem":4302},"Декоратори маршрутизації HTTP-методів","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Froute-decorators","18.web-development\u002F07.nestjs-controllers-routing\u002F07.route-decorators",{"title":4304,"path":4305,"stem":4306},"Параметри маршруту та декоратор @Param","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Froute-parameters","18.web-development\u002F07.nestjs-controllers-routing\u002F08.route-parameters",{"title":4308,"path":4309,"stem":4310},"Query-параметри та декоратор @Query","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fquery-parameters","18.web-development\u002F07.nestjs-controllers-routing\u002F09.query-parameters",{"title":4312,"path":4313,"stem":4314},"Тіло запиту та декоратор @Body","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Frequest-body","18.web-development\u002F07.nestjs-controllers-routing\u002F10.request-body",{"title":4316,"path":4317,"stem":4318},"Робота з заголовками запиту та відповіді","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fheaders-decorators","18.web-development\u002F07.nestjs-controllers-routing\u002F11.headers-decorators",{"title":4320,"path":4321,"stem":4322},"Data Transfer Objects (DTO): визначення та призначення","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fdto-introduction","18.web-development\u002F07.nestjs-controllers-routing\u002F12.dto-introduction",{"title":4324,"path":4325,"stem":4326},"Об'єкти Request та Response","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Frequest-response-objects","18.web-development\u002F07.nestjs-controllers-routing\u002F13.request-response-objects",{"title":4328,"path":4329,"stem":4330},"HTTP-статус коди та декоратор @HttpCode","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fhttp-status-codes","18.web-development\u002F07.nestjs-controllers-routing\u002F14.http-status-codes",{"title":4332,"path":4333,"stem":4334},"Перенаправлення (Redirects) та декоратор @Redirect","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fredirects","18.web-development\u002F07.nestjs-controllers-routing\u002F15.redirects",{"title":4336,"path":4337,"stem":4338},"Асинхронні обробники та Observables","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fasync-handlers","18.web-development\u002F07.nestjs-controllers-routing\u002F16.async-handlers",{"title":4340,"path":4341,"stem":4342},"Маршрутизація за піддоменами та версіонування API","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fsub-domain-routing","18.web-development\u002F07.nestjs-controllers-routing\u002F17.sub-domain-routing",{"title":4344,"path":4345,"stem":4346},"Області видимості контролерів (Scopes)","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fcontroller-scopes","18.web-development\u002F07.nestjs-controllers-routing\u002F18.controller-scopes",{"title":4348,"path":4349,"stem":4350},"Основні команди NestJS CLI","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fnestjs-cli-commands","18.web-development\u002F07.nestjs-controllers-routing\u002F19.nestjs-cli-commands",{"title":4352,"path":4353,"stem":4354},"Практичний приклад: створення CRUD-контролера","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fcrud-example","18.web-development\u002F07.nestjs-controllers-routing\u002F20.crud-example",{"title":4356,"path":4357,"stem":4358},"Тестування контролерів","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Ftesting-controllers","18.web-development\u002F07.nestjs-controllers-routing\u002F21.testing-controllers",{"title":4360,"path":4361,"stem":4362},"Best Practices для контролерів та маршрутизації","\u002Fweb-development\u002Fnestjs-controllers-routing\u002Fbest-practices","18.web-development\u002F07.nestjs-controllers-routing\u002F22.best-practices",{"title":4364,"icon":4365,"path":4366,"stem":4367,"children":4368,"page":59},"Тема 8. Провайдери, сервіси та модульна система NestJS","i-lucide-package","\u002Fweb-development\u002Fnestjs-providers-modules","18.web-development\u002F08.nestjs-providers-modules",[4369,4373,4377,4381,4385,4389,4393,4397,4401,4405,4409,4413,4417,4421,4425],{"title":4370,"path":4371,"stem":4372},"Концепція провайдерів у NestJS","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fproviders-concept","18.web-development\u002F08.nestjs-providers-modules\u002F01.providers-concept",{"title":4374,"path":4375,"stem":4376},"Сервіси: інкапсуляція бізнес-логіки","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fservices-business-logic","18.web-development\u002F08.nestjs-providers-modules\u002F02.services-business-logic",{"title":4378,"path":4379,"stem":4380},"Практика ін","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fdependency-injection-practice","18.web-development\u002F08.nestjs-providers-modules\u002F03.dependency-injection-practice",{"title":4382,"path":4383,"stem":4384},"Custom Providers: useValue, useClass, useFactory, useExisting","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fcustom-providers","18.web-development\u002F08.nestjs-providers-modules\u002F04.custom-providers",{"title":4386,"path":4387,"stem":4388},"Injection Tokens: рядкові та символьні токени","\u002Fweb-development\u002Fnestjs-providers-modules\u002Finjection-tokens","18.web-development\u002F08.nestjs-providers-modules\u002F05.injection-tokens",{"title":4390,"path":4391,"stem":4392},"Опціональні провайдери та декоратор @Optional","\u002Fweb-development\u002Fnestjs-providers-modules\u002Foptional-providers","18.web-development\u002F08.nestjs-providers-modules\u002F07.optional-providers",{"title":4394,"path":4395,"stem":4396},"Структура модулів: imports, controllers, providers, exports","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fmodules-structure","18.web-development\u002F08.nestjs-providers-modules\u002F08.modules-structure",{"title":4398,"path":4399,"stem":4400},"Feature Modules: ізоляція функціональності","\u002Fweb-development\u002Fnestjs-providers-modules\u002Ffeature-modules","18.web-development\u002F08.nestjs-providers-modules\u002F09.feature-modules",{"title":4402,"path":4403,"stem":4404},"Shared Modules: перевикористання провайдерів","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fshared-modules","18.web-development\u002F08.nestjs-providers-modules\u002F10.shared-modules",{"title":4406,"path":4407,"stem":4408},"Global Modules та декоратор @Global","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fglobal-modules","18.web-development\u002F08.nestjs-providers-modules\u002F11.global-modules",{"title":4410,"path":4411,"stem":4412},"Dynamic Modules: конфігурація під час виконання","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fdynamic-modules","18.web-development\u002F08.nestjs-providers-modules\u002F12.dynamic-modules",{"title":4414,"path":4415,"stem":4416},"Циклічні залежності та forwardRef","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fcircular-dependencies","18.web-development\u002F08.nestjs-providers-modules\u002F13.circular-dependencies",{"title":4418,"path":4419,"stem":4420},"Lifecycle Hooks: хуки життєвого циклу","\u002Fweb-development\u002Fnestjs-providers-modules\u002Flifecycle-hooks","18.web-development\u002F08.nestjs-providers-modules\u002F14.lifecycle-hooks",{"title":4422,"path":4423,"stem":4424},"ModuleRef: динамічний доступ до провайдерів","\u002Fweb-development\u002Fnestjs-providers-modules\u002Fmodule-reference","18.web-development\u002F08.nestjs-providers-modules\u002F15.module-reference",{"title":4426,"path":4427,"stem":4428},"Тестування сервісів та провайдерів","\u002Fweb-development\u002Fnestjs-providers-modules\u002Ftesting-services","18.web-development\u002F08.nestjs-providers-modules\u002F16.testing-services",{"title":4430,"icon":4431,"path":4432,"stem":4433,"children":4434,"page":59},"Тема 9. Валідація даних та конвеєр обробки запитів у NestJS","i-lucide-filter","\u002Fweb-development\u002Fnestjs-validation-pipeline","18.web-development\u002F09.nestjs-validation-pipeline",[4435,4439,4443,4447,4451,4455,4459,4463,4467,4471,4475,4479,4483,4487,4491,4495,4499,4503,4507],{"title":4436,"path":4437,"stem":4438},"Request Pipeline: конвеєр обробки запитів","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Frequest-pipeline","18.web-development\u002F09.nestjs-validation-pipeline\u002F01.request-pipeline",{"title":4440,"path":4441,"stem":4442},"Pipes: концепція трансформації та валідації","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fpipes-concept","18.web-development\u002F09.nestjs-validation-pipeline\u002F02.pipes-concept",{"title":4444,"path":4445,"stem":4446},"Вбудовані pipes: ParseIntPipe, ParseBoolPipe, ParseUUIDPipe","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fbuilt-in-pipes","18.web-development\u002F09.nestjs-validation-pipeline\u002F03.built-in-pipes",{"title":4448,"path":4449,"stem":4450},"ValidationPipe: автоматична валідація DTO","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fvalidation-pipe","18.web-development\u002F09.nestjs-validation-pipeline\u002F04.validation-pipe",{"title":4452,"path":4453,"stem":4454},"Декоратори class-validator для DTO","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fclass-validator-decorators","18.web-development\u002F09.nestjs-validation-pipeline\u002F05.class-validator-decorators",{"title":4456,"path":4457,"stem":4458},"Створення кастомних валідаторів","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-validators","18.web-development\u002F09.nestjs-validation-pipeline\u002F06.custom-validators",{"title":4460,"path":4461,"stem":4462},"Створення власних Pipes","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-pipes","18.web-development\u002F09.nestjs-validation-pipeline\u002F07.custom-pipes",{"title":4464,"path":4465,"stem":4466},"Основи Middleware","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fmiddleware-basics","18.web-development\u002F09.nestjs-validation-pipeline\u002F08.middleware-basics",{"title":4468,"path":4469,"stem":4470},"Практичні приклади Middleware","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fmiddleware-examples","18.web-development\u002F09.nestjs-validation-pipeline\u002F09.middleware-examples",{"title":4472,"path":4473,"stem":4474},"Guards: захисні перехоплювачі доступу","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fguards-concept","18.web-development\u002F09.nestjs-validation-pipeline\u002F10.guards-concept",{"title":4476,"path":4477,"stem":4478},"Створення кастомних Guards","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-guards","18.web-development\u002F09.nestjs-validation-pipeline\u002F11.custom-guards",{"title":4480,"path":4481,"stem":4482},"Interceptors: перехоплення та трансформація відповідей","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Finterceptors-concept","18.web-development\u002F09.nestjs-validation-pipeline\u002F12.interceptors-concept",{"title":4484,"path":4485,"stem":4486},"Практичні приклади Interceptors","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Finterceptor-examples","18.web-development\u002F09.nestjs-validation-pipeline\u002F13.interceptor-examples",{"title":4488,"path":4489,"stem":4490},"Exception Filters: обробка виключень","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fexception-filters","18.web-development\u002F09.nestjs-validation-pipeline\u002F14.exception-filters",{"title":4492,"path":4493,"stem":4494},"Custom Exception Filters: спеціалізовані фільтри","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-exception-filters","18.web-development\u002F09.nestjs-validation-pipeline\u002F15.custom-exception-filters",{"title":4496,"path":4497,"stem":4498},"Execution Context: контекст виконання","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fexecution-context","18.web-development\u002F09.nestjs-validation-pipeline\u002F16.execution-context",{"title":4500,"path":4501,"stem":4502},"Custom Decorators: власні декоратори","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fcustom-decorators","18.web-development\u002F09.nestjs-validation-pipeline\u002F17.custom-decorators",{"title":4504,"path":4505,"stem":4506},"Global Components: глобальні компоненти","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fglobal-components","18.web-development\u002F09.nestjs-validation-pipeline\u002F18.global-components",{"title":4508,"path":4509,"stem":4510},"Pipeline Best Practices: найкращі практики","\u002Fweb-development\u002Fnestjs-validation-pipeline\u002Fpipeline-best-practices","18.web-development\u002F09.nestjs-validation-pipeline\u002F19.pipeline-best-practices",{"title":4512,"icon":2821,"path":4513,"stem":4514,"children":4515,"page":59},"Інтеграція реляційних баз даних засобами TypeORM","\u002Fweb-development\u002Ftypeorm-integration","18.web-development\u002F10.typeorm-integration",[4516,4520,4524,4528,4532,4536,4540],{"title":4517,"path":4518,"stem":4519},"Робота з базами даних у Node.js через нативні драйвери","\u002Fweb-development\u002Ftypeorm-integration\u002F01-nodejs-database-drivers","18.web-development\u002F10.typeorm-integration\u002F01-nodejs-database-drivers",{"title":4521,"path":4522,"stem":4523},"ORM та знайомство з TypeORM","\u002Fweb-development\u002Ftypeorm-integration\u002F02-orm-and-typeorm-intro","18.web-development\u002F10.typeorm-integration\u002F02-orm-and-typeorm-intro",{"title":4525,"path":4526,"stem":4527},"Налаштування TypeORM у NestJS проєкті","\u002Fweb-development\u002Ftypeorm-integration\u002F03-typeorm-setup-nestjs","18.web-development\u002F10.typeorm-integration\u002F03-typeorm-setup-nestjs",{"title":4529,"path":4530,"stem":4531},"Entity класи та декоратори TypeORM","\u002Fweb-development\u002Ftypeorm-integration\u002F04-entities-and-decorators","18.web-development\u002F10.typeorm-integration\u002F04-entities-and-decorators",{"title":4533,"path":4534,"stem":4535},"Repository Pattern та CRUD операції","\u002Fweb-development\u002Ftypeorm-integration\u002F05-repository-pattern-crud","18.web-development\u002F10.typeorm-integration\u002F05-repository-pattern-crud",{"title":4537,"path":4538,"stem":4539},"Пагінація та фільтрація даних","\u002Fweb-development\u002Ftypeorm-integration\u002F06-pagination-filtering","18.web-development\u002F10.typeorm-integration\u002F06-pagination-filtering",{"title":4541,"path":4542,"stem":4543},"QueryBuilder для складних запитів","\u002Fweb-development\u002Ftypeorm-integration\u002F07-query-builder","18.web-development\u002F10.typeorm-integration\u002F07-query-builder",{"title":4545,"icon":4546,"path":4547,"stem":4548,"children":4549,"page":59},"Зв'язки між сутностями, міграції та оптимізація запитів","i-lucide-git-branch","\u002Fweb-development\u002Fentity-relations-migrations","18.web-development\u002F11.entity-relations-migrations",[4550,4554,4558,4562,4566],{"title":4551,"path":4552,"stem":4553},"Зв'язки One-to-Many та Many-to-One","\u002Fweb-development\u002Fentity-relations-migrations\u002F01-one-to-many-many-to-one","18.web-development\u002F11.entity-relations-migrations\u002F01-one-to-many-many-to-one",{"title":4555,"path":4556,"stem":4557},"Зв'язки One-to-One та Many-to-Many","\u002Fweb-development\u002Fentity-relations-migrations\u002F02-one-to-one-many-to-many","18.web-development\u002F11.entity-relations-migrations\u002F02-one-to-one-many-to-many",{"title":4559,"path":4560,"stem":4561},"Керування міграціями бази даних","\u002Fweb-development\u002Fentity-relations-migrations\u002F03-migrations-management","18.web-development\u002F11.entity-relations-migrations\u002F03-migrations-management",{"title":4563,"path":4564,"stem":4565},"Транзакції у TypeORM","\u002Fweb-development\u002Fentity-relations-migrations\u002F04-transactions","18.web-development\u002F11.entity-relations-migrations\u002F04-transactions",{"title":4567,"path":4568,"stem":4569,"children":4570},"Індекси та оптимізація запитів","\u002Fweb-development\u002Fentity-relations-migrations\u002F05-indexes-optimization","18.web-development\u002F11.entity-relations-migrations\u002F05-indexes-optimization",[4571],{"title":4567,"path":4568,"stem":4569},{"title":4573,"icon":4574,"path":4575,"stem":4576,"children":4577,"page":59},"Механізми автентифікації у вебзастосунках","i-lucide-key","\u002Fweb-development\u002Fauthentication","18.web-development\u002F12.authentication",[4578,4582,4586,4590,4594,4598,4602,4606,4610],{"title":4579,"path":4580,"stem":4581},"Автентифікація vs Авторизація","\u002Fweb-development\u002Fauthentication\u002F01-authentication-vs-authorization","18.web-development\u002F12.authentication\u002F01-authentication-vs-authorization",{"title":4583,"path":4584,"stem":4585},"Стратегії автентифікації","\u002Fweb-development\u002Fauthentication\u002F02-authentication-strategies","18.web-development\u002F12.authentication\u002F02-authentication-strategies",{"title":4587,"path":4588,"stem":4589},"Автентифікація на основі сесій","\u002Fweb-development\u002Fauthentication\u002F03-session-based-authentication","18.web-development\u002F12.authentication\u002F03-session-based-authentication",{"title":4591,"path":4592,"stem":4593},"Структура JSON Web Token (JWT)","\u002Fweb-development\u002Fauthentication\u002F04-jwt-structure","18.web-development\u002F12.authentication\u002F04-jwt-structure",{"title":4595,"path":4596,"stem":4597},"Інтеграція JWT у NestJS","\u002Fweb-development\u002Fauthentication\u002F05-nestjs-jwt-integration","18.web-development\u002F12.authentication\u002F05-nestjs-jwt-integration",{"title":4599,"path":4600,"stem":4601},"Passport.js стратегії у NestJS","\u002Fweb-development\u002Fauthentication\u002F06-passport-strategies","18.web-development\u002F12.authentication\u002F06-passport-strategies",{"title":4603,"path":4604,"stem":4605},"Безпечне зберігання паролів: хешування та криптографічний захист","\u002Fweb-development\u002Fauthentication\u002F07-password-hashing","18.web-development\u002F12.authentication\u002F07-password-hashing",{"title":4607,"path":4608,"stem":4609},"Refresh Token та безпечне оновлення доступу","\u002Fweb-development\u002Fauthentication\u002F08-refresh-tokens","18.web-development\u002F12.authentication\u002F08-refresh-tokens",{"title":4611,"path":4612,"stem":4613},"OAuth 2.0 та OpenID Connect: делегована автентифікація","\u002Fweb-development\u002Fauthentication\u002F09-oauth2-openid","18.web-development\u002F12.authentication\u002F09-oauth2-openid",{"title":4615,"icon":4616,"path":4617,"stem":4618,"children":4619,"page":59},"Авторизація та безпека серверних застосунків","i-lucide-shield","\u002Fweb-development\u002Fauthorization-security","18.web-development\u002F13.authorization-security",[4620,4624,4628,4632,4636,4640,4644,4648,4652,4656],{"title":4621,"path":4622,"stem":4623},"Моделі авторизації","\u002Fweb-development\u002Fauthorization-security\u002F01-authorization-models","18.web-development\u002F13.authorization-security\u002F01-authorization-models",{"title":4625,"path":4626,"stem":4627},"Реалізація RBAC у NestJS","\u002Fweb-development\u002Fauthorization-security\u002F02-rbac-implementation","18.web-development\u002F13.authorization-security\u002F02-rbac-implementation",{"title":4629,"path":4630,"stem":4631},"Permission-Based Access Control","\u002Fweb-development\u002Fauthorization-security\u002F03-permission-based-access","18.web-development\u002F13.authorization-security\u002F03-permission-based-access",{"title":4633,"path":4634,"stem":4635},"ABAC та бібліотека CASL","\u002Fweb-development\u002Fauthorization-security\u002F04-abac-casl","18.web-development\u002F13.authorization-security\u002F04-abac-casl",{"title":4637,"path":4638,"stem":4639},"Кастомні декоратори та метадані","\u002Fweb-development\u002Fauthorization-security\u002F05-custom-decorators-metadata","18.web-development\u002F13.authorization-security\u002F05-custom-decorators-metadata",{"title":4641,"path":4642,"stem":4643},"Конфігурація CORS","\u002Fweb-development\u002Fauthorization-security\u002F06-cors-configuration","18.web-development\u002F13.authorization-security\u002F06-cors-configuration",{"title":4645,"path":4646,"stem":4647},"Захист через HTTP Security Headers (Helmet)","\u002Fweb-development\u002Fauthorization-security\u002F07-helmet-security-headers","18.web-development\u002F13.authorization-security\u002F07-helmet-security-headers",{"title":4649,"path":4650,"stem":4651},"Rate Limiting та Throttling","\u002Fweb-development\u002Fauthorization-security\u002F08-rate-limiting-throttling","18.web-development\u002F13.authorization-security\u002F08-rate-limiting-throttling",{"title":4653,"path":4654,"stem":4655},"Захист від поширених атак","\u002Fweb-development\u002Fauthorization-security\u002F09-common-attacks-protection","18.web-development\u002F13.authorization-security\u002F09-common-attacks-protection",{"title":4657,"path":4658,"stem":4659},"HTTPS у продакшені","\u002Fweb-development\u002Fauthorization-security\u002F10-https-production","18.web-development\u002F13.authorization-security\u002F10-https-production",{"title":4661,"icon":871,"path":4662,"stem":4663,"children":4664,"page":59},"Комунікація у реальному часі, нотифікації та фонові задачі","\u002Fweb-development\u002Frealtime-notifications-jobs","18.web-development\u002F14.realtime-notifications-jobs",[4665,4669,4673,4677,4681,4685,4688,4691,4695,4699],{"title":4666,"path":4667,"stem":4668},"Методи комунікації у реальному часі","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F01-realtime-communication-methods","18.web-development\u002F14.realtime-notifications-jobs\u002F01-realtime-communication-methods",{"title":4670,"path":4671,"stem":4672},"WebSocket Gateway у NestJS","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F02-websocket-gateway","18.web-development\u002F14.realtime-notifications-jobs\u002F02-websocket-gateway",{"title":4674,"path":4675,"stem":4676},"Lifecycle та Rooms у WebSocket","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F03-websocket-lifecycle-rooms","18.web-development\u002F14.realtime-notifications-jobs\u002F03-websocket-lifecycle-rooms",{"title":4678,"path":4679,"stem":4680},"Server-Sent Events (SSE)","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F04-server-sent-events","18.web-development\u002F14.realtime-notifications-jobs\u002F04-server-sent-events",{"title":4682,"path":4683,"stem":4684},"Архітектура системи нотифікацій","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F05-notification-system","18.web-development\u002F14.realtime-notifications-jobs\u002F05-notification-system",{"title":904,"path":4686,"stem":4687},"\u002Fweb-development\u002Frealtime-notifications-jobs\u002F06-email-notifications","18.web-development\u002F14.realtime-notifications-jobs\u002F06-email-notifications",{"title":900,"path":4689,"stem":4690},"\u002Fweb-development\u002Frealtime-notifications-jobs\u002F07-web-push-notifications","18.web-development\u002F14.realtime-notifications-jobs\u002F07-web-push-notifications",{"title":4692,"path":4693,"stem":4694},"Фонові задачі та черги","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F08-background-jobs-queues","18.web-development\u002F14.realtime-notifications-jobs\u002F08-background-jobs-queues",{"title":4696,"path":4697,"stem":4698},"Планувальники та Cron jobs","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F09-schedulers-cron","18.web-development\u002F14.realtime-notifications-jobs\u002F09-schedulers-cron",{"title":4700,"path":4701,"stem":4702},"Практичні сценарії застосування","\u002Fweb-development\u002Frealtime-notifications-jobs\u002F10-practical-scenarios","18.web-development\u002F14.realtime-notifications-jobs\u002F10-practical-scenarios",{"title":4704,"icon":4705,"path":4706,"stem":4707,"children":4708,"page":59},"Тестування, документування та розгортання застосунків","i-lucide-rocket","\u002Fweb-development\u002Ftesting-documentation-deployment","18.web-development\u002F15.testing-documentation-deployment",[4709,4713,4717,4721,4725,4729,4733,4737,4741,4745],{"title":4710,"path":4711,"stem":4712},"Піраміда тестування та стратегія","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F01-testing-pyramid-strategy","18.web-development\u002F15.testing-documentation-deployment\u002F01-testing-pyramid-strategy",{"title":4714,"path":4715,"stem":4716},"Основи Jest у NestJS","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F02-jest-nestjs-basics","18.web-development\u002F15.testing-documentation-deployment\u002F02-jest-nestjs-basics",{"title":4718,"path":4719,"stem":4720},"Unit-тестування сервісів","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F03-unit-testing-services","18.web-development\u002F15.testing-documentation-deployment\u002F03-unit-testing-services",{"title":4722,"path":4723,"stem":4724},"E2E тестування та покриття коду","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F04-e2e-testing-coverage","18.web-development\u002F15.testing-documentation-deployment\u002F04-e2e-testing-coverage",{"title":4726,"path":4727,"stem":4728},"Swagger, OpenAPI, Scalar та Arazzo","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F05-swagger-openapi","18.web-development\u002F15.testing-documentation-deployment\u002F05-swagger-openapi",{"title":4730,"path":4731,"stem":4732},"Керування конфігурацією","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F06-configuration-management","18.web-development\u002F15.testing-documentation-deployment\u002F06-configuration-management",{"title":4734,"path":4735,"stem":4736},"Docker та контейнеризація","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F07-docker-containerization","18.web-development\u002F15.testing-documentation-deployment\u002F07-docker-containerization",{"title":4738,"path":4739,"stem":4740},"CI\u002FCD Pipelines","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F08-cicd-pipelines","18.web-development\u002F15.testing-documentation-deployment\u002F08-cicd-pipelines",{"title":4742,"path":4743,"stem":4744},"Логування та моніторинг","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F09-logging-monitoring","18.web-development\u002F15.testing-documentation-deployment\u002F09-logging-monitoring",{"title":4746,"path":4747,"stem":4748},"Серіалізація та компресія","\u002Fweb-development\u002Ftesting-documentation-deployment\u002F10-serialization-compression","18.web-development\u002F15.testing-documentation-deployment\u002F10-serialization-compression",{"title":4750,"icon":4751,"path":4752,"stem":4753,"children":4754,"page":59},"AI Core: мислення AI","i-lucide-brain","\u002Fai-core","19.ai-core",[4755,4796,4845,4883],{"title":4756,"icon":4705,"path":4757,"stem":4758,"children":4759,"page":59},"Вхід у професію AI Native Developer","\u002Fai-core\u002Fai-native-developer","19.ai-core\u002F01.ai-native-developer",[4760,4764,4768,4772,4776,4780,4784,4788,4792],{"title":4761,"path":4762,"stem":4763},"Вступ до професії розробника цифрових продуктів","\u002Fai-core\u002Fai-native-developer\u002Fdigital-products","19.ai-core\u002F01.ai-native-developer\u002F01.digital-products",{"title":4765,"path":4766,"stem":4767},"Професія розробника програмного забезпечення","\u002Fai-core\u002Fai-native-developer\u002Fsoftware-developer","19.ai-core\u002F01.ai-native-developer\u002F02.software-developer",{"title":4769,"path":4770,"stem":4771},"Професія AI Native Developer","\u002Fai-core\u002Fai-native-developer\u002Fai-native-developer","19.ai-core\u002F01.ai-native-developer\u002F03.ai-native-developer",{"title":4773,"path":4774,"stem":4775},"Вплив AI на розробку програмного забезпечення","\u002Fai-core\u002Fai-native-developer\u002Fai-impact-on-development","19.ai-core\u002F01.ai-native-developer\u002F04.ai-impact-on-development",{"title":4777,"path":4778,"stem":4779},"Життєвий цикл цифрового продукту","\u002Fai-core\u002Fai-native-developer\u002Fproduct-lifecycle","19.ai-core\u002F01.ai-native-developer\u002F05.product-lifecycle",{"title":4781,"path":4782,"stem":4783},"Застосування AI на етапах створення цифрового продукту","\u002Fai-core\u002Fai-native-developer\u002Fai-in-product-creation","19.ai-core\u002F01.ai-native-developer\u002F06.ai-in-product-creation",{"title":4785,"path":4786,"stem":4787},"Розподіл завдань між людиною та AI","\u002Fai-core\u002Fai-native-developer\u002Fhuman-vs-ai-tasks","19.ai-core\u002F01.ai-native-developer\u002F07.human-vs-ai-tasks",{"title":4789,"path":4790,"stem":4791},"Компетенції AI Native Developer","\u002Fai-core\u002Fai-native-developer\u002Fcompetencies","19.ai-core\u002F01.ai-native-developer\u002F08.competencies",{"title":4793,"path":4794,"stem":4795},"Карта професійного розвитку AI Native Developer","\u002Fai-core\u002Fai-native-developer\u002Fcareer-roadmap","19.ai-core\u002F01.ai-native-developer\u002F09.career-roadmap",{"title":4797,"icon":255,"path":4798,"stem":4799,"children":4800,"page":59},"Штучний інтелект і машинне навчання","\u002Fai-core\u002Fai-and-machine-learning","19.ai-core\u002F02.ai-and-machine-learning",[4801,4805,4809,4813,4817,4821,4825,4829,4833,4837,4841],{"title":4802,"path":4803,"stem":4804},"Штучний інтелект","\u002Fai-core\u002Fai-and-machine-learning\u002Fwhat-is-ai","19.ai-core\u002F02.ai-and-machine-learning\u002F01.what-is-ai",{"title":4806,"path":4807,"stem":4808},"Відмінність AI від інших програмних систем","\u002Fai-core\u002Fai-and-machine-learning\u002Fai-vs-automation","19.ai-core\u002F02.ai-and-machine-learning\u002F02.ai-vs-automation",{"title":4810,"path":4811,"stem":4812},"Завдання штучного інтелекту","\u002Fai-core\u002Fai-and-machine-learning\u002Fai-tasks","19.ai-core\u002F02.ai-and-machine-learning\u002F03.ai-tasks",{"title":4814,"path":4815,"stem":4816},"Machine Learning","\u002Fai-core\u002Fai-and-machine-learning\u002Fmachine-learning","19.ai-core\u002F02.ai-and-machine-learning\u002F04.machine-learning",{"title":4818,"path":4819,"stem":4820},"Machine Learning Workflow","\u002Fai-core\u002Fai-and-machine-learning\u002Fml-workflow","19.ai-core\u002F02.ai-and-machine-learning\u002F05.ml-workflow",{"title":4822,"path":4823,"stem":4824},"Типи машинного навчання","\u002Fai-core\u002Fai-and-machine-learning\u002Fml-types","19.ai-core\u002F02.ai-and-machine-learning\u002F06.ml-types",{"title":4826,"path":4827,"stem":4828},"Generative AI","\u002Fai-core\u002Fai-and-machine-learning\u002Fgenerative-ai","19.ai-core\u002F02.ai-and-machine-learning\u002F07.generative-ai",{"title":4830,"path":4831,"stem":4832},"Типи контенту, створюваного AI","\u002Fai-core\u002Fai-and-machine-learning\u002Fai-content-types","19.ai-core\u002F02.ai-and-machine-learning\u002F08.ai-content-types",{"title":4834,"path":4835,"stem":4836},"Великі мовні моделі","\u002Fai-core\u002Fai-and-machine-learning\u002Flarge-language-models","19.ai-core\u002F02.ai-and-machine-learning\u002F09.large-language-models",{"title":4838,"path":4839,"stem":4840},"Можливості та обмеження Generative AI","\u002Fai-core\u002Fai-and-machine-learning\u002Fcapabilities-and-limitations","19.ai-core\u002F02.ai-and-machine-learning\u002F10.capabilities-and-limitations",{"title":4842,"path":4843,"stem":4844},"Сучасні AI-асистенти","\u002Fai-core\u002Fai-and-machine-learning\u002Fmodern-ai-assistants","19.ai-core\u002F02.ai-and-machine-learning\u002F11.modern-ai-assistants",{"title":4846,"icon":4847,"path":4848,"stem":4849,"children":4850,"page":59},"Постановка завдань для AI: принципи створення промптів","i-lucide-message-square-text","\u002Fai-core\u002Fprompt-engineering","19.ai-core\u002F03.prompt-engineering",[4851,4855,4859,4863,4867,4871,4875,4879],{"title":4852,"path":4853,"stem":4854},"Промпт як інструмент","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-as-tool","19.ai-core\u002F03.prompt-engineering\u002F01.prompt-as-tool",{"title":4856,"path":4857,"stem":4858},"Принципи створення промптів","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-principles","19.ai-core\u002F03.prompt-engineering\u002F02.prompt-principles",{"title":4860,"path":4861,"stem":4862},"Структура промпта","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-structure","19.ai-core\u002F03.prompt-engineering\u002F03.prompt-structure",{"title":4864,"path":4865,"stem":4866},"Види промптів за типом задачі","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-types","19.ai-core\u002F03.prompt-engineering\u002F04.prompt-types",{"title":4868,"path":4869,"stem":4870},"Прийоми посилення промпта","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-enhancement","19.ai-core\u002F03.prompt-engineering\u002F05.prompt-enhancement",{"title":4872,"path":4873,"stem":4874},"Розбір і покращення промпта","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-analysis","19.ai-core\u002F03.prompt-engineering\u002F06.prompt-analysis",{"title":4876,"path":4877,"stem":4878},"Типові помилки під час створення промптів","\u002Fai-core\u002Fprompt-engineering\u002Fcommon-mistakes","19.ai-core\u002F03.prompt-engineering\u002F07.common-mistakes",{"title":4880,"path":4881,"stem":4882},"Практикум: особиста бібліотека промптів","\u002Fai-core\u002Fprompt-engineering\u002Fprompt-library","19.ai-core\u002F03.prompt-engineering\u002F08.prompt-library",{"title":4884,"icon":793,"path":4885,"stem":4886,"children":4887,"page":59},"Перевірка результатів, безпека та AI Native Workflow","\u002Fai-core\u002Fverification-security-workflow","19.ai-core\u002F04.verification-security-workflow",[4888,4892,4896,4900,4904,4908,4912,4916,4920],{"title":4889,"path":4890,"stem":4891},"Межі можливостей AI","\u002Fai-core\u002Fverification-security-workflow\u002Fai-limitations","19.ai-core\u002F04.verification-security-workflow\u002F01.ai-limitations",{"title":4893,"path":4894,"stem":4895},"Галюцинації AI","\u002Fai-core\u002Fverification-security-workflow\u002Fai-hallucinations","19.ai-core\u002F04.verification-security-workflow\u002F02.ai-hallucinations",{"title":4897,"path":4898,"stem":4899},"Критичне мислення під час роботи з AI","\u002Fai-core\u002Fverification-security-workflow\u002Fcritical-thinking","19.ai-core\u002F04.verification-security-workflow\u002F03.critical-thinking",{"title":4901,"path":4902,"stem":4903},"Перевірка результатів роботи AI","\u002Fai-core\u002Fverification-security-workflow\u002Fresult-verification","19.ai-core\u002F04.verification-security-workflow\u002F04.result-verification",{"title":4905,"path":4906,"stem":4907},"Захист даних під час роботи з AI","\u002Fai-core\u002Fverification-security-workflow\u002Fdata-protection","19.ai-core\u002F04.verification-security-workflow\u002F05.data-protection",{"title":4909,"path":4910,"stem":4911},"Авторське право та навчальна доброчесність","\u002Fai-core\u002Fverification-security-workflow\u002Fcopyright-integrity","19.ai-core\u002F04.verification-security-workflow\u002F06.copyright-integrity",{"title":4913,"path":4914,"stem":4915},"Відповідальне використання AI","\u002Fai-core\u002Fverification-security-workflow\u002Fresponsible-use","19.ai-core\u002F04.verification-security-workflow\u002F07.responsible-use",{"title":4917,"path":4918,"stem":4919},"AI Native Workflow","\u002Fai-core\u002Fverification-security-workflow\u002Fai-native-workflow","19.ai-core\u002F04.verification-security-workflow\u002F08.ai-native-workflow",{"title":4921,"path":4922,"stem":4923},"Застосування AI Native Workflow під час створення цифрового продукту","\u002Fai-core\u002Fverification-security-workflow\u002Fworkflow-in-practice","19.ai-core\u002F04.verification-security-workflow\u002F09.workflow-in-practice",{"title":4925,"icon":4926,"path":4927,"stem":4928,"children":4929,"page":59},"AI Developer: Vibe Coding Sprint","i-lucide-code-xml","\u002Fai-developer","20.ai-developer",[4930,4956,4978,4999],{"title":4931,"icon":4932,"path":4933,"stem":4934,"children":4935,"page":59},"Проєктування і чорнова версія","i-lucide-pencil-ruler","\u002Fai-developer\u002Fdraft-creation","20.ai-developer\u002F01.draft-creation",[4936,4940,4944,4948,4952],{"title":4937,"path":4938,"stem":4939},"Парадигма Vibe Coding Workflow","\u002Fai-developer\u002Fdraft-creation\u002Fvibe-coding-workflow","20.ai-developer\u002F01.draft-creation\u002F01.vibe-coding-workflow",{"title":4941,"path":4942,"stem":4943},"AI-середовище швидкої розробки","\u002Fai-developer\u002Fdraft-creation\u002Fai-ide-environment","20.ai-developer\u002F01.draft-creation\u002F02.ai-ide-environment",{"title":4945,"path":4946,"stem":4947},"Користувацьке завдання та межі першої версії","\u002Fai-developer\u002Fdraft-creation\u002Fproduct-scope-and-mvp","20.ai-developer\u002F01.draft-creation\u002F03.product-scope-and-mvp",{"title":4949,"path":4950,"stem":4951},"Архітектура інтерфейсу та стани застосунку","\u002Fai-developer\u002Fdraft-creation\u002Fapplication-architecture-and-states","20.ai-developer\u002F01.draft-creation\u002F04.application-architecture-and-states",{"title":4953,"path":4954,"stem":4955},"Генерація та фіксація чорнової версії","\u002Fai-developer\u002Fdraft-creation\u002Fgenerating-draft-version","20.ai-developer\u002F01.draft-creation\u002F05.generating-draft-version",{"title":4957,"icon":4958,"path":4959,"stem":4960,"children":4961,"page":59},"Перша робоча версія","i-lucide-play-circle","\u002Fai-developer\u002Ffirst-working-version","20.ai-developer\u002F02.first-working-version",[4962,4966,4970,4974],{"title":4963,"path":4964,"stem":4965},"Уточнення контексту проєкту для AI","\u002Fai-developer\u002Ffirst-working-version\u002Frefining-project-context","20.ai-developer\u002F02.first-working-version\u002F01.refining-project-context",{"title":4967,"path":4968,"stem":4969},"Стратегія завдань для AI-розробки","\u002Fai-developer\u002Ffirst-working-version\u002Fai-prompting-strategy","20.ai-developer\u002F02.first-working-version\u002F02.ai-prompting-strategy",{"title":4971,"path":4972,"stem":4973},"Доопрацювання до першої робочої версії","\u002Fai-developer\u002Ffirst-working-version\u002Frefining-to-working-version","20.ai-developer\u002F02.first-working-version\u002F03.refining-to-working-version",{"title":4975,"path":4976,"stem":4977},"Перевірка першої робочої версії","\u002Fai-developer\u002Ffirst-working-version\u002Ftesting-first-working-version","20.ai-developer\u002F02.first-working-version\u002F04.testing-first-working-version",{"title":4979,"icon":3028,"path":4980,"stem":4981,"children":4982,"page":59},"Ітерації, дебагінг та відновлення","\u002Fai-developer\u002Fiteration-debugging-recovery","20.ai-developer\u002F03.iteration-debugging-recovery",[4983,4987,4991,4995],{"title":4984,"path":4985,"stem":4986},"Управління точковими змінами продукту","\u002Fai-developer\u002Fiteration-debugging-recovery\u002Fchange-management","20.ai-developer\u002F03.iteration-debugging-recovery\u002F01.change-management",{"title":4988,"path":4989,"stem":4990},"Надійність інтерфейсу та обробка помилок","\u002Fai-developer\u002Fiteration-debugging-recovery\u002Fscenario-reliability-and-errors","20.ai-developer\u002F03.iteration-debugging-recovery\u002F02.scenario-reliability-and-errors",{"title":4992,"path":4993,"stem":4994},"Керування контекстом і збереження версій","\u002Fai-developer\u002Fiteration-debugging-recovery\u002Fproject-context-and-versions","20.ai-developer\u002F03.iteration-debugging-recovery\u002F03.project-context-and-versions",{"title":4996,"path":4997,"stem":4998},"Збої AI-розробки, ліміти та аварійне відновлення","\u002Fai-developer\u002Fiteration-debugging-recovery\u002Fai-breakdowns-and-recovery","20.ai-developer\u002F03.iteration-debugging-recovery\u002F04.ai-breakdowns-and-recovery",{"title":5000,"icon":5001,"path":5002,"stem":5003,"children":5004,"page":59},"Перевірка та завершення продукту","i-lucide-check-check","\u002Fai-developer\u002Fverification-and-completion","20.ai-developer\u002F04.verification-and-completion",[5005,5009,5013],{"title":5006,"path":5007,"stem":5008},"Комплексний аудит та підсумкове тестування","\u002Fai-developer\u002Fverification-and-completion\u002Ffinal-product-testing","20.ai-developer\u002F04.verification-and-completion\u002F01.final-product-testing",{"title":5010,"path":5011,"stem":5012},"Підготовка підсумкової версії коду","\u002Fai-developer\u002Fverification-and-completion\u002Fpreparing-release-version","20.ai-developer\u002F04.verification-and-completion\u002F02.preparing-release-version",{"title":5014,"path":5015,"stem":5016},"Демонстрація, публікація та критерії оцінювання","\u002Fai-developer\u002Fverification-and-completion\u002Fproduct-showcase-and-publishing","20.ai-developer\u002F04.verification-and-completion\u002F03.product-showcase-and-publishing",{"title":5018,"path":5019,"stem":5020,"children":5021,"page":59},"Tailwind","\u002Ftailwind","21.tailwind",[5022,5026,5030,5034,5038,5042,5046,5050,5054,5058,5062,5066],{"title":5023,"path":5024,"stem":5025},"Що таке Tailwind CSS і навіщо він потрібен","\u002Ftailwind\u002Ftailwind-intro-philosophy","21.tailwind\u002F01.tailwind-intro-philosophy",{"title":5027,"path":5028,"stem":5029},"Встановлення та налаштування Tailwind CSS v4","\u002Ftailwind\u002Ftailwind-installation-setup","21.tailwind\u002F02.tailwind-installation-setup",{"title":5031,"path":5032,"stem":5033},"Utility-класи: основи та система Tailwind","\u002Ftailwind\u002Ftailwind-utility-classes-core","21.tailwind\u002F03.tailwind-utility-classes-core",{"title":5035,"path":5036,"stem":5037},"Layout: Flexbox та Grid через Tailwind","\u002Ftailwind\u002Ftailwind-flexbox-grid","21.tailwind\u002F04.tailwind-flexbox-grid",{"title":5039,"path":5040,"stem":5041},"Кастомізація теми через @theme у Tailwind v4","\u002Ftailwind\u002Ftailwind-theme-customization","21.tailwind\u002F05.tailwind-theme-customization",{"title":5043,"path":5044,"stem":5045},"Варіанти: hover, focus, responsive, dark mode та нові v4","\u002Ftailwind\u002Ftailwind-variants-states","21.tailwind\u002F06.tailwind-variants-states",{"title":5047,"path":5048,"stem":5049},"Типографіка та система кольорів у Tailwind v4","\u002Ftailwind\u002Ftailwind-typography-colors","21.tailwind\u002F07.tailwind-typography-colors",{"title":5051,"path":5052,"stem":5053},"Компоненти та повторюваність: @apply, @utility та патерни","\u002Ftailwind\u002Ftailwind-components-patterns","21.tailwind\u002F08.tailwind-components-patterns",{"title":5055,"path":5056,"stem":5057},"Темна тема та система дизайн-токенів у Tailwind v4","\u002Ftailwind\u002Ftailwind-dark-mode-theming","21.tailwind\u002F09.tailwind-dark-mode-theming",{"title":5059,"path":5060,"stem":5061},"Довільні значення та контейнерні запити у Tailwind v4","\u002Ftailwind\u002Ftailwind-arbitrary-container-queries","21.tailwind\u002F10.tailwind-arbitrary-container-queries",{"title":5063,"path":5064,"stem":5065},"Анімації, трансформації та 3D у Tailwind v4","\u002Ftailwind\u002Ftailwind-animations-transforms","21.tailwind\u002F11.tailwind-animations-transforms",{"title":5067,"path":5068,"stem":5069},"Tailwind CLI, PostCSS та інтеграція з фреймворками","\u002Ftailwind\u002Ftailwind-cli-tooling","21.tailwind\u002F12.tailwind-cli-tooling",{"title":5071,"path":5072,"stem":5073},"Тестування компонентів діаграм","\u002Ftest-components","98.test-components",{"id":5075,"title":4621,"body":5076,"description":5425,"extension":16473,"links":16474,"meta":16475,"navigation":5453,"path":4622,"seo":16476,"stem":4623,"__hash__":16477},"docs\u002F18.web-development\u002F13.authorization-security\u002F01-authorization-models.md",{"type":5077,"value":5078,"toc":16421},"minimark",[5079,5083,5088,5092,5121,5124,5127,5184,5186,5190,5210,5213,5218,5277,5294,5296,5300,5316,5321,5326,5356,5360,5363,5368,5388,5393,5413,5419,5551,5555,5558,5563,5802,5807,6776,6781,6865,6870,7483,7487,7492,7518,7523,7554,7568,7572,7577,7596,7601,7606,7611,7623,7689,7691,7695,7712,7716,7720,7779,7783,7790,7804,7829,7840,7864,7889,7893,8033,8037,8040,8044,8278,8283,8914,8919,9421,9425,9429,9455,9459,9491,9513,9517,9522,9530,9535,9540,9545,9561,9566,9578,9580,9584,9608,9612,9616,9669,9673,9680,9686,9714,9720,9736,9742,9764,9770,9774,9945,9950,10004,10008,10012,10289,10294,10875,10880,11342,11347,11435,11440,12093,12097,12101,12143,12147,12185,12205,12209,12214,12241,12246,12280,12285,12300,12302,12306,12317,12355,12359,12363,12409,12413,12416,12421,12429,12434,12440,12444,12580,12585,12610,12614,12621,12626,12924,12929,13393,13398,14227,14232,14297,14302,14793,14797,14801,14833,14837,14875,14906,14910,14915,14920,14925,14930,14934,14942,14947,14956,14958,14962,15490,15644,15646,15650,15653,15657,15701,15705,15725,15729,15734,15742,15745,15749,15754,15774,15780,15782,15786,15789,15793,15796,16015,16019,16022,16207,16211,16222,16224,16228,16303,16305,16309,16408,16414,16417],[5080,5081,4621],"h1",{"id":5082},"моделі-авторизації",[5084,5085,5087],"h2",{"id":5086},"короткий-зміст","Короткий зміст",[5089,5090,5091],"p",{},"У цій лекції розглядається порівняння основних моделей контролю доступу до ресурсів:",[5093,5094,5095,5103,5109,5115],"ul",{},[5096,5097,5098,5102],"li",{},[5099,5100,5101],"strong",{},"DAC (Discretionary Access Control)"," — дискреційний контроль доступу, власник ресурсу сам визначає права доступу інших користувачів",[5096,5104,5105,5108],{},[5099,5106,5107],{},"MAC (Mandatory Access Control)"," — мандатний контроль доступу, права визначаються централізованою політикою безпеки на основі рівнів секретності",[5096,5110,5111,5114],{},[5099,5112,5113],{},"RBAC (Role-Based Access Control)"," — рольовий контроль доступу, права надаються на основі ролей користувача у системі",[5096,5116,5117,5120],{},[5099,5118,5119],{},"ABAC (Attribute-Based Access Control)"," — атрибутивний контроль доступу, рішення про доступ приймається на основі атрибутів користувача, ресурсу, дії та контексту",[5089,5122,5123],{},"Вивчаються переваги та недоліки кожної моделі, типові сценарії використання (DAC для файлових систем, MAC для військових систем, RBAC для корпоративних застосунків, ABAC для складних багатофакторних рішень), критерії вибору моделі залежно від вимог проєкту до безпеки, гнучкості та складності адміністрування.",[5125,5126],"hr",{},[5128,5129,5130,5149],"card-group",{},[5131,5132,5135],"card",{"icon":5133,"title":5134},"i-lucide-target","🎯 Мета лекції",[5093,5136,5137,5140,5143,5146],{},[5096,5138,5139],{},"Опанувати фундаментальні моделі контролю доступу до ресурсів у програмних системах.",[5096,5141,5142],{},"Зрозуміти архітектурні відмінності між DAC, MAC, RBAC та ABAC підходами.",[5096,5144,5145],{},"Навчитися обирати оптимальну модель авторизації залежно від вимог проєкту до безпеки, масштабованості та гнучкості адміністрування.",[5096,5147,5148],{},"Ознайомитися з практичними сценаріями застосування кожної моделі у реальних веб-застосунках.",[5131,5150,5152],{"icon":4574,"title":5151},"🔑 Ключові терміни",[5093,5153,5154,5160,5166,5172,5178],{},[5096,5155,5156,5159],{},[5099,5157,5158],{},"Access Control Model (Модель контролю доступу):"," формальний опис правил, що визначають, які суб'єкти мають доступ до яких об'єктів.",[5096,5161,5162,5165],{},[5099,5163,5164],{},"Subject (Суб'єкт):"," активна сутність, що виконує дії — користувач, процес, сервіс.",[5096,5167,5168,5171],{},[5099,5169,5170],{},"Object (Об'єкт):"," пасивна сутність, до якої здійснюється доступ — файл, база даних, API-ендпоінт.",[5096,5173,5174,5177],{},[5099,5175,5176],{},"Principal (Принципал):"," автентифікована ідентичність, від імені якої діє суб'єкт.",[5096,5179,5180,5183],{},[5099,5181,5182],{},"Permission (Дозвіл):"," право виконувати певну операцію над об'єктом.",[5125,5185],{},[5084,5187,5189],{"id":5188},"еволюція-моделей-контролю-доступу","Еволюція моделей контролю доступу",[5089,5191,5192,5193,5197,5198,5201,5202,5205,5206,5209],{},"У попередній лекції ми розглянули фундаментальну відмінність між автентифікацією (",[5194,5195,5196],"em",{},"authentication",") — підтвердженням особи користувача — та авторизацією (",[5194,5199,5200],{},"authorization",") — наданням прав доступу до ресурсів. Автентифікація відповідає на питання ",[5099,5203,5204],{},"«Хто ви?»",", тоді як авторизація вирішує ",[5099,5207,5208],{},"«Що вам дозволено робити?»",".",[5089,5211,5212],{},"Проте сама по собі відповідь на друге питання може будуватися за різними принципами. Протягом десятиліть еволюції систем безпеки було розроблено кілька фундаментальних моделей контролю доступу, кожна з яких відповідає на різні вимоги до безпеки, гнучкості та складності адміністрування. Ці моделі не є взаємовиключними — сучасні застосунки часто комбінують елементи кількох підходів залежно від контексту.",[5089,5214,5215],{},[5099,5216,5217],{},"Чотири основні моделі контролю доступу:",[5219,5220,5221,5243,5252,5265],"ol",{},[5096,5222,5223,5225,5226,5229,5230,5234,5235,5238,5239,5242],{},[5099,5224,5101],{}," — дискреційний контроль доступу, де власник ресурсу має повну свободу (",[5194,5227,5228],{},"discretion",") у визначенні прав доступу інших користувачів. Це найстаріший та найпростіший підхід, що лежить в основі файлових систем UNIX\u002FLinux (",[5231,5232,5233],"code",{},"chmod",", ",[5231,5236,5237],{},"chown",") та Windows ACL (",[5194,5240,5241],{},"Access Control Lists",").",[5096,5244,5245,5247,5248,5251],{},[5099,5246,5107],{}," — мандатний (обов'язковий) контроль доступу, де права визначаються централізованою політикою безпеки на основі міток секретності (",[5194,5249,5250],{},"security labels",") та рівнів доступу. Модель розроблена для високозахищених середовищ — військових систем, державних установ, банківських core-систем.",[5096,5253,5254,5256,5257,5260,5261,5264],{},[5099,5255,5113],{}," — рольовий контроль доступу, де права надаються не безпосередньо користувачам, а через проміжний шар ",[5099,5258,5259],{},"ролей"," (",[5194,5262,5263],{},"roles","). Користувач отримує одну або кілька ролей, кожна з яких визначає набір дозволів. Це стандарт для корпоративних застосунків, CRM, ERP, систем управління контентом.",[5096,5266,5267,5269,5270,5260,5273,5276],{},[5099,5268,5119],{}," — атрибутивний контроль доступу, де рішення про доступ приймається динамічно на основі ",[5099,5271,5272],{},"атрибутів",[5194,5274,5275],{},"attributes",") суб'єкта (користувача), об'єкта (ресурсу), дії та контексту виконання (час, місце, стан сесії). Це найгнучкіша та найскладніша модель, що дозволяє виражати складні багатофакторні політики.",[5278,5279,5280,5281,5234,5284,5234,5287,5290,5291,5209],"note",{},"У реальних проєктах рідко зустрічається «чиста» реалізація однієї моделі. Наприклад, GitHub використовує RBAC для управління правами у репозиторіях (",[5231,5282,5283],{},"admin",[5231,5285,5286],{},"write",[5231,5288,5289],{},"read","), але додає елементи ABAC для перевірки контексту — чи походить запит із довіреної IP-адреси, чи увімкнена двофакторна автентифікація, чи дозволений доступ для API токена з певними ",[5194,5292,5293],{},"scopes",[5125,5295],{},[5084,5297,5299],{"id":5298},"dac-дискреційний-контроль-доступу","DAC: Дискреційний контроль доступу",[5089,5301,5302,5305,5306,5260,5309,5312,5313,5315],{},[5099,5303,5304],{},"Discretionary Access Control (DAC)"," — це модель, у якій ",[5099,5307,5308],{},"власник",[5194,5310,5311],{},"owner",") ресурсу має повну свободу вибору (",[5194,5314,5228],{},") у визначенні прав доступу інших користувачів до цього ресурсу. Власник може надавати, змінювати або відкликати дозволи на свій розсуд, без узгодження з централізованою адміністрацією безпеки.",[5317,5318,5320],"h3",{"id":5319},"базові-принципи-dac","Базові принципи DAC",[5089,5322,5323],{},[5099,5324,5325],{},"Ключові характеристики:",[5093,5327,5328,5334,5344,5350],{},[5096,5329,5330,5333],{},[5099,5331,5332],{},"Децентралізоване управління доступом:"," кожен користувач, який створює ресурс, автоматично стає його власником і отримує право управляти доступом до нього.",[5096,5335,5336,5339,5340,5343],{},[5099,5337,5338],{},"Передача прав:"," власник може не лише надати дозвіл іншому користувачеві, але й передати йому право надавати доступ третім особам (",[5194,5341,5342],{},"grant option","). Це створює ланцюжки делегування прав.",[5096,5345,5346,5349],{},[5099,5347,5348],{},"Гнучкість та простота:"," для малих систем та особистих даних це інтуїтивно зрозумілий підхід — «Це мій файл, я вирішую, хто його читає».",[5096,5351,5352,5355],{},[5099,5353,5354],{},"Ризик неконтрольованого поширення прав:"," відсутність централізованого контролю може призвести до ситуації, коли конфіденційні дані стають доступними непередбаченому колу осіб через ланцюжок делегувань.",[5317,5357,5359],{"id":5358},"приклад-файлова-система-unixlinux","Приклад: Файлова система UNIX\u002FLinux",[5089,5361,5362],{},"Класичний приклад DAC — система дозволів у UNIX\u002FLinux, що базується на трьох категоріях суб'єктів та трьох типах операцій:",[5089,5364,5365],{},[5099,5366,5367],{},"Категорії суб'єктів:",[5093,5369,5370,5376,5382],{},[5096,5371,5372,5375],{},[5099,5373,5374],{},"User (Власник):"," користувач, який створив файл.",[5096,5377,5378,5381],{},[5099,5379,5380],{},"Group (Група):"," всі користувачі, що входять до певної групи.",[5096,5383,5384,5387],{},[5099,5385,5386],{},"Others (Інші):"," всі інші користувачі у системі.",[5089,5389,5390],{},[5099,5391,5392],{},"Типи операцій:",[5093,5394,5395,5401,5407],{},[5096,5396,5397,5400],{},[5099,5398,5399],{},"Read (r):"," читання вмісту файлу або перегляд списку файлів у каталозі.",[5096,5402,5403,5406],{},[5099,5404,5405],{},"Write (w):"," зміна вмісту файлу або створення\u002Fвидалення файлів у каталозі.",[5096,5408,5409,5412],{},[5099,5410,5411],{},"Execute (x):"," виконання файлу як програми або перехід у каталог.",[5089,5414,5415,5416,5418],{},"Власник файлу може в будь-який момент змінити дозволи за допомогою команди ",[5231,5417,5233],{},":",[5420,5421,5426],"pre",{"className":5422,"code":5423,"language":5424,"meta":5425,"style":5425},"language-bash shiki shiki-themes light-plus dark-plus dark-plus","# Створюємо файл — автоматично стаємо його власником\ntouch report.txt\n\n# Дивимося поточні дозволи\nls -l report.txt\n# -rw-r--r--  1 ivan  staff  0 Sep  7 14:30 report.txt\n# ^^^ ^^^ ^^^\n#  |   |   └─ Others: read\n#  |   └───── Group: read\n#  └───────── User: read + write\n\n# Надаємо групі право на запис, забираємо доступ у інших\nchmod 660 report.txt\n\n# Результат\nls -l report.txt\n# -rw-rw----  1 ivan  staff  0 Sep  7 14:30 report.txt\n","bash","",[5231,5427,5428,5437,5448,5455,5461,5473,5479,5485,5491,5497,5503,5508,5514,5525,5530,5536,5545],{"__ignoreMap":5425},[5429,5430,5433],"span",{"class":5431,"line":5432},"line",1,[5429,5434,5436],{"class":5435},"spJ8K","# Створюємо файл — автоматично стаємо його власником\n",[5429,5438,5440,5444],{"class":5431,"line":5439},2,[5429,5441,5443],{"class":5442},"s8Opu","touch",[5429,5445,5447],{"class":5446},"sbdoH"," report.txt\n",[5429,5449,5451],{"class":5431,"line":5450},3,[5429,5452,5454],{"emptyLinePlaceholder":5453},true,"\n",[5429,5456,5458],{"class":5431,"line":5457},4,[5429,5459,5460],{"class":5435},"# Дивимося поточні дозволи\n",[5429,5462,5464,5467,5471],{"class":5431,"line":5463},5,[5429,5465,5466],{"class":5442},"ls",[5429,5468,5470],{"class":5469},"su1O8"," -l",[5429,5472,5447],{"class":5446},[5429,5474,5476],{"class":5431,"line":5475},6,[5429,5477,5478],{"class":5435},"# -rw-r--r--  1 ivan  staff  0 Sep  7 14:30 report.txt\n",[5429,5480,5482],{"class":5431,"line":5481},7,[5429,5483,5484],{"class":5435},"# ^^^ ^^^ ^^^\n",[5429,5486,5488],{"class":5431,"line":5487},8,[5429,5489,5490],{"class":5435},"#  |   |   └─ Others: read\n",[5429,5492,5494],{"class":5431,"line":5493},9,[5429,5495,5496],{"class":5435},"#  |   └───── Group: read\n",[5429,5498,5500],{"class":5431,"line":5499},10,[5429,5501,5502],{"class":5435},"#  └───────── User: read + write\n",[5429,5504,5506],{"class":5431,"line":5505},11,[5429,5507,5454],{"emptyLinePlaceholder":5453},[5429,5509,5511],{"class":5431,"line":5510},12,[5429,5512,5513],{"class":5435},"# Надаємо групі право на запис, забираємо доступ у інших\n",[5429,5515,5517,5519,5523],{"class":5431,"line":5516},13,[5429,5518,5233],{"class":5442},[5429,5520,5522],{"class":5521},"sJj4R"," 660",[5429,5524,5447],{"class":5446},[5429,5526,5528],{"class":5431,"line":5527},14,[5429,5529,5454],{"emptyLinePlaceholder":5453},[5429,5531,5533],{"class":5431,"line":5532},15,[5429,5534,5535],{"class":5435},"# Результат\n",[5429,5537,5539,5541,5543],{"class":5431,"line":5538},16,[5429,5540,5466],{"class":5442},[5429,5542,5470],{"class":5469},[5429,5544,5447],{"class":5446},[5429,5546,5548],{"class":5431,"line":5547},17,[5429,5549,5550],{"class":5435},"# -rw-rw----  1 ivan  staff  0 Sep  7 14:30 report.txt\n",[5317,5552,5554],{"id":5553},"реалізація-dac-у-веб-застосунку-typescript-nestjs","Реалізація DAC у веб-застосунку (TypeScript + NestJS)",[5089,5556,5557],{},"Розглянемо спрощену реалізацію DAC для системи управління документами, де користувач може створювати документи та надавати доступ іншим користувачам.",[5089,5559,5560],{},[5099,5561,5562],{},"Модель даних:",[5420,5564,5568],{"className":5565,"code":5566,"language":5567,"meta":5425,"style":5425},"language-typescript shiki shiki-themes light-plus dark-plus dark-plus","\u002F\u002F domain\u002Fdocument.entity.ts\nexport class Document {\n  id: string;\n  title: string;\n  content: string;\n  ownerId: string; \u002F\u002F UUID власника документа\n  createdAt: Date;\n  \n  \u002F\u002F Список дозволів: які користувачі мають які права\n  permissions: DocumentPermission[];\n}\n\nexport class DocumentPermission {\n  id: string;\n  documentId: string;\n  userId: string; \u002F\u002F UUID користувача, якому надано доступ\n  canRead: boolean;\n  canWrite: boolean;\n  canDelete: boolean;\n  canGrantAccess: boolean; \u002F\u002F Чи може цей користувач надавати доступ іншим\n  grantedAt: Date;\n}\n","typescript",[5231,5569,5570,5575,5592,5607,5618,5629,5644,5656,5661,5666,5679,5684,5688,5699,5709,5720,5734,5746,5758,5770,5785,5797],{"__ignoreMap":5425},[5429,5571,5572],{"class":5431,"line":5432},[5429,5573,5574],{"class":5435},"\u002F\u002F domain\u002Fdocument.entity.ts\n",[5429,5576,5577,5581,5584,5588],{"class":5431,"line":5439},[5429,5578,5580],{"class":5579},"s8xlr","export",[5429,5582,5583],{"class":5469}," class",[5429,5585,5587],{"class":5586},"sN1BT"," Document",[5429,5589,5591],{"class":5590},"sHH4Y"," {\n",[5429,5593,5594,5598,5601,5604],{"class":5431,"line":5450},[5429,5595,5597],{"class":5596},"siwwj","  id",[5429,5599,5600],{"class":5590},": ",[5429,5602,5603],{"class":5586},"string",[5429,5605,5606],{"class":5590},";\n",[5429,5608,5609,5612,5614,5616],{"class":5431,"line":5457},[5429,5610,5611],{"class":5596},"  title",[5429,5613,5600],{"class":5590},[5429,5615,5603],{"class":5586},[5429,5617,5606],{"class":5590},[5429,5619,5620,5623,5625,5627],{"class":5431,"line":5463},[5429,5621,5622],{"class":5596},"  content",[5429,5624,5600],{"class":5590},[5429,5626,5603],{"class":5586},[5429,5628,5606],{"class":5590},[5429,5630,5631,5634,5636,5638,5641],{"class":5431,"line":5475},[5429,5632,5633],{"class":5596},"  ownerId",[5429,5635,5600],{"class":5590},[5429,5637,5603],{"class":5586},[5429,5639,5640],{"class":5590},"; ",[5429,5642,5643],{"class":5435},"\u002F\u002F UUID власника документа\n",[5429,5645,5646,5649,5651,5654],{"class":5431,"line":5481},[5429,5647,5648],{"class":5596},"  createdAt",[5429,5650,5600],{"class":5590},[5429,5652,5653],{"class":5586},"Date",[5429,5655,5606],{"class":5590},[5429,5657,5658],{"class":5431,"line":5487},[5429,5659,5660],{"class":5590},"  \n",[5429,5662,5663],{"class":5431,"line":5493},[5429,5664,5665],{"class":5435},"  \u002F\u002F Список дозволів: які користувачі мають які права\n",[5429,5667,5668,5671,5673,5676],{"class":5431,"line":5499},[5429,5669,5670],{"class":5596},"  permissions",[5429,5672,5600],{"class":5590},[5429,5674,5675],{"class":5586},"DocumentPermission",[5429,5677,5678],{"class":5590},"[];\n",[5429,5680,5681],{"class":5431,"line":5505},[5429,5682,5683],{"class":5590},"}\n",[5429,5685,5686],{"class":5431,"line":5510},[5429,5687,5454],{"emptyLinePlaceholder":5453},[5429,5689,5690,5692,5694,5697],{"class":5431,"line":5516},[5429,5691,5580],{"class":5579},[5429,5693,5583],{"class":5469},[5429,5695,5696],{"class":5586}," DocumentPermission",[5429,5698,5591],{"class":5590},[5429,5700,5701,5703,5705,5707],{"class":5431,"line":5527},[5429,5702,5597],{"class":5596},[5429,5704,5600],{"class":5590},[5429,5706,5603],{"class":5586},[5429,5708,5606],{"class":5590},[5429,5710,5711,5714,5716,5718],{"class":5431,"line":5532},[5429,5712,5713],{"class":5596},"  documentId",[5429,5715,5600],{"class":5590},[5429,5717,5603],{"class":5586},[5429,5719,5606],{"class":5590},[5429,5721,5722,5725,5727,5729,5731],{"class":5431,"line":5538},[5429,5723,5724],{"class":5596},"  userId",[5429,5726,5600],{"class":5590},[5429,5728,5603],{"class":5586},[5429,5730,5640],{"class":5590},[5429,5732,5733],{"class":5435},"\u002F\u002F UUID користувача, якому надано доступ\n",[5429,5735,5736,5739,5741,5744],{"class":5431,"line":5547},[5429,5737,5738],{"class":5596},"  canRead",[5429,5740,5600],{"class":5590},[5429,5742,5743],{"class":5586},"boolean",[5429,5745,5606],{"class":5590},[5429,5747,5749,5752,5754,5756],{"class":5431,"line":5748},18,[5429,5750,5751],{"class":5596},"  canWrite",[5429,5753,5600],{"class":5590},[5429,5755,5743],{"class":5586},[5429,5757,5606],{"class":5590},[5429,5759,5761,5764,5766,5768],{"class":5431,"line":5760},19,[5429,5762,5763],{"class":5596},"  canDelete",[5429,5765,5600],{"class":5590},[5429,5767,5743],{"class":5586},[5429,5769,5606],{"class":5590},[5429,5771,5773,5776,5778,5780,5782],{"class":5431,"line":5772},20,[5429,5774,5775],{"class":5596},"  canGrantAccess",[5429,5777,5600],{"class":5590},[5429,5779,5743],{"class":5586},[5429,5781,5640],{"class":5590},[5429,5783,5784],{"class":5435},"\u002F\u002F Чи може цей користувач надавати доступ іншим\n",[5429,5786,5788,5791,5793,5795],{"class":5431,"line":5787},21,[5429,5789,5790],{"class":5596},"  grantedAt",[5429,5792,5600],{"class":5590},[5429,5794,5653],{"class":5586},[5429,5796,5606],{"class":5590},[5429,5798,5800],{"class":5431,"line":5799},22,[5429,5801,5683],{"class":5590},[5089,5803,5804],{},[5099,5805,5806],{},"Guard для перевірки DAC дозволів:",[5420,5808,5810],{"className":5565,"code":5809,"language":5567,"meta":5425,"style":5425},"\u002F\u002F guards\u002Fdac-authorization.guard.ts\nimport { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs\u002Fcommon';\nimport { Reflector } from '@nestjs\u002Fcore';\nimport { DocumentService } from '..\u002Fservices\u002Fdocument.service';\n\n@Injectable()\nexport class DacAuthorizationGuard implements CanActivate {\n  constructor(\n    private reflector: Reflector,\n    private documentService: DocumentService\n  ) {}\n\n  async canActivate(context: ExecutionContext): Promise\u003Cboolean> {\n    \u002F\u002F Витягуємо необхідну операцію з метаданих декоратора\n    const requiredOperation = this.reflector.get\u003C'read' | 'write' | 'delete' | 'grant'>(\n      'operation',\n      context.getHandler()\n    );\n\n    if (!requiredOperation) {\n      return true; \u002F\u002F Якщо операція не вказана, дозволяємо доступ\n    }\n\n    const request = context.switchToHttp().getRequest();\n    const currentUser = request.user; \u002F\u002F Встановлений AuthGuard\n    const documentId = request.params.id;\n\n    if (!currentUser || !documentId) {\n      throw new ForbiddenException('Missing authentication or document ID');\n    }\n\n    const document = await this.documentService.findById(documentId);\n\n    if (!document) {\n      return false; \u002F\u002F Документ не існує — Guard не несе відповідальності за 404\n    }\n\n    \u002F\u002F Перевірка 1: Власник має всі права\n    if (document.ownerId === currentUser.sub) {\n      return true;\n    }\n\n    \u002F\u002F Перевірка 2: Шукаємо явний дозвіл для поточного користувача\n    const permission = document.permissions.find(p => p.userId === currentUser.sub);\n\n    if (!permission) {\n      throw new ForbiddenException('You do not have access to this document');\n    }\n\n    \u002F\u002F Перевірка 3: Чи має користувач необхідну операцію\n    const hasPermission = this.checkPermission(permission, requiredOperation);\n\n    if (!hasPermission) {\n      throw new ForbiddenException(\n        `You do not have permission to ${requiredOperation} this document`\n      );\n    }\n\n    return true;\n  }\n\n  private checkPermission(\n    permission: DocumentPermission,\n    operation: 'read' | 'write' | 'delete' | 'grant'\n  ): boolean {\n    switch (operation) {\n      case 'read':\n        return permission.canRead;\n      case 'write':\n        return permission.canWrite;\n      case 'delete':\n        return permission.canDelete;\n      case 'grant':\n        return permission.canGrantAccess;\n      default:\n        return false;\n    }\n  }\n}\n",[5231,5811,5812,5817,5854,5872,5890,5894,5904,5921,5929,5944,5956,5961,5965,5997,6002,6051,6058,6070,6075,6079,6093,6106,6111,6116,6142,6165,6189,6194,6212,6232,6237,6242,6274,6279,6291,6304,6309,6314,6320,6346,6355,6360,6365,6371,6418,6423,6435,6451,6456,6461,6467,6494,6499,6511,6522,6539,6545,6550,6555,6565,6571,6576,6587,6599,6622,6632,6645,6657,6672,6682,6696,6706,6720,6730,6744,6752,6761,6766,6771],{"__ignoreMap":5425},[5429,5813,5814],{"class":5431,"line":5432},[5429,5815,5816],{"class":5435},"\u002F\u002F guards\u002Fdac-authorization.guard.ts\n",[5429,5818,5819,5822,5825,5828,5830,5833,5835,5838,5840,5843,5846,5849,5852],{"class":5431,"line":5439},[5429,5820,5821],{"class":5579},"import",[5429,5823,5824],{"class":5590}," { ",[5429,5826,5827],{"class":5596},"Injectable",[5429,5829,5234],{"class":5590},[5429,5831,5832],{"class":5596},"CanActivate",[5429,5834,5234],{"class":5590},[5429,5836,5837],{"class":5596},"ExecutionContext",[5429,5839,5234],{"class":5590},[5429,5841,5842],{"class":5596},"ForbiddenException",[5429,5844,5845],{"class":5590}," } ",[5429,5847,5848],{"class":5579},"from",[5429,5850,5851],{"class":5446}," '@nestjs\u002Fcommon'",[5429,5853,5606],{"class":5590},[5429,5855,5856,5858,5860,5863,5865,5867,5870],{"class":5431,"line":5450},[5429,5857,5821],{"class":5579},[5429,5859,5824],{"class":5590},[5429,5861,5862],{"class":5596},"Reflector",[5429,5864,5845],{"class":5590},[5429,5866,5848],{"class":5579},[5429,5868,5869],{"class":5446}," '@nestjs\u002Fcore'",[5429,5871,5606],{"class":5590},[5429,5873,5874,5876,5878,5881,5883,5885,5888],{"class":5431,"line":5457},[5429,5875,5821],{"class":5579},[5429,5877,5824],{"class":5590},[5429,5879,5880],{"class":5596},"DocumentService",[5429,5882,5845],{"class":5590},[5429,5884,5848],{"class":5579},[5429,5886,5887],{"class":5446}," '..\u002Fservices\u002Fdocument.service'",[5429,5889,5606],{"class":5590},[5429,5891,5892],{"class":5431,"line":5463},[5429,5893,5454],{"emptyLinePlaceholder":5453},[5429,5895,5896,5899,5901],{"class":5431,"line":5475},[5429,5897,5898],{"class":5590},"@",[5429,5900,5827],{"class":5442},[5429,5902,5903],{"class":5590},"()\n",[5429,5905,5906,5908,5910,5913,5916,5919],{"class":5431,"line":5481},[5429,5907,5580],{"class":5579},[5429,5909,5583],{"class":5469},[5429,5911,5912],{"class":5586}," DacAuthorizationGuard",[5429,5914,5915],{"class":5469}," implements",[5429,5917,5918],{"class":5586}," CanActivate",[5429,5920,5591],{"class":5590},[5429,5922,5923,5926],{"class":5431,"line":5487},[5429,5924,5925],{"class":5469},"  constructor",[5429,5927,5928],{"class":5590},"(\n",[5429,5930,5931,5934,5937,5939,5941],{"class":5431,"line":5493},[5429,5932,5933],{"class":5469},"    private",[5429,5935,5936],{"class":5596}," reflector",[5429,5938,5600],{"class":5590},[5429,5940,5862],{"class":5586},[5429,5942,5943],{"class":5590},",\n",[5429,5945,5946,5948,5951,5953],{"class":5431,"line":5499},[5429,5947,5933],{"class":5469},[5429,5949,5950],{"class":5596}," documentService",[5429,5952,5600],{"class":5590},[5429,5954,5955],{"class":5586},"DocumentService\n",[5429,5957,5958],{"class":5431,"line":5505},[5429,5959,5960],{"class":5590},"  ) {}\n",[5429,5962,5963],{"class":5431,"line":5510},[5429,5964,5454],{"emptyLinePlaceholder":5453},[5429,5966,5967,5970,5973,5976,5979,5981,5983,5986,5989,5992,5994],{"class":5431,"line":5516},[5429,5968,5969],{"class":5469},"  async",[5429,5971,5972],{"class":5442}," canActivate",[5429,5974,5975],{"class":5590},"(",[5429,5977,5978],{"class":5596},"context",[5429,5980,5600],{"class":5590},[5429,5982,5837],{"class":5586},[5429,5984,5985],{"class":5590},"): ",[5429,5987,5988],{"class":5586},"Promise",[5429,5990,5991],{"class":5590},"\u003C",[5429,5993,5743],{"class":5586},[5429,5995,5996],{"class":5590},"> {\n",[5429,5998,5999],{"class":5431,"line":5527},[5429,6000,6001],{"class":5435},"    \u002F\u002F Витягуємо необхідну операцію з метаданих декоратора\n",[5429,6003,6004,6007,6011,6014,6017,6019,6022,6024,6027,6029,6032,6035,6038,6040,6043,6045,6048],{"class":5431,"line":5532},[5429,6005,6006],{"class":5469},"    const",[5429,6008,6010],{"class":6009},"s-QsJ"," requiredOperation",[5429,6012,6013],{"class":5590}," = ",[5429,6015,6016],{"class":5469},"this",[5429,6018,5209],{"class":5590},[5429,6020,6021],{"class":5596},"reflector",[5429,6023,5209],{"class":5590},[5429,6025,6026],{"class":5442},"get",[5429,6028,5991],{"class":5590},[5429,6030,6031],{"class":5446},"'read'",[5429,6033,6034],{"class":5590}," | ",[5429,6036,6037],{"class":5446},"'write'",[5429,6039,6034],{"class":5590},[5429,6041,6042],{"class":5446},"'delete'",[5429,6044,6034],{"class":5590},[5429,6046,6047],{"class":5446},"'grant'",[5429,6049,6050],{"class":5590},">(\n",[5429,6052,6053,6056],{"class":5431,"line":5538},[5429,6054,6055],{"class":5446},"      'operation'",[5429,6057,5943],{"class":5590},[5429,6059,6060,6063,6065,6068],{"class":5431,"line":5547},[5429,6061,6062],{"class":5596},"      context",[5429,6064,5209],{"class":5590},[5429,6066,6067],{"class":5442},"getHandler",[5429,6069,5903],{"class":5590},[5429,6071,6072],{"class":5431,"line":5748},[5429,6073,6074],{"class":5590},"    );\n",[5429,6076,6077],{"class":5431,"line":5760},[5429,6078,5454],{"emptyLinePlaceholder":5453},[5429,6080,6081,6084,6087,6090],{"class":5431,"line":5772},[5429,6082,6083],{"class":5579},"    if",[5429,6085,6086],{"class":5590}," (!",[5429,6088,6089],{"class":5596},"requiredOperation",[5429,6091,6092],{"class":5590},") {\n",[5429,6094,6095,6098,6101,6103],{"class":5431,"line":5787},[5429,6096,6097],{"class":5579},"      return",[5429,6099,6100],{"class":5469}," true",[5429,6102,5640],{"class":5590},[5429,6104,6105],{"class":5435},"\u002F\u002F Якщо операція не вказана, дозволяємо доступ\n",[5429,6107,6108],{"class":5431,"line":5799},[5429,6109,6110],{"class":5590},"    }\n",[5429,6112,6114],{"class":5431,"line":6113},23,[5429,6115,5454],{"emptyLinePlaceholder":5453},[5429,6117,6119,6121,6124,6126,6128,6130,6133,6136,6139],{"class":5431,"line":6118},24,[5429,6120,6006],{"class":5469},[5429,6122,6123],{"class":6009}," request",[5429,6125,6013],{"class":5590},[5429,6127,5978],{"class":5596},[5429,6129,5209],{"class":5590},[5429,6131,6132],{"class":5442},"switchToHttp",[5429,6134,6135],{"class":5590},"().",[5429,6137,6138],{"class":5442},"getRequest",[5429,6140,6141],{"class":5590},"();\n",[5429,6143,6145,6147,6150,6152,6155,6157,6160,6162],{"class":5431,"line":6144},25,[5429,6146,6006],{"class":5469},[5429,6148,6149],{"class":6009}," currentUser",[5429,6151,6013],{"class":5590},[5429,6153,6154],{"class":5596},"request",[5429,6156,5209],{"class":5590},[5429,6158,6159],{"class":5596},"user",[5429,6161,5640],{"class":5590},[5429,6163,6164],{"class":5435},"\u002F\u002F Встановлений AuthGuard\n",[5429,6166,6168,6170,6173,6175,6177,6179,6182,6184,6187],{"class":5431,"line":6167},26,[5429,6169,6006],{"class":5469},[5429,6171,6172],{"class":6009}," documentId",[5429,6174,6013],{"class":5590},[5429,6176,6154],{"class":5596},[5429,6178,5209],{"class":5590},[5429,6180,6181],{"class":5596},"params",[5429,6183,5209],{"class":5590},[5429,6185,6186],{"class":5596},"id",[5429,6188,5606],{"class":5590},[5429,6190,6192],{"class":5431,"line":6191},27,[5429,6193,5454],{"emptyLinePlaceholder":5453},[5429,6195,6197,6199,6201,6204,6207,6210],{"class":5431,"line":6196},28,[5429,6198,6083],{"class":5579},[5429,6200,6086],{"class":5590},[5429,6202,6203],{"class":5596},"currentUser",[5429,6205,6206],{"class":5590}," || !",[5429,6208,6209],{"class":5596},"documentId",[5429,6211,6092],{"class":5590},[5429,6213,6215,6218,6221,6224,6226,6229],{"class":5431,"line":6214},29,[5429,6216,6217],{"class":5579},"      throw",[5429,6219,6220],{"class":5469}," new",[5429,6222,6223],{"class":5442}," ForbiddenException",[5429,6225,5975],{"class":5590},[5429,6227,6228],{"class":5446},"'Missing authentication or document ID'",[5429,6230,6231],{"class":5590},");\n",[5429,6233,6235],{"class":5431,"line":6234},30,[5429,6236,6110],{"class":5590},[5429,6238,6240],{"class":5431,"line":6239},31,[5429,6241,5454],{"emptyLinePlaceholder":5453},[5429,6243,6245,6247,6250,6252,6255,6258,6260,6263,6265,6268,6270,6272],{"class":5431,"line":6244},32,[5429,6246,6006],{"class":5469},[5429,6248,6249],{"class":6009}," document",[5429,6251,6013],{"class":5590},[5429,6253,6254],{"class":5579},"await",[5429,6256,6257],{"class":5469}," this",[5429,6259,5209],{"class":5590},[5429,6261,6262],{"class":5596},"documentService",[5429,6264,5209],{"class":5590},[5429,6266,6267],{"class":5442},"findById",[5429,6269,5975],{"class":5590},[5429,6271,6209],{"class":5596},[5429,6273,6231],{"class":5590},[5429,6275,6277],{"class":5431,"line":6276},33,[5429,6278,5454],{"emptyLinePlaceholder":5453},[5429,6280,6282,6284,6286,6289],{"class":5431,"line":6281},34,[5429,6283,6083],{"class":5579},[5429,6285,6086],{"class":5590},[5429,6287,6288],{"class":5596},"document",[5429,6290,6092],{"class":5590},[5429,6292,6294,6296,6299,6301],{"class":5431,"line":6293},35,[5429,6295,6097],{"class":5579},[5429,6297,6298],{"class":5469}," false",[5429,6300,5640],{"class":5590},[5429,6302,6303],{"class":5435},"\u002F\u002F Документ не існує — Guard не несе відповідальності за 404\n",[5429,6305,6307],{"class":5431,"line":6306},36,[5429,6308,6110],{"class":5590},[5429,6310,6312],{"class":5431,"line":6311},37,[5429,6313,5454],{"emptyLinePlaceholder":5453},[5429,6315,6317],{"class":5431,"line":6316},38,[5429,6318,6319],{"class":5435},"    \u002F\u002F Перевірка 1: Власник має всі права\n",[5429,6321,6323,6325,6327,6329,6331,6334,6337,6339,6341,6344],{"class":5431,"line":6322},39,[5429,6324,6083],{"class":5579},[5429,6326,5260],{"class":5590},[5429,6328,6288],{"class":5596},[5429,6330,5209],{"class":5590},[5429,6332,6333],{"class":5596},"ownerId",[5429,6335,6336],{"class":5590}," === ",[5429,6338,6203],{"class":5596},[5429,6340,5209],{"class":5590},[5429,6342,6343],{"class":5596},"sub",[5429,6345,6092],{"class":5590},[5429,6347,6349,6351,6353],{"class":5431,"line":6348},40,[5429,6350,6097],{"class":5579},[5429,6352,6100],{"class":5469},[5429,6354,5606],{"class":5590},[5429,6356,6358],{"class":5431,"line":6357},41,[5429,6359,6110],{"class":5590},[5429,6361,6363],{"class":5431,"line":6362},42,[5429,6364,5454],{"emptyLinePlaceholder":5453},[5429,6366,6368],{"class":5431,"line":6367},43,[5429,6369,6370],{"class":5435},"    \u002F\u002F Перевірка 2: Шукаємо явний дозвіл для поточного користувача\n",[5429,6372,6374,6376,6379,6381,6383,6385,6388,6390,6393,6395,6397,6400,6403,6405,6408,6410,6412,6414,6416],{"class":5431,"line":6373},44,[5429,6375,6006],{"class":5469},[5429,6377,6378],{"class":6009}," permission",[5429,6380,6013],{"class":5590},[5429,6382,6288],{"class":5596},[5429,6384,5209],{"class":5590},[5429,6386,6387],{"class":5596},"permissions",[5429,6389,5209],{"class":5590},[5429,6391,6392],{"class":5442},"find",[5429,6394,5975],{"class":5590},[5429,6396,5089],{"class":5596},[5429,6398,6399],{"class":5469}," =>",[5429,6401,6402],{"class":5596}," p",[5429,6404,5209],{"class":5590},[5429,6406,6407],{"class":5596},"userId",[5429,6409,6336],{"class":5590},[5429,6411,6203],{"class":5596},[5429,6413,5209],{"class":5590},[5429,6415,6343],{"class":5596},[5429,6417,6231],{"class":5590},[5429,6419,6421],{"class":5431,"line":6420},45,[5429,6422,5454],{"emptyLinePlaceholder":5453},[5429,6424,6426,6428,6430,6433],{"class":5431,"line":6425},46,[5429,6427,6083],{"class":5579},[5429,6429,6086],{"class":5590},[5429,6431,6432],{"class":5596},"permission",[5429,6434,6092],{"class":5590},[5429,6436,6438,6440,6442,6444,6446,6449],{"class":5431,"line":6437},47,[5429,6439,6217],{"class":5579},[5429,6441,6220],{"class":5469},[5429,6443,6223],{"class":5442},[5429,6445,5975],{"class":5590},[5429,6447,6448],{"class":5446},"'You do not have access to this document'",[5429,6450,6231],{"class":5590},[5429,6452,6454],{"class":5431,"line":6453},48,[5429,6455,6110],{"class":5590},[5429,6457,6459],{"class":5431,"line":6458},49,[5429,6460,5454],{"emptyLinePlaceholder":5453},[5429,6462,6464],{"class":5431,"line":6463},50,[5429,6465,6466],{"class":5435},"    \u002F\u002F Перевірка 3: Чи має користувач необхідну операцію\n",[5429,6468,6470,6472,6475,6477,6479,6481,6484,6486,6488,6490,6492],{"class":5431,"line":6469},51,[5429,6471,6006],{"class":5469},[5429,6473,6474],{"class":6009}," hasPermission",[5429,6476,6013],{"class":5590},[5429,6478,6016],{"class":5469},[5429,6480,5209],{"class":5590},[5429,6482,6483],{"class":5442},"checkPermission",[5429,6485,5975],{"class":5590},[5429,6487,6432],{"class":5596},[5429,6489,5234],{"class":5590},[5429,6491,6089],{"class":5596},[5429,6493,6231],{"class":5590},[5429,6495,6497],{"class":5431,"line":6496},52,[5429,6498,5454],{"emptyLinePlaceholder":5453},[5429,6500,6502,6504,6506,6509],{"class":5431,"line":6501},53,[5429,6503,6083],{"class":5579},[5429,6505,6086],{"class":5590},[5429,6507,6508],{"class":5596},"hasPermission",[5429,6510,6092],{"class":5590},[5429,6512,6514,6516,6518,6520],{"class":5431,"line":6513},54,[5429,6515,6217],{"class":5579},[5429,6517,6220],{"class":5469},[5429,6519,6223],{"class":5442},[5429,6521,5928],{"class":5590},[5429,6523,6525,6528,6531,6533,6536],{"class":5431,"line":6524},55,[5429,6526,6527],{"class":5446},"        `You do not have permission to ",[5429,6529,6530],{"class":5469},"${",[5429,6532,6089],{"class":5596},[5429,6534,6535],{"class":5469},"}",[5429,6537,6538],{"class":5446}," this document`\n",[5429,6540,6542],{"class":5431,"line":6541},56,[5429,6543,6544],{"class":5590},"      );\n",[5429,6546,6548],{"class":5431,"line":6547},57,[5429,6549,6110],{"class":5590},[5429,6551,6553],{"class":5431,"line":6552},58,[5429,6554,5454],{"emptyLinePlaceholder":5453},[5429,6556,6558,6561,6563],{"class":5431,"line":6557},59,[5429,6559,6560],{"class":5579},"    return",[5429,6562,6100],{"class":5469},[5429,6564,5606],{"class":5590},[5429,6566,6568],{"class":5431,"line":6567},60,[5429,6569,6570],{"class":5590},"  }\n",[5429,6572,6574],{"class":5431,"line":6573},61,[5429,6575,5454],{"emptyLinePlaceholder":5453},[5429,6577,6579,6582,6585],{"class":5431,"line":6578},62,[5429,6580,6581],{"class":5469},"  private",[5429,6583,6584],{"class":5442}," checkPermission",[5429,6586,5928],{"class":5590},[5429,6588,6590,6593,6595,6597],{"class":5431,"line":6589},63,[5429,6591,6592],{"class":5596},"    permission",[5429,6594,5600],{"class":5590},[5429,6596,5675],{"class":5586},[5429,6598,5943],{"class":5590},[5429,6600,6602,6605,6607,6609,6611,6613,6615,6617,6619],{"class":5431,"line":6601},64,[5429,6603,6604],{"class":5596},"    operation",[5429,6606,5600],{"class":5590},[5429,6608,6031],{"class":5446},[5429,6610,6034],{"class":5590},[5429,6612,6037],{"class":5446},[5429,6614,6034],{"class":5590},[5429,6616,6042],{"class":5446},[5429,6618,6034],{"class":5590},[5429,6620,6621],{"class":5446},"'grant'\n",[5429,6623,6625,6628,6630],{"class":5431,"line":6624},65,[5429,6626,6627],{"class":5590},"  ): ",[5429,6629,5743],{"class":5586},[5429,6631,5591],{"class":5590},[5429,6633,6635,6638,6640,6643],{"class":5431,"line":6634},66,[5429,6636,6637],{"class":5579},"    switch",[5429,6639,5260],{"class":5590},[5429,6641,6642],{"class":5596},"operation",[5429,6644,6092],{"class":5590},[5429,6646,6648,6651,6654],{"class":5431,"line":6647},67,[5429,6649,6650],{"class":5579},"      case",[5429,6652,6653],{"class":5446}," 'read'",[5429,6655,6656],{"class":5590},":\n",[5429,6658,6660,6663,6665,6667,6670],{"class":5431,"line":6659},68,[5429,6661,6662],{"class":5579},"        return",[5429,6664,6378],{"class":5596},[5429,6666,5209],{"class":5590},[5429,6668,6669],{"class":5596},"canRead",[5429,6671,5606],{"class":5590},[5429,6673,6675,6677,6680],{"class":5431,"line":6674},69,[5429,6676,6650],{"class":5579},[5429,6678,6679],{"class":5446}," 'write'",[5429,6681,6656],{"class":5590},[5429,6683,6685,6687,6689,6691,6694],{"class":5431,"line":6684},70,[5429,6686,6662],{"class":5579},[5429,6688,6378],{"class":5596},[5429,6690,5209],{"class":5590},[5429,6692,6693],{"class":5596},"canWrite",[5429,6695,5606],{"class":5590},[5429,6697,6699,6701,6704],{"class":5431,"line":6698},71,[5429,6700,6650],{"class":5579},[5429,6702,6703],{"class":5446}," 'delete'",[5429,6705,6656],{"class":5590},[5429,6707,6709,6711,6713,6715,6718],{"class":5431,"line":6708},72,[5429,6710,6662],{"class":5579},[5429,6712,6378],{"class":5596},[5429,6714,5209],{"class":5590},[5429,6716,6717],{"class":5596},"canDelete",[5429,6719,5606],{"class":5590},[5429,6721,6723,6725,6728],{"class":5431,"line":6722},73,[5429,6724,6650],{"class":5579},[5429,6726,6727],{"class":5446}," 'grant'",[5429,6729,6656],{"class":5590},[5429,6731,6733,6735,6737,6739,6742],{"class":5431,"line":6732},74,[5429,6734,6662],{"class":5579},[5429,6736,6378],{"class":5596},[5429,6738,5209],{"class":5590},[5429,6740,6741],{"class":5596},"canGrantAccess",[5429,6743,5606],{"class":5590},[5429,6745,6747,6750],{"class":5431,"line":6746},75,[5429,6748,6749],{"class":5579},"      default",[5429,6751,6656],{"class":5590},[5429,6753,6755,6757,6759],{"class":5431,"line":6754},76,[5429,6756,6662],{"class":5579},[5429,6758,6298],{"class":5469},[5429,6760,5606],{"class":5590},[5429,6762,6764],{"class":5431,"line":6763},77,[5429,6765,6110],{"class":5590},[5429,6767,6769],{"class":5431,"line":6768},78,[5429,6770,6570],{"class":5590},[5429,6772,6774],{"class":5431,"line":6773},79,[5429,6775,5683],{"class":5590},[5089,6777,6778],{},[5099,6779,6780],{},"Декоратор для вказівки необхідної операції:",[5420,6782,6784],{"className":5565,"code":6783,"language":5567,"meta":5425,"style":5425},"\u002F\u002F decorators\u002Frequire-operation.decorator.ts\nimport { SetMetadata } from '@nestjs\u002Fcommon';\n\nexport const RequireOperation = (operation: 'read' | 'write' | 'delete' | 'grant') =>\n  SetMetadata('operation', operation);\n",[5231,6785,6786,6791,6808,6812,6849],{"__ignoreMap":5425},[5429,6787,6788],{"class":5431,"line":5432},[5429,6789,6790],{"class":5435},"\u002F\u002F decorators\u002Frequire-operation.decorator.ts\n",[5429,6792,6793,6795,6797,6800,6802,6804,6806],{"class":5431,"line":5439},[5429,6794,5821],{"class":5579},[5429,6796,5824],{"class":5590},[5429,6798,6799],{"class":5596},"SetMetadata",[5429,6801,5845],{"class":5590},[5429,6803,5848],{"class":5579},[5429,6805,5851],{"class":5446},[5429,6807,5606],{"class":5590},[5429,6809,6810],{"class":5431,"line":5450},[5429,6811,5454],{"emptyLinePlaceholder":5453},[5429,6813,6814,6816,6819,6822,6825,6827,6829,6831,6833,6835,6837,6839,6841,6843,6846],{"class":5431,"line":5457},[5429,6815,5580],{"class":5579},[5429,6817,6818],{"class":5469}," const",[5429,6820,6821],{"class":5442}," RequireOperation",[5429,6823,6824],{"class":5590}," = (",[5429,6826,6642],{"class":5596},[5429,6828,5600],{"class":5590},[5429,6830,6031],{"class":5446},[5429,6832,6034],{"class":5590},[5429,6834,6037],{"class":5446},[5429,6836,6034],{"class":5590},[5429,6838,6042],{"class":5446},[5429,6840,6034],{"class":5590},[5429,6842,6047],{"class":5446},[5429,6844,6845],{"class":5590},") ",[5429,6847,6848],{"class":5469},"=>\n",[5429,6850,6851,6854,6856,6859,6861,6863],{"class":5431,"line":5463},[5429,6852,6853],{"class":5442},"  SetMetadata",[5429,6855,5975],{"class":5590},[5429,6857,6858],{"class":5446},"'operation'",[5429,6860,5234],{"class":5590},[5429,6862,6642],{"class":5596},[5429,6864,6231],{"class":5590},[5089,6866,6867],{},[5099,6868,6869],{},"Контролер для роботи з документами:",[5420,6871,6873],{"className":5565,"code":6872,"language":5567,"meta":5425,"style":5425},"\u002F\u002F controllers\u002Fdocuments.controller.ts\nimport { Controller, Get, Put, Delete, Post, Param, Body, UseGuards } from '@nestjs\u002Fcommon';\nimport { AuthGuard } from '..\u002Fguards\u002Fauth.guard';\nimport { DacAuthorizationGuard } from '..\u002Fguards\u002Fdac-authorization.guard';\nimport { RequireOperation } from '..\u002Fdecorators\u002Frequire-operation.decorator';\nimport { CurrentUser } from '..\u002Fdecorators\u002Fcurrent-user.decorator';\n\n@Controller('documents')\n@UseGuards(AuthGuard, DacAuthorizationGuard)\nexport class DocumentsController {\n  constructor(private documentService: DocumentService) {}\n\n  \u002F\u002F Читання документа — потребує canRead\n  @Get(':id')\n  @RequireOperation('read')\n  async getDocument(@Param('id') id: string) {\n    return this.documentService.findById(id);\n  }\n\n  \u002F\u002F Редагування документа — потребує canWrite\n  @Put(':id')\n  @RequireOperation('write')\n  async updateDocument(\n    @Param('id') id: string,\n    @Body() updateDto: UpdateDocumentDto\n  ) {\n    return this.documentService.update(id, updateDto);\n  }\n\n  \u002F\u002F Видалення документа — потребує canDelete\n  @Delete(':id')\n  @RequireOperation('delete')\n  async deleteDocument(@Param('id') id: string) {\n    return this.documentService.delete(id);\n  }\n\n  \u002F\u002F Надання доступу іншому користувачеві — потребує canGrantAccess\n  @Post(':id\u002Fpermissions')\n  @RequireOperation('grant')\n  async grantPermission(\n    @Param('id') id: string,\n    @Body() grantDto: GrantPermissionDto,\n    @CurrentUser() currentUser: JwtPayload\n  ) {\n    return this.documentService.grantPermission(id, grantDto);\n  }\n}\n",[5231,6874,6875,6880,6932,6950,6968,6986,7004,7008,7022,7038,7049,7067,7071,7076,7090,7102,7129,7149,7153,7157,7162,7174,7186,7195,7216,7233,7238,7263,7267,7271,7276,7288,7300,7325,7346,7350,7354,7359,7372,7384,7393,7413,7431,7446,7450,7475,7479],{"__ignoreMap":5425},[5429,6876,6877],{"class":5431,"line":5432},[5429,6878,6879],{"class":5435},"\u002F\u002F controllers\u002Fdocuments.controller.ts\n",[5429,6881,6882,6884,6886,6889,6891,6894,6896,6899,6901,6904,6906,6909,6911,6914,6916,6919,6921,6924,6926,6928,6930],{"class":5431,"line":5439},[5429,6883,5821],{"class":5579},[5429,6885,5824],{"class":5590},[5429,6887,6888],{"class":5596},"Controller",[5429,6890,5234],{"class":5590},[5429,6892,6893],{"class":5596},"Get",[5429,6895,5234],{"class":5590},[5429,6897,6898],{"class":5596},"Put",[5429,6900,5234],{"class":5590},[5429,6902,6903],{"class":5596},"Delete",[5429,6905,5234],{"class":5590},[5429,6907,6908],{"class":5596},"Post",[5429,6910,5234],{"class":5590},[5429,6912,6913],{"class":5596},"Param",[5429,6915,5234],{"class":5590},[5429,6917,6918],{"class":5596},"Body",[5429,6920,5234],{"class":5590},[5429,6922,6923],{"class":5596},"UseGuards",[5429,6925,5845],{"class":5590},[5429,6927,5848],{"class":5579},[5429,6929,5851],{"class":5446},[5429,6931,5606],{"class":5590},[5429,6933,6934,6936,6938,6941,6943,6945,6948],{"class":5431,"line":5450},[5429,6935,5821],{"class":5579},[5429,6937,5824],{"class":5590},[5429,6939,6940],{"class":5596},"AuthGuard",[5429,6942,5845],{"class":5590},[5429,6944,5848],{"class":5579},[5429,6946,6947],{"class":5446}," '..\u002Fguards\u002Fauth.guard'",[5429,6949,5606],{"class":5590},[5429,6951,6952,6954,6956,6959,6961,6963,6966],{"class":5431,"line":5457},[5429,6953,5821],{"class":5579},[5429,6955,5824],{"class":5590},[5429,6957,6958],{"class":5596},"DacAuthorizationGuard",[5429,6960,5845],{"class":5590},[5429,6962,5848],{"class":5579},[5429,6964,6965],{"class":5446}," '..\u002Fguards\u002Fdac-authorization.guard'",[5429,6967,5606],{"class":5590},[5429,6969,6970,6972,6974,6977,6979,6981,6984],{"class":5431,"line":5463},[5429,6971,5821],{"class":5579},[5429,6973,5824],{"class":5590},[5429,6975,6976],{"class":5596},"RequireOperation",[5429,6978,5845],{"class":5590},[5429,6980,5848],{"class":5579},[5429,6982,6983],{"class":5446}," '..\u002Fdecorators\u002Frequire-operation.decorator'",[5429,6985,5606],{"class":5590},[5429,6987,6988,6990,6992,6995,6997,6999,7002],{"class":5431,"line":5475},[5429,6989,5821],{"class":5579},[5429,6991,5824],{"class":5590},[5429,6993,6994],{"class":5596},"CurrentUser",[5429,6996,5845],{"class":5590},[5429,6998,5848],{"class":5579},[5429,7000,7001],{"class":5446}," '..\u002Fdecorators\u002Fcurrent-user.decorator'",[5429,7003,5606],{"class":5590},[5429,7005,7006],{"class":5431,"line":5481},[5429,7007,5454],{"emptyLinePlaceholder":5453},[5429,7009,7010,7012,7014,7016,7019],{"class":5431,"line":5487},[5429,7011,5898],{"class":5590},[5429,7013,6888],{"class":5442},[5429,7015,5975],{"class":5590},[5429,7017,7018],{"class":5446},"'documents'",[5429,7020,7021],{"class":5590},")\n",[5429,7023,7024,7026,7028,7030,7032,7034,7036],{"class":5431,"line":5493},[5429,7025,5898],{"class":5590},[5429,7027,6923],{"class":5442},[5429,7029,5975],{"class":5590},[5429,7031,6940],{"class":5596},[5429,7033,5234],{"class":5590},[5429,7035,6958],{"class":5596},[5429,7037,7021],{"class":5590},[5429,7039,7040,7042,7044,7047],{"class":5431,"line":5499},[5429,7041,5580],{"class":5579},[5429,7043,5583],{"class":5469},[5429,7045,7046],{"class":5586}," DocumentsController",[5429,7048,5591],{"class":5590},[5429,7050,7051,7053,7055,7058,7060,7062,7064],{"class":5431,"line":5505},[5429,7052,5925],{"class":5469},[5429,7054,5975],{"class":5590},[5429,7056,7057],{"class":5469},"private",[5429,7059,5950],{"class":5596},[5429,7061,5600],{"class":5590},[5429,7063,5880],{"class":5586},[5429,7065,7066],{"class":5590},") {}\n",[5429,7068,7069],{"class":5431,"line":5510},[5429,7070,5454],{"emptyLinePlaceholder":5453},[5429,7072,7073],{"class":5431,"line":5516},[5429,7074,7075],{"class":5435},"  \u002F\u002F Читання документа — потребує canRead\n",[5429,7077,7078,7081,7083,7085,7088],{"class":5431,"line":5527},[5429,7079,7080],{"class":5590},"  @",[5429,7082,6893],{"class":5442},[5429,7084,5975],{"class":5590},[5429,7086,7087],{"class":5446},"':id'",[5429,7089,7021],{"class":5590},[5429,7091,7092,7094,7096,7098,7100],{"class":5431,"line":5532},[5429,7093,7080],{"class":5590},[5429,7095,6976],{"class":5442},[5429,7097,5975],{"class":5590},[5429,7099,6031],{"class":5446},[5429,7101,7021],{"class":5590},[5429,7103,7104,7106,7109,7112,7114,7116,7119,7121,7123,7125,7127],{"class":5431,"line":5538},[5429,7105,5969],{"class":5469},[5429,7107,7108],{"class":5442}," getDocument",[5429,7110,7111],{"class":5590},"(@",[5429,7113,6913],{"class":5442},[5429,7115,5975],{"class":5590},[5429,7117,7118],{"class":5446},"'id'",[5429,7120,6845],{"class":5590},[5429,7122,6186],{"class":5596},[5429,7124,5600],{"class":5590},[5429,7126,5603],{"class":5586},[5429,7128,6092],{"class":5590},[5429,7130,7131,7133,7135,7137,7139,7141,7143,7145,7147],{"class":5431,"line":5547},[5429,7132,6560],{"class":5579},[5429,7134,6257],{"class":5469},[5429,7136,5209],{"class":5590},[5429,7138,6262],{"class":5596},[5429,7140,5209],{"class":5590},[5429,7142,6267],{"class":5442},[5429,7144,5975],{"class":5590},[5429,7146,6186],{"class":5596},[5429,7148,6231],{"class":5590},[5429,7150,7151],{"class":5431,"line":5748},[5429,7152,6570],{"class":5590},[5429,7154,7155],{"class":5431,"line":5760},[5429,7156,5454],{"emptyLinePlaceholder":5453},[5429,7158,7159],{"class":5431,"line":5772},[5429,7160,7161],{"class":5435},"  \u002F\u002F Редагування документа — потребує canWrite\n",[5429,7163,7164,7166,7168,7170,7172],{"class":5431,"line":5787},[5429,7165,7080],{"class":5590},[5429,7167,6898],{"class":5442},[5429,7169,5975],{"class":5590},[5429,7171,7087],{"class":5446},[5429,7173,7021],{"class":5590},[5429,7175,7176,7178,7180,7182,7184],{"class":5431,"line":5799},[5429,7177,7080],{"class":5590},[5429,7179,6976],{"class":5442},[5429,7181,5975],{"class":5590},[5429,7183,6037],{"class":5446},[5429,7185,7021],{"class":5590},[5429,7187,7188,7190,7193],{"class":5431,"line":6113},[5429,7189,5969],{"class":5469},[5429,7191,7192],{"class":5442}," updateDocument",[5429,7194,5928],{"class":5590},[5429,7196,7197,7200,7202,7204,7206,7208,7210,7212,7214],{"class":5431,"line":6118},[5429,7198,7199],{"class":5590},"    @",[5429,7201,6913],{"class":5442},[5429,7203,5975],{"class":5590},[5429,7205,7118],{"class":5446},[5429,7207,6845],{"class":5590},[5429,7209,6186],{"class":5596},[5429,7211,5600],{"class":5590},[5429,7213,5603],{"class":5586},[5429,7215,5943],{"class":5590},[5429,7217,7218,7220,7222,7225,7228,7230],{"class":5431,"line":6144},[5429,7219,7199],{"class":5590},[5429,7221,6918],{"class":5442},[5429,7223,7224],{"class":5590},"() ",[5429,7226,7227],{"class":5596},"updateDto",[5429,7229,5600],{"class":5590},[5429,7231,7232],{"class":5586},"UpdateDocumentDto\n",[5429,7234,7235],{"class":5431,"line":6167},[5429,7236,7237],{"class":5590},"  ) {\n",[5429,7239,7240,7242,7244,7246,7248,7250,7253,7255,7257,7259,7261],{"class":5431,"line":6191},[5429,7241,6560],{"class":5579},[5429,7243,6257],{"class":5469},[5429,7245,5209],{"class":5590},[5429,7247,6262],{"class":5596},[5429,7249,5209],{"class":5590},[5429,7251,7252],{"class":5442},"update",[5429,7254,5975],{"class":5590},[5429,7256,6186],{"class":5596},[5429,7258,5234],{"class":5590},[5429,7260,7227],{"class":5596},[5429,7262,6231],{"class":5590},[5429,7264,7265],{"class":5431,"line":6196},[5429,7266,6570],{"class":5590},[5429,7268,7269],{"class":5431,"line":6214},[5429,7270,5454],{"emptyLinePlaceholder":5453},[5429,7272,7273],{"class":5431,"line":6234},[5429,7274,7275],{"class":5435},"  \u002F\u002F Видалення документа — потребує canDelete\n",[5429,7277,7278,7280,7282,7284,7286],{"class":5431,"line":6239},[5429,7279,7080],{"class":5590},[5429,7281,6903],{"class":5442},[5429,7283,5975],{"class":5590},[5429,7285,7087],{"class":5446},[5429,7287,7021],{"class":5590},[5429,7289,7290,7292,7294,7296,7298],{"class":5431,"line":6244},[5429,7291,7080],{"class":5590},[5429,7293,6976],{"class":5442},[5429,7295,5975],{"class":5590},[5429,7297,6042],{"class":5446},[5429,7299,7021],{"class":5590},[5429,7301,7302,7304,7307,7309,7311,7313,7315,7317,7319,7321,7323],{"class":5431,"line":6276},[5429,7303,5969],{"class":5469},[5429,7305,7306],{"class":5442}," deleteDocument",[5429,7308,7111],{"class":5590},[5429,7310,6913],{"class":5442},[5429,7312,5975],{"class":5590},[5429,7314,7118],{"class":5446},[5429,7316,6845],{"class":5590},[5429,7318,6186],{"class":5596},[5429,7320,5600],{"class":5590},[5429,7322,5603],{"class":5586},[5429,7324,6092],{"class":5590},[5429,7326,7327,7329,7331,7333,7335,7337,7340,7342,7344],{"class":5431,"line":6281},[5429,7328,6560],{"class":5579},[5429,7330,6257],{"class":5469},[5429,7332,5209],{"class":5590},[5429,7334,6262],{"class":5596},[5429,7336,5209],{"class":5590},[5429,7338,7339],{"class":5442},"delete",[5429,7341,5975],{"class":5590},[5429,7343,6186],{"class":5596},[5429,7345,6231],{"class":5590},[5429,7347,7348],{"class":5431,"line":6293},[5429,7349,6570],{"class":5590},[5429,7351,7352],{"class":5431,"line":6306},[5429,7353,5454],{"emptyLinePlaceholder":5453},[5429,7355,7356],{"class":5431,"line":6311},[5429,7357,7358],{"class":5435},"  \u002F\u002F Надання доступу іншому користувачеві — потребує canGrantAccess\n",[5429,7360,7361,7363,7365,7367,7370],{"class":5431,"line":6316},[5429,7362,7080],{"class":5590},[5429,7364,6908],{"class":5442},[5429,7366,5975],{"class":5590},[5429,7368,7369],{"class":5446},"':id\u002Fpermissions'",[5429,7371,7021],{"class":5590},[5429,7373,7374,7376,7378,7380,7382],{"class":5431,"line":6322},[5429,7375,7080],{"class":5590},[5429,7377,6976],{"class":5442},[5429,7379,5975],{"class":5590},[5429,7381,6047],{"class":5446},[5429,7383,7021],{"class":5590},[5429,7385,7386,7388,7391],{"class":5431,"line":6348},[5429,7387,5969],{"class":5469},[5429,7389,7390],{"class":5442}," grantPermission",[5429,7392,5928],{"class":5590},[5429,7394,7395,7397,7399,7401,7403,7405,7407,7409,7411],{"class":5431,"line":6357},[5429,7396,7199],{"class":5590},[5429,7398,6913],{"class":5442},[5429,7400,5975],{"class":5590},[5429,7402,7118],{"class":5446},[5429,7404,6845],{"class":5590},[5429,7406,6186],{"class":5596},[5429,7408,5600],{"class":5590},[5429,7410,5603],{"class":5586},[5429,7412,5943],{"class":5590},[5429,7414,7415,7417,7419,7421,7424,7426,7429],{"class":5431,"line":6362},[5429,7416,7199],{"class":5590},[5429,7418,6918],{"class":5442},[5429,7420,7224],{"class":5590},[5429,7422,7423],{"class":5596},"grantDto",[5429,7425,5600],{"class":5590},[5429,7427,7428],{"class":5586},"GrantPermissionDto",[5429,7430,5943],{"class":5590},[5429,7432,7433,7435,7437,7439,7441,7443],{"class":5431,"line":6367},[5429,7434,7199],{"class":5590},[5429,7436,6994],{"class":5442},[5429,7438,7224],{"class":5590},[5429,7440,6203],{"class":5596},[5429,7442,5600],{"class":5590},[5429,7444,7445],{"class":5586},"JwtPayload\n",[5429,7447,7448],{"class":5431,"line":6373},[5429,7449,7237],{"class":5590},[5429,7451,7452,7454,7456,7458,7460,7462,7465,7467,7469,7471,7473],{"class":5431,"line":6420},[5429,7453,6560],{"class":5579},[5429,7455,6257],{"class":5469},[5429,7457,5209],{"class":5590},[5429,7459,6262],{"class":5596},[5429,7461,5209],{"class":5590},[5429,7463,7464],{"class":5442},"grantPermission",[5429,7466,5975],{"class":5590},[5429,7468,6186],{"class":5596},[5429,7470,5234],{"class":5590},[5429,7472,7423],{"class":5596},[5429,7474,6231],{"class":5590},[5429,7476,7477],{"class":5431,"line":6425},[5429,7478,6570],{"class":5590},[5429,7480,7481],{"class":5431,"line":6437},[5429,7482,5683],{"class":5590},[5317,7484,7486],{"id":7485},"переваги-та-недоліки-dac","Переваги та недоліки DAC",[5089,7488,7489],{},[5099,7490,7491],{},"Переваги:",[5093,7493,7494,7500,7506,7512],{},[5096,7495,7496,7499],{},[5099,7497,7498],{},"Інтуїтивність:"," модель відображає природні уявлення про власність — «Я створив документ, я вирішую, хто його бачить».",[5096,7501,7502,7505],{},[5099,7503,7504],{},"Гнучкість:"," власник може миттєво надати або відкликати доступ без звернення до адміністратора.",[5096,7507,7508,7511],{},[5099,7509,7510],{},"Низька складність адміністрування:"," не потребує складних політик безпеки та централізованого управління.",[5096,7513,7514,7517],{},[5099,7515,7516],{},"Ефективність для особистих даних:"," ідеально підходить для систем зберігання файлів, де користувачі працюють з власними даними та іноді діляться ними.",[5089,7519,7520],{},[5099,7521,7522],{},"Недоліки:",[5093,7524,7525,7531,7539,7545],{},[5096,7526,7527,7530],{},[5099,7528,7529],{},"Відсутність централізованого контролю:"," адміністратор не може централізовано переглянути, хто має доступ до конфіденційних даних по всій системі.",[5096,7532,7533,7535,7536,7538],{},[5099,7534,5354],{}," якщо користувач A надав доступ користувачеві B з правом ",[5231,7537,6741],{},", а B надав доступ C, виникає ланцюжок делегувань, що може бути важко відстежити.",[5096,7540,7541,7544],{},[5099,7542,7543],{},"Складність аудиту:"," відповідь на питання «Хто має доступ до всіх документів, що містять фінансові дані?» вимагає перебору всіх документів та їхніх списків дозволів.",[5096,7546,7547,7550,7551,7553],{},[5099,7548,7549],{},"Проблема відкликання прав:"," якщо користувач A надав доступ B, а B — користувачеві C, і тепер A хоче відкликати доступ у C, йому потрібно або знати про існування C, або відкликати право ",[5231,7552,6741],{}," у B, що впливає на всіх, кому B надав доступ.",[7555,7556,7557,7560,7561,7564,7565,5209],"warning",{},[5099,7558,7559],{},"Проблема трояна (Trojan Horse Problem):"," у DAC системах зловмисник може отримати доступ до конфіденційних даних через ланцюжок делегувань. Наприклад, користувач із доступом до секретного документа може скопіювати його вміст у новий документ та надати доступ іншій особі, обходячи первинні обмеження. DAC не контролює ",[5099,7562,7563],{},"поширення інформації",", лише ",[5099,7566,7567],{},"пряме копіювання файлів",[5317,7569,7571],{"id":7570},"типові-сценарії-використання-dac","Типові сценарії використання DAC",[5089,7573,7574],{},[5099,7575,7576],{},"Файлові сховища та хмарні диски:",[5093,7578,7579,7582],{},[5096,7580,7581],{},"Google Drive, Dropbox, OneDrive — користувач завантажує файл та вручну налаштовує доступ через інтерфейс «Share» \u002F «Поділитися».",[5096,7583,7584,7585,7588,7589,7592,7593,7595],{},"Кожен файл має власника та список користувачів з правами ",[5231,7586,7587],{},"viewer"," (читання), ",[5231,7590,7591],{},"editor"," (редагування), ",[5231,7594,5311],{}," (повний контроль).",[5089,7597,7598],{},[5099,7599,7600],{},"Системи управління документами (DMS):",[5093,7602,7603],{},[5096,7604,7605],{},"Confluence, Notion, SharePoint — сторінки та документи створюються користувачами, які самостійно налаштовують рівні доступу для колег.",[5089,7607,7608],{},[5099,7609,7610],{},"Бази даних (SQL):",[5093,7612,7613],{},[5096,7614,7615,7616,7619,7620,5418],{},"PostgreSQL, MySQL підтримують DAC через команди ",[5231,7617,7618],{},"GRANT"," та ",[5231,7621,7622],{},"REVOKE",[5420,7624,7628],{"className":7625,"code":7626,"language":7627,"meta":5425,"style":5425},"language-sql shiki shiki-themes light-plus dark-plus dark-plus","-- Власник таблиці надає право читання іншому користувачеві\nGRANT SELECT ON users TO analyst_user;\n\n-- Передача права надавати доступ іншим\nGRANT SELECT ON users TO manager_user WITH GRANT OPTION;\n","sql",[5231,7629,7630,7635,7654,7658,7663],{"__ignoreMap":5425},[5429,7631,7632],{"class":5431,"line":5432},[5429,7633,7634],{"class":5435},"-- Власник таблиці надає право читання іншому користувачеві\n",[5429,7636,7637,7639,7642,7645,7648,7651],{"class":5431,"line":5439},[5429,7638,7618],{"class":5469},[5429,7640,7641],{"class":5469}," SELECT",[5429,7643,7644],{"class":5469}," ON",[5429,7646,7647],{"class":5590}," users ",[5429,7649,7650],{"class":5469},"TO",[5429,7652,7653],{"class":5590}," analyst_user;\n",[5429,7655,7656],{"class":5431,"line":5450},[5429,7657,5454],{"emptyLinePlaceholder":5453},[5429,7659,7660],{"class":5431,"line":5457},[5429,7661,7662],{"class":5435},"-- Передача права надавати доступ іншим\n",[5429,7664,7665,7667,7669,7671,7673,7675,7678,7681,7684,7687],{"class":5431,"line":5463},[5429,7666,7618],{"class":5469},[5429,7668,7641],{"class":5469},[5429,7670,7644],{"class":5469},[5429,7672,7647],{"class":5590},[5429,7674,7650],{"class":5469},[5429,7676,7677],{"class":5590}," manager_user ",[5429,7679,7680],{"class":5469},"WITH",[5429,7682,7683],{"class":5469}," GRANT",[5429,7685,7686],{"class":5469}," OPTION",[5429,7688,5606],{"class":5590},[5125,7690],{},[5084,7692,7694],{"id":7693},"mac-мандатний-контроль-доступу","MAC: Мандатний контроль доступу",[5089,7696,7697,7700,7701,7704,7705,5260,7708,7711],{},[5099,7698,7699],{},"Mandatory Access Control (MAC)"," — це модель, у якій права доступу визначаються ",[5099,7702,7703],{},"централізованою політикою безпеки",", що не може бути змінена індивідуальними користувачами або власниками ресурсів. Система присвоює кожному суб'єкту (користувачеві, процесу) та об'єкту (файлу, ресурсу) ",[5099,7706,7707],{},"мітку безпеки",[5194,7709,7710],{},"security label","), і доступ надається або відхиляється на основі формальних правил порівняння цих міток.",[5317,7713,7715],{"id":7714},"базові-принципи-mac","Базові принципи MAC",[5089,7717,7718],{},[5099,7719,5325],{},[5093,7721,7722,7732,7764,7770],{},[5096,7723,7724,7727,7728,7731],{},[5099,7725,7726],{},"Централізоване управління:"," всі рішення про доступ приймаються на основі глобальної політики, встановленої адміністратором безпеки (",[5194,7729,7730],{},"security administrator","). Звичайні користувачі не можуть змінювати мітки безпеки або обходити правила.",[5096,7733,7734,7737,7738,5260,7741,7744,7745,5260,7748,7751,7752,5234,7755,5234,7758,5234,7761,5209],{},[5099,7735,7736],{},"Мітки безпеки:"," кожен суб'єкт отримує ",[5099,7739,7740],{},"рівень допуску",[5194,7742,7743],{},"clearance level","), а кожен об'єкт — ",[5099,7746,7747],{},"рівень класифікації",[5194,7749,7750],{},"classification level","). Типові рівні у військових системах: ",[5231,7753,7754],{},"Unclassified",[5231,7756,7757],{},"Confidential",[5231,7759,7760],{},"Secret",[5231,7762,7763],{},"Top Secret",[5096,7765,7766,7769],{},[5099,7767,7768],{},"Неможливість зниження класифікації:"," користувач не може самостійно знизити рівень секретності документа або передати інформацію особі з нижчим рівнем допуску. Це запобігає витокам через соціальну інженерію.",[5096,7771,7772,7775,7776,5242],{},[5099,7773,7774],{},"Формальна перевірка моделі:"," MAC політики часто виражаються через математичні моделі (наприклад, модель Белла-ЛаПадули), що дозволяє формально довести відсутність витоків інформації (",[5194,7777,7778],{},"information flow control",[5317,7780,7782],{"id":7781},"модель-белла-лападули-bell-lapadula","Модель Белла-ЛаПадули (Bell-LaPadula)",[5089,7784,7785,7786,7789],{},"Найвідоміша формалізація MAC — модель Белла-ЛаПадули (",[5194,7787,7788],{},"Bell-LaPadula Model","), розроблена у 1973 році для Міністерства оборони США. Вона визначає два фундаментальні правила:",[5089,7791,7792,7795,7796,7799,7800,7803],{},[5099,7793,7794],{},"Правило 1: No Read Up (Simple Security Property)","\nСуб'єкт може ",[5099,7797,7798],{},"читати"," об'єкт лише якщо рівень допуску суб'єкта ",[5099,7801,7802],{},"не нижчий"," за рівень класифікації об'єкта.",[5093,7805,7806,7818],{},[5096,7807,7808,7809,7811,7812,5234,7814,5234,7816,5209],{},"Користувач з рівнем ",[5231,7810,7760],{}," може читати документи ",[5231,7813,7754],{},[5231,7815,7757],{},[5231,7817,7760],{},[5096,7819,7808,7820,7822,7823,7826,7827,5209],{},[5231,7821,7760],{}," ",[5099,7824,7825],{},"не може"," читати документи ",[5231,7828,7763],{},[5089,7830,7831,7795,7834,7799,7837,7803],{},[5099,7832,7833],{},"Правило 2: No Write Down (*-Property, Star Property)",[5099,7835,7836],{},"записувати",[5099,7838,7839],{},"не вищий",[5093,7841,7842,7852],{},[5096,7843,7808,7844,7846,7847,7849,7850,5209],{},[5231,7845,7760],{}," може створювати документи з класифікацією ",[5231,7848,7760],{}," або ",[5231,7851,7763],{},[5096,7853,7808,7854,7822,7856,7858,7859,7849,7861,7863],{},[5231,7855,7760],{},[5099,7857,7825],{}," створювати документи ",[5231,7860,7757],{},[5231,7862,7754],{}," (щоб запобігти витоку інформації через зниження класифікації).",[5278,7865,7866,7867,7870,7871,7874,7875,7877,7878,7880,7881,7884,7885,7888],{},"Правило ",[5099,7868,7869],{},"No Write Down"," здається нелогічним на перший погляд — чому не можна писати у менш секретний файл? Причина у запобіганні ",[5099,7872,7873],{},"витоку інформації",": якщо користувач з доступом до ",[5231,7876,7763],{}," даних зможе записати їх у ",[5231,7879,7754],{}," файл, ці дані стануть доступні всім. Модель Белла-ЛаПадули захищає ",[5099,7882,7883],{},"конфіденційність",", але ",[5099,7886,7887],{},"не цілісність"," (для цього існує модель Біби — Biba Model).",[5317,7890,7892],{"id":7891},"візуалізація-моделі-белла-лападули","Візуалізація моделі Белла-ЛаПадули",[7894,7895,7896],"mermaid",{},[5420,7897,7900],{"className":7898,"code":7899,"language":7894,"meta":5425,"style":5425},"language-mermaid shiki shiki-themes light-plus dark-plus dark-plus","graph TB\n    subgraph \"Рівні класифікації (від нижчого до вищого)\"\n        L1[Unclassified\u003Cbr\u002F>Несекретно]\n        L2[Confidential\u003Cbr\u002F>Конфіденційно]\n        L3[Secret\u003Cbr\u002F>Таємно]\n        L4[Top Secret\u003Cbr\u002F>Цілком таємно]\n    end\n    \n    subgraph \"Користувач з допуском Secret\"\n        U[User: Secret Clearance]\n    end\n    \n    U -->|✅ Read Allowed| L1\n    U -->|✅ Read Allowed| L2\n    U -->|✅ Read Allowed| L3\n    U -->|❌ Read Denied\u003Cbr\u002F>No Read Up| L4\n    \n    U -->|❌ Write Denied\u003Cbr\u002F>No Write Down| L1\n    U -->|❌ Write Denied\u003Cbr\u002F>No Write Down| L2\n    U -->|✅ Write Allowed| L3\n    U -->|✅ Write Allowed| L4\n    \n    style L1 fill:#10b981,stroke:#047857,color:#ffffff\n    style L2 fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n    style L3 fill:#f59e0b,stroke:#b45309,color:#ffffff\n    style L4 fill:#ef4444,stroke:#b91c1c,color:#ffffff\n    style U fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n",[5231,7901,7902,7907,7912,7917,7922,7927,7932,7937,7942,7947,7952,7956,7960,7965,7970,7975,7980,7984,7989,7994,7999,8004,8008,8013,8018,8023,8028],{"__ignoreMap":5425},[5429,7903,7904],{"class":5431,"line":5432},[5429,7905,7906],{},"graph TB\n",[5429,7908,7909],{"class":5431,"line":5439},[5429,7910,7911],{},"    subgraph \"Рівні класифікації (від нижчого до вищого)\"\n",[5429,7913,7914],{"class":5431,"line":5450},[5429,7915,7916],{},"        L1[Unclassified\u003Cbr\u002F>Несекретно]\n",[5429,7918,7919],{"class":5431,"line":5457},[5429,7920,7921],{},"        L2[Confidential\u003Cbr\u002F>Конфіденційно]\n",[5429,7923,7924],{"class":5431,"line":5463},[5429,7925,7926],{},"        L3[Secret\u003Cbr\u002F>Таємно]\n",[5429,7928,7929],{"class":5431,"line":5475},[5429,7930,7931],{},"        L4[Top Secret\u003Cbr\u002F>Цілком таємно]\n",[5429,7933,7934],{"class":5431,"line":5481},[5429,7935,7936],{},"    end\n",[5429,7938,7939],{"class":5431,"line":5487},[5429,7940,7941],{},"    \n",[5429,7943,7944],{"class":5431,"line":5493},[5429,7945,7946],{},"    subgraph \"Користувач з допуском Secret\"\n",[5429,7948,7949],{"class":5431,"line":5499},[5429,7950,7951],{},"        U[User: Secret Clearance]\n",[5429,7953,7954],{"class":5431,"line":5505},[5429,7955,7936],{},[5429,7957,7958],{"class":5431,"line":5510},[5429,7959,7941],{},[5429,7961,7962],{"class":5431,"line":5516},[5429,7963,7964],{},"    U -->|✅ Read Allowed| L1\n",[5429,7966,7967],{"class":5431,"line":5527},[5429,7968,7969],{},"    U -->|✅ Read Allowed| L2\n",[5429,7971,7972],{"class":5431,"line":5532},[5429,7973,7974],{},"    U -->|✅ Read Allowed| L3\n",[5429,7976,7977],{"class":5431,"line":5538},[5429,7978,7979],{},"    U -->|❌ Read Denied\u003Cbr\u002F>No Read Up| L4\n",[5429,7981,7982],{"class":5431,"line":5547},[5429,7983,7941],{},[5429,7985,7986],{"class":5431,"line":5748},[5429,7987,7988],{},"    U -->|❌ Write Denied\u003Cbr\u002F>No Write Down| L1\n",[5429,7990,7991],{"class":5431,"line":5760},[5429,7992,7993],{},"    U -->|❌ Write Denied\u003Cbr\u002F>No Write Down| L2\n",[5429,7995,7996],{"class":5431,"line":5772},[5429,7997,7998],{},"    U -->|✅ Write Allowed| L3\n",[5429,8000,8001],{"class":5431,"line":5787},[5429,8002,8003],{},"    U -->|✅ Write Allowed| L4\n",[5429,8005,8006],{"class":5431,"line":5799},[5429,8007,7941],{},[5429,8009,8010],{"class":5431,"line":6113},[5429,8011,8012],{},"    style L1 fill:#10b981,stroke:#047857,color:#ffffff\n",[5429,8014,8015],{"class":5431,"line":6118},[5429,8016,8017],{},"    style L2 fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n",[5429,8019,8020],{"class":5431,"line":6144},[5429,8021,8022],{},"    style L3 fill:#f59e0b,stroke:#b45309,color:#ffffff\n",[5429,8024,8025],{"class":5431,"line":6167},[5429,8026,8027],{},"    style L4 fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[5429,8029,8030],{"class":5431,"line":6191},[5429,8031,8032],{},"    style U fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n",[5317,8034,8036],{"id":8035},"реалізація-mac-у-веб-застосунку-спрощена","Реалізація MAC у веб-застосунку (спрощена)",[5089,8038,8039],{},"Реалізація повноцінного MAC у веб-застосунках є рідкісною, оскільки більшість комерційних систем не оперують формальними рівнями секретності. Проте розглянемо концептуальну реалізацію для системи управління державними документами:",[5089,8041,8042],{},[5099,8043,5562],{},[5420,8045,8047],{"className":5565,"code":8046,"language":5567,"meta":5425,"style":5425},"\u002F\u002F domain\u002Fsecurity-level.enum.ts\nexport enum SecurityLevel {\n  UNCLASSIFIED = 0,\n  CONFIDENTIAL = 1,\n  SECRET = 2,\n  TOP_SECRET = 3,\n}\n\n\u002F\u002F domain\u002Fclassified-document.entity.ts\nexport class ClassifiedDocument {\n  id: string;\n  title: string;\n  content: string;\n  classification: SecurityLevel; \u002F\u002F Рівень класифікації документа\n  createdBy: string;\n  createdAt: Date;\n}\n\n\u002F\u002F domain\u002Fuser.entity.ts (розширення базової моделі)\nexport class User {\n  id: string;\n  email: string;\n  clearanceLevel: SecurityLevel; \u002F\u002F Рівень допуску користувача\n  department: string;\n}\n",[5231,8048,8049,8054,8066,8078,8090,8102,8114,8118,8122,8127,8138,8148,8158,8168,8183,8194,8204,8208,8212,8217,8228,8238,8249,8263,8274],{"__ignoreMap":5425},[5429,8050,8051],{"class":5431,"line":5432},[5429,8052,8053],{"class":5435},"\u002F\u002F domain\u002Fsecurity-level.enum.ts\n",[5429,8055,8056,8058,8061,8064],{"class":5431,"line":5439},[5429,8057,5580],{"class":5579},[5429,8059,8060],{"class":5469}," enum",[5429,8062,8063],{"class":5586}," SecurityLevel",[5429,8065,5591],{"class":5590},[5429,8067,8068,8071,8073,8076],{"class":5431,"line":5450},[5429,8069,8070],{"class":6009},"  UNCLASSIFIED",[5429,8072,6013],{"class":5590},[5429,8074,8075],{"class":5521},"0",[5429,8077,5943],{"class":5590},[5429,8079,8080,8083,8085,8088],{"class":5431,"line":5457},[5429,8081,8082],{"class":6009},"  CONFIDENTIAL",[5429,8084,6013],{"class":5590},[5429,8086,8087],{"class":5521},"1",[5429,8089,5943],{"class":5590},[5429,8091,8092,8095,8097,8100],{"class":5431,"line":5463},[5429,8093,8094],{"class":6009},"  SECRET",[5429,8096,6013],{"class":5590},[5429,8098,8099],{"class":5521},"2",[5429,8101,5943],{"class":5590},[5429,8103,8104,8107,8109,8112],{"class":5431,"line":5475},[5429,8105,8106],{"class":6009},"  TOP_SECRET",[5429,8108,6013],{"class":5590},[5429,8110,8111],{"class":5521},"3",[5429,8113,5943],{"class":5590},[5429,8115,8116],{"class":5431,"line":5481},[5429,8117,5683],{"class":5590},[5429,8119,8120],{"class":5431,"line":5487},[5429,8121,5454],{"emptyLinePlaceholder":5453},[5429,8123,8124],{"class":5431,"line":5493},[5429,8125,8126],{"class":5435},"\u002F\u002F domain\u002Fclassified-document.entity.ts\n",[5429,8128,8129,8131,8133,8136],{"class":5431,"line":5499},[5429,8130,5580],{"class":5579},[5429,8132,5583],{"class":5469},[5429,8134,8135],{"class":5586}," ClassifiedDocument",[5429,8137,5591],{"class":5590},[5429,8139,8140,8142,8144,8146],{"class":5431,"line":5505},[5429,8141,5597],{"class":5596},[5429,8143,5600],{"class":5590},[5429,8145,5603],{"class":5586},[5429,8147,5606],{"class":5590},[5429,8149,8150,8152,8154,8156],{"class":5431,"line":5510},[5429,8151,5611],{"class":5596},[5429,8153,5600],{"class":5590},[5429,8155,5603],{"class":5586},[5429,8157,5606],{"class":5590},[5429,8159,8160,8162,8164,8166],{"class":5431,"line":5516},[5429,8161,5622],{"class":5596},[5429,8163,5600],{"class":5590},[5429,8165,5603],{"class":5586},[5429,8167,5606],{"class":5590},[5429,8169,8170,8173,8175,8178,8180],{"class":5431,"line":5527},[5429,8171,8172],{"class":5596},"  classification",[5429,8174,5600],{"class":5590},[5429,8176,8177],{"class":5586},"SecurityLevel",[5429,8179,5640],{"class":5590},[5429,8181,8182],{"class":5435},"\u002F\u002F Рівень класифікації документа\n",[5429,8184,8185,8188,8190,8192],{"class":5431,"line":5532},[5429,8186,8187],{"class":5596},"  createdBy",[5429,8189,5600],{"class":5590},[5429,8191,5603],{"class":5586},[5429,8193,5606],{"class":5590},[5429,8195,8196,8198,8200,8202],{"class":5431,"line":5538},[5429,8197,5648],{"class":5596},[5429,8199,5600],{"class":5590},[5429,8201,5653],{"class":5586},[5429,8203,5606],{"class":5590},[5429,8205,8206],{"class":5431,"line":5547},[5429,8207,5683],{"class":5590},[5429,8209,8210],{"class":5431,"line":5748},[5429,8211,5454],{"emptyLinePlaceholder":5453},[5429,8213,8214],{"class":5431,"line":5760},[5429,8215,8216],{"class":5435},"\u002F\u002F domain\u002Fuser.entity.ts (розширення базової моделі)\n",[5429,8218,8219,8221,8223,8226],{"class":5431,"line":5772},[5429,8220,5580],{"class":5579},[5429,8222,5583],{"class":5469},[5429,8224,8225],{"class":5586}," User",[5429,8227,5591],{"class":5590},[5429,8229,8230,8232,8234,8236],{"class":5431,"line":5787},[5429,8231,5597],{"class":5596},[5429,8233,5600],{"class":5590},[5429,8235,5603],{"class":5586},[5429,8237,5606],{"class":5590},[5429,8239,8240,8243,8245,8247],{"class":5431,"line":5799},[5429,8241,8242],{"class":5596},"  email",[5429,8244,5600],{"class":5590},[5429,8246,5603],{"class":5586},[5429,8248,5606],{"class":5590},[5429,8250,8251,8254,8256,8258,8260],{"class":5431,"line":6113},[5429,8252,8253],{"class":5596},"  clearanceLevel",[5429,8255,5600],{"class":5590},[5429,8257,8177],{"class":5586},[5429,8259,5640],{"class":5590},[5429,8261,8262],{"class":5435},"\u002F\u002F Рівень допуску користувача\n",[5429,8264,8265,8268,8270,8272],{"class":5431,"line":6118},[5429,8266,8267],{"class":5596},"  department",[5429,8269,5600],{"class":5590},[5429,8271,5603],{"class":5586},[5429,8273,5606],{"class":5590},[5429,8275,8276],{"class":5431,"line":6144},[5429,8277,5683],{"class":5590},[5089,8279,8280],{},[5099,8281,8282],{},"Guard для перевірки MAC політики:",[5420,8284,8286],{"className":5565,"code":8285,"language":5567,"meta":5425,"style":5425},"\u002F\u002F guards\u002Fmac-authorization.guard.ts\nimport { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs\u002Fcommon';\nimport { Reflector } from '@nestjs\u002Fcore';\nimport { ClassifiedDocumentService } from '..\u002Fservices\u002Fclassified-document.service';\nimport { SecurityLevel } from '..\u002Fdomain\u002Fsecurity-level.enum';\n\n@Injectable()\nexport class MacAuthorizationGuard implements CanActivate {\n  constructor(\n    private reflector: Reflector,\n    private documentService: ClassifiedDocumentService\n  ) {}\n\n  async canActivate(context: ExecutionContext): Promise\u003Cboolean> {\n    const operation = this.reflector.get\u003C'read' | 'write'>('operation', context.getHandler());\n\n    if (!operation) {\n      return true;\n    }\n\n    const request = context.switchToHttp().getRequest();\n    const currentUser = request.user;\n    const documentId = request.params.id;\n\n    if (!currentUser || !documentId) {\n      throw new ForbiddenException('Missing authentication or document ID');\n    }\n\n    const document = await this.documentService.findById(documentId);\n\n    if (!document) {\n      return false;\n    }\n\n    \u002F\u002F Застосовуємо правила Белла-ЛаПадули\n    if (operation === 'read') {\n      \u002F\u002F No Read Up: користувач може читати лише документи свого рівня або нижче\n      if (currentUser.clearanceLevel \u003C document.classification) {\n        throw new ForbiddenException(\n          `Access denied: your clearance level (${SecurityLevel[currentUser.clearanceLevel]}) ` +\n          `is insufficient for documents classified as ${SecurityLevel[document.classification]}`\n        );\n      }\n    }\n\n    if (operation === 'write') {\n      \u002F\u002F No Write Down: користувач може писати лише у документи свого рівня або вище\n      if (currentUser.clearanceLevel > document.classification) {\n        throw new ForbiddenException(\n          `Access denied: you cannot write to documents with lower classification ` +\n          `(No Write Down policy)`\n        );\n      }\n    }\n\n    return true;\n  }\n}\n",[5231,8287,8288,8293,8321,8337,8355,8372,8376,8384,8399,8405,8417,8428,8432,8436,8460,8503,8507,8517,8525,8529,8533,8553,8569,8589,8593,8607,8621,8625,8629,8655,8659,8669,8677,8681,8685,8690,8704,8709,8735,8746,8776,8800,8805,8810,8814,8818,8832,8837,8860,8870,8877,8882,8886,8890,8894,8898,8906,8910],{"__ignoreMap":5425},[5429,8289,8290],{"class":5431,"line":5432},[5429,8291,8292],{"class":5435},"\u002F\u002F guards\u002Fmac-authorization.guard.ts\n",[5429,8294,8295,8297,8299,8301,8303,8305,8307,8309,8311,8313,8315,8317,8319],{"class":5431,"line":5439},[5429,8296,5821],{"class":5579},[5429,8298,5824],{"class":5590},[5429,8300,5827],{"class":5596},[5429,8302,5234],{"class":5590},[5429,8304,5832],{"class":5596},[5429,8306,5234],{"class":5590},[5429,8308,5837],{"class":5596},[5429,8310,5234],{"class":5590},[5429,8312,5842],{"class":5596},[5429,8314,5845],{"class":5590},[5429,8316,5848],{"class":5579},[5429,8318,5851],{"class":5446},[5429,8320,5606],{"class":5590},[5429,8322,8323,8325,8327,8329,8331,8333,8335],{"class":5431,"line":5450},[5429,8324,5821],{"class":5579},[5429,8326,5824],{"class":5590},[5429,8328,5862],{"class":5596},[5429,8330,5845],{"class":5590},[5429,8332,5848],{"class":5579},[5429,8334,5869],{"class":5446},[5429,8336,5606],{"class":5590},[5429,8338,8339,8341,8343,8346,8348,8350,8353],{"class":5431,"line":5457},[5429,8340,5821],{"class":5579},[5429,8342,5824],{"class":5590},[5429,8344,8345],{"class":5596},"ClassifiedDocumentService",[5429,8347,5845],{"class":5590},[5429,8349,5848],{"class":5579},[5429,8351,8352],{"class":5446}," '..\u002Fservices\u002Fclassified-document.service'",[5429,8354,5606],{"class":5590},[5429,8356,8357,8359,8361,8363,8365,8367,8370],{"class":5431,"line":5463},[5429,8358,5821],{"class":5579},[5429,8360,5824],{"class":5590},[5429,8362,8177],{"class":5596},[5429,8364,5845],{"class":5590},[5429,8366,5848],{"class":5579},[5429,8368,8369],{"class":5446}," '..\u002Fdomain\u002Fsecurity-level.enum'",[5429,8371,5606],{"class":5590},[5429,8373,8374],{"class":5431,"line":5475},[5429,8375,5454],{"emptyLinePlaceholder":5453},[5429,8377,8378,8380,8382],{"class":5431,"line":5481},[5429,8379,5898],{"class":5590},[5429,8381,5827],{"class":5442},[5429,8383,5903],{"class":5590},[5429,8385,8386,8388,8390,8393,8395,8397],{"class":5431,"line":5487},[5429,8387,5580],{"class":5579},[5429,8389,5583],{"class":5469},[5429,8391,8392],{"class":5586}," MacAuthorizationGuard",[5429,8394,5915],{"class":5469},[5429,8396,5918],{"class":5586},[5429,8398,5591],{"class":5590},[5429,8400,8401,8403],{"class":5431,"line":5493},[5429,8402,5925],{"class":5469},[5429,8404,5928],{"class":5590},[5429,8406,8407,8409,8411,8413,8415],{"class":5431,"line":5499},[5429,8408,5933],{"class":5469},[5429,8410,5936],{"class":5596},[5429,8412,5600],{"class":5590},[5429,8414,5862],{"class":5586},[5429,8416,5943],{"class":5590},[5429,8418,8419,8421,8423,8425],{"class":5431,"line":5505},[5429,8420,5933],{"class":5469},[5429,8422,5950],{"class":5596},[5429,8424,5600],{"class":5590},[5429,8426,8427],{"class":5586},"ClassifiedDocumentService\n",[5429,8429,8430],{"class":5431,"line":5510},[5429,8431,5960],{"class":5590},[5429,8433,8434],{"class":5431,"line":5516},[5429,8435,5454],{"emptyLinePlaceholder":5453},[5429,8437,8438,8440,8442,8444,8446,8448,8450,8452,8454,8456,8458],{"class":5431,"line":5527},[5429,8439,5969],{"class":5469},[5429,8441,5972],{"class":5442},[5429,8443,5975],{"class":5590},[5429,8445,5978],{"class":5596},[5429,8447,5600],{"class":5590},[5429,8449,5837],{"class":5586},[5429,8451,5985],{"class":5590},[5429,8453,5988],{"class":5586},[5429,8455,5991],{"class":5590},[5429,8457,5743],{"class":5586},[5429,8459,5996],{"class":5590},[5429,8461,8462,8464,8467,8469,8471,8473,8475,8477,8479,8481,8483,8485,8487,8490,8492,8494,8496,8498,8500],{"class":5431,"line":5532},[5429,8463,6006],{"class":5469},[5429,8465,8466],{"class":6009}," operation",[5429,8468,6013],{"class":5590},[5429,8470,6016],{"class":5469},[5429,8472,5209],{"class":5590},[5429,8474,6021],{"class":5596},[5429,8476,5209],{"class":5590},[5429,8478,6026],{"class":5442},[5429,8480,5991],{"class":5590},[5429,8482,6031],{"class":5446},[5429,8484,6034],{"class":5590},[5429,8486,6037],{"class":5446},[5429,8488,8489],{"class":5590},">(",[5429,8491,6858],{"class":5446},[5429,8493,5234],{"class":5590},[5429,8495,5978],{"class":5596},[5429,8497,5209],{"class":5590},[5429,8499,6067],{"class":5442},[5429,8501,8502],{"class":5590},"());\n",[5429,8504,8505],{"class":5431,"line":5538},[5429,8506,5454],{"emptyLinePlaceholder":5453},[5429,8508,8509,8511,8513,8515],{"class":5431,"line":5547},[5429,8510,6083],{"class":5579},[5429,8512,6086],{"class":5590},[5429,8514,6642],{"class":5596},[5429,8516,6092],{"class":5590},[5429,8518,8519,8521,8523],{"class":5431,"line":5748},[5429,8520,6097],{"class":5579},[5429,8522,6100],{"class":5469},[5429,8524,5606],{"class":5590},[5429,8526,8527],{"class":5431,"line":5760},[5429,8528,6110],{"class":5590},[5429,8530,8531],{"class":5431,"line":5772},[5429,8532,5454],{"emptyLinePlaceholder":5453},[5429,8534,8535,8537,8539,8541,8543,8545,8547,8549,8551],{"class":5431,"line":5787},[5429,8536,6006],{"class":5469},[5429,8538,6123],{"class":6009},[5429,8540,6013],{"class":5590},[5429,8542,5978],{"class":5596},[5429,8544,5209],{"class":5590},[5429,8546,6132],{"class":5442},[5429,8548,6135],{"class":5590},[5429,8550,6138],{"class":5442},[5429,8552,6141],{"class":5590},[5429,8554,8555,8557,8559,8561,8563,8565,8567],{"class":5431,"line":5799},[5429,8556,6006],{"class":5469},[5429,8558,6149],{"class":6009},[5429,8560,6013],{"class":5590},[5429,8562,6154],{"class":5596},[5429,8564,5209],{"class":5590},[5429,8566,6159],{"class":5596},[5429,8568,5606],{"class":5590},[5429,8570,8571,8573,8575,8577,8579,8581,8583,8585,8587],{"class":5431,"line":6113},[5429,8572,6006],{"class":5469},[5429,8574,6172],{"class":6009},[5429,8576,6013],{"class":5590},[5429,8578,6154],{"class":5596},[5429,8580,5209],{"class":5590},[5429,8582,6181],{"class":5596},[5429,8584,5209],{"class":5590},[5429,8586,6186],{"class":5596},[5429,8588,5606],{"class":5590},[5429,8590,8591],{"class":5431,"line":6118},[5429,8592,5454],{"emptyLinePlaceholder":5453},[5429,8594,8595,8597,8599,8601,8603,8605],{"class":5431,"line":6144},[5429,8596,6083],{"class":5579},[5429,8598,6086],{"class":5590},[5429,8600,6203],{"class":5596},[5429,8602,6206],{"class":5590},[5429,8604,6209],{"class":5596},[5429,8606,6092],{"class":5590},[5429,8608,8609,8611,8613,8615,8617,8619],{"class":5431,"line":6167},[5429,8610,6217],{"class":5579},[5429,8612,6220],{"class":5469},[5429,8614,6223],{"class":5442},[5429,8616,5975],{"class":5590},[5429,8618,6228],{"class":5446},[5429,8620,6231],{"class":5590},[5429,8622,8623],{"class":5431,"line":6191},[5429,8624,6110],{"class":5590},[5429,8626,8627],{"class":5431,"line":6196},[5429,8628,5454],{"emptyLinePlaceholder":5453},[5429,8630,8631,8633,8635,8637,8639,8641,8643,8645,8647,8649,8651,8653],{"class":5431,"line":6214},[5429,8632,6006],{"class":5469},[5429,8634,6249],{"class":6009},[5429,8636,6013],{"class":5590},[5429,8638,6254],{"class":5579},[5429,8640,6257],{"class":5469},[5429,8642,5209],{"class":5590},[5429,8644,6262],{"class":5596},[5429,8646,5209],{"class":5590},[5429,8648,6267],{"class":5442},[5429,8650,5975],{"class":5590},[5429,8652,6209],{"class":5596},[5429,8654,6231],{"class":5590},[5429,8656,8657],{"class":5431,"line":6234},[5429,8658,5454],{"emptyLinePlaceholder":5453},[5429,8660,8661,8663,8665,8667],{"class":5431,"line":6239},[5429,8662,6083],{"class":5579},[5429,8664,6086],{"class":5590},[5429,8666,6288],{"class":5596},[5429,8668,6092],{"class":5590},[5429,8670,8671,8673,8675],{"class":5431,"line":6244},[5429,8672,6097],{"class":5579},[5429,8674,6298],{"class":5469},[5429,8676,5606],{"class":5590},[5429,8678,8679],{"class":5431,"line":6276},[5429,8680,6110],{"class":5590},[5429,8682,8683],{"class":5431,"line":6281},[5429,8684,5454],{"emptyLinePlaceholder":5453},[5429,8686,8687],{"class":5431,"line":6293},[5429,8688,8689],{"class":5435},"    \u002F\u002F Застосовуємо правила Белла-ЛаПадули\n",[5429,8691,8692,8694,8696,8698,8700,8702],{"class":5431,"line":6306},[5429,8693,6083],{"class":5579},[5429,8695,5260],{"class":5590},[5429,8697,6642],{"class":5596},[5429,8699,6336],{"class":5590},[5429,8701,6031],{"class":5446},[5429,8703,6092],{"class":5590},[5429,8705,8706],{"class":5431,"line":6311},[5429,8707,8708],{"class":5435},"      \u002F\u002F No Read Up: користувач може читати лише документи свого рівня або нижче\n",[5429,8710,8711,8714,8716,8718,8720,8723,8726,8728,8730,8733],{"class":5431,"line":6316},[5429,8712,8713],{"class":5579},"      if",[5429,8715,5260],{"class":5590},[5429,8717,6203],{"class":5596},[5429,8719,5209],{"class":5590},[5429,8721,8722],{"class":5596},"clearanceLevel",[5429,8724,8725],{"class":5590}," \u003C ",[5429,8727,6288],{"class":5596},[5429,8729,5209],{"class":5590},[5429,8731,8732],{"class":5596},"classification",[5429,8734,6092],{"class":5590},[5429,8736,8737,8740,8742,8744],{"class":5431,"line":6322},[5429,8738,8739],{"class":5579},"        throw",[5429,8741,6220],{"class":5469},[5429,8743,6223],{"class":5442},[5429,8745,5928],{"class":5590},[5429,8747,8748,8751,8753,8755,8759,8761,8763,8765,8768,8770,8773],{"class":5431,"line":6348},[5429,8749,8750],{"class":5446},"          `Access denied: your clearance level (",[5429,8752,6530],{"class":5469},[5429,8754,8177],{"class":5596},[5429,8756,8758],{"class":8757},"sD7JJ","[",[5429,8760,6203],{"class":5596},[5429,8762,5209],{"class":8757},[5429,8764,8722],{"class":5596},[5429,8766,8767],{"class":8757},"]",[5429,8769,6535],{"class":5469},[5429,8771,8772],{"class":5446},") `",[5429,8774,8775],{"class":5590}," +\n",[5429,8777,8778,8781,8783,8785,8787,8789,8791,8793,8795,8797],{"class":5431,"line":6357},[5429,8779,8780],{"class":5446},"          `is insufficient for documents classified as ",[5429,8782,6530],{"class":5469},[5429,8784,8177],{"class":5596},[5429,8786,8758],{"class":8757},[5429,8788,6288],{"class":5596},[5429,8790,5209],{"class":8757},[5429,8792,8732],{"class":5596},[5429,8794,8767],{"class":8757},[5429,8796,6535],{"class":5469},[5429,8798,8799],{"class":5446},"`\n",[5429,8801,8802],{"class":5431,"line":6362},[5429,8803,8804],{"class":5590},"        );\n",[5429,8806,8807],{"class":5431,"line":6367},[5429,8808,8809],{"class":5590},"      }\n",[5429,8811,8812],{"class":5431,"line":6373},[5429,8813,6110],{"class":5590},[5429,8815,8816],{"class":5431,"line":6420},[5429,8817,5454],{"emptyLinePlaceholder":5453},[5429,8819,8820,8822,8824,8826,8828,8830],{"class":5431,"line":6425},[5429,8821,6083],{"class":5579},[5429,8823,5260],{"class":5590},[5429,8825,6642],{"class":5596},[5429,8827,6336],{"class":5590},[5429,8829,6037],{"class":5446},[5429,8831,6092],{"class":5590},[5429,8833,8834],{"class":5431,"line":6437},[5429,8835,8836],{"class":5435},"      \u002F\u002F No Write Down: користувач може писати лише у документи свого рівня або вище\n",[5429,8838,8839,8841,8843,8845,8847,8849,8852,8854,8856,8858],{"class":5431,"line":6453},[5429,8840,8713],{"class":5579},[5429,8842,5260],{"class":5590},[5429,8844,6203],{"class":5596},[5429,8846,5209],{"class":5590},[5429,8848,8722],{"class":5596},[5429,8850,8851],{"class":5590}," > ",[5429,8853,6288],{"class":5596},[5429,8855,5209],{"class":5590},[5429,8857,8732],{"class":5596},[5429,8859,6092],{"class":5590},[5429,8861,8862,8864,8866,8868],{"class":5431,"line":6458},[5429,8863,8739],{"class":5579},[5429,8865,6220],{"class":5469},[5429,8867,6223],{"class":5442},[5429,8869,5928],{"class":5590},[5429,8871,8872,8875],{"class":5431,"line":6463},[5429,8873,8874],{"class":5446},"          `Access denied: you cannot write to documents with lower classification `",[5429,8876,8775],{"class":5590},[5429,8878,8879],{"class":5431,"line":6469},[5429,8880,8881],{"class":5446},"          `(No Write Down policy)`\n",[5429,8883,8884],{"class":5431,"line":6496},[5429,8885,8804],{"class":5590},[5429,8887,8888],{"class":5431,"line":6501},[5429,8889,8809],{"class":5590},[5429,8891,8892],{"class":5431,"line":6513},[5429,8893,6110],{"class":5590},[5429,8895,8896],{"class":5431,"line":6524},[5429,8897,5454],{"emptyLinePlaceholder":5453},[5429,8899,8900,8902,8904],{"class":5431,"line":6541},[5429,8901,6560],{"class":5579},[5429,8903,6100],{"class":5469},[5429,8905,5606],{"class":5590},[5429,8907,8908],{"class":5431,"line":6547},[5429,8909,6570],{"class":5590},[5429,8911,8912],{"class":5431,"line":6552},[5429,8913,5683],{"class":5590},[5089,8915,8916],{},[5099,8917,8918],{},"Контролер для створення документів із автоматичним встановленням класифікації:",[5420,8920,8922],{"className":5565,"code":8921,"language":5567,"meta":5425,"style":5425},"\u002F\u002F controllers\u002Fclassified-documents.controller.ts\nimport { Controller, Get, Post, Param, Body, UseGuards } from '@nestjs\u002Fcommon';\nimport { AuthGuard } from '..\u002Fguards\u002Fauth.guard';\nimport { MacAuthorizationGuard } from '..\u002Fguards\u002Fmac-authorization.guard';\nimport { RequireOperation } from '..\u002Fdecorators\u002Frequire-operation.decorator';\nimport { CurrentUser } from '..\u002Fdecorators\u002Fcurrent-user.decorator';\nimport { SecurityLevel } from '..\u002Fdomain\u002Fsecurity-level.enum';\n\n@Controller('classified-documents')\n@UseGuards(AuthGuard, MacAuthorizationGuard)\nexport class ClassifiedDocumentsController {\n  constructor(private documentService: ClassifiedDocumentService) {}\n\n  @Get(':id')\n  @RequireOperation('read')\n  async getDocument(@Param('id') id: string) {\n    return this.documentService.findById(id);\n  }\n\n  @Post()\n  async createDocument(\n    @Body() createDto: CreateClassifiedDocumentDto,\n    @CurrentUser() currentUser: User\n  ) {\n    \u002F\u002F Користувач може створити документ лише зі своїм рівнем класифікації або вище\n    \u002F\u002F (No Write Down: не можна писати у менш секретні документи)\n    if (createDto.classification \u003C currentUser.clearanceLevel) {\n      throw new ForbiddenException(\n        'You cannot create documents with classification lower than your clearance level'\n      );\n    }\n\n    \u002F\u002F Користувач не може створити документ з класифікацією вище за свій допуск\n    if (createDto.classification > currentUser.clearanceLevel) {\n      throw new ForbiddenException(\n        'You cannot create documents with classification higher than your clearance level'\n      );\n    }\n\n    return this.documentService.create({\n      ...createDto,\n      createdBy: currentUser.sub,\n      classification: createDto.classification,\n    });\n  }\n}\n",[5231,8923,8924,8929,8965,8981,8999,9015,9031,9047,9051,9064,9080,9091,9107,9111,9123,9135,9159,9179,9183,9187,9195,9204,9222,9237,9241,9246,9251,9273,9283,9288,9292,9296,9300,9305,9327,9337,9342,9346,9350,9354,9372,9381,9394,9408,9413,9417],{"__ignoreMap":5425},[5429,8925,8926],{"class":5431,"line":5432},[5429,8927,8928],{"class":5435},"\u002F\u002F controllers\u002Fclassified-documents.controller.ts\n",[5429,8930,8931,8933,8935,8937,8939,8941,8943,8945,8947,8949,8951,8953,8955,8957,8959,8961,8963],{"class":5431,"line":5439},[5429,8932,5821],{"class":5579},[5429,8934,5824],{"class":5590},[5429,8936,6888],{"class":5596},[5429,8938,5234],{"class":5590},[5429,8940,6893],{"class":5596},[5429,8942,5234],{"class":5590},[5429,8944,6908],{"class":5596},[5429,8946,5234],{"class":5590},[5429,8948,6913],{"class":5596},[5429,8950,5234],{"class":5590},[5429,8952,6918],{"class":5596},[5429,8954,5234],{"class":5590},[5429,8956,6923],{"class":5596},[5429,8958,5845],{"class":5590},[5429,8960,5848],{"class":5579},[5429,8962,5851],{"class":5446},[5429,8964,5606],{"class":5590},[5429,8966,8967,8969,8971,8973,8975,8977,8979],{"class":5431,"line":5450},[5429,8968,5821],{"class":5579},[5429,8970,5824],{"class":5590},[5429,8972,6940],{"class":5596},[5429,8974,5845],{"class":5590},[5429,8976,5848],{"class":5579},[5429,8978,6947],{"class":5446},[5429,8980,5606],{"class":5590},[5429,8982,8983,8985,8987,8990,8992,8994,8997],{"class":5431,"line":5457},[5429,8984,5821],{"class":5579},[5429,8986,5824],{"class":5590},[5429,8988,8989],{"class":5596},"MacAuthorizationGuard",[5429,8991,5845],{"class":5590},[5429,8993,5848],{"class":5579},[5429,8995,8996],{"class":5446}," '..\u002Fguards\u002Fmac-authorization.guard'",[5429,8998,5606],{"class":5590},[5429,9000,9001,9003,9005,9007,9009,9011,9013],{"class":5431,"line":5463},[5429,9002,5821],{"class":5579},[5429,9004,5824],{"class":5590},[5429,9006,6976],{"class":5596},[5429,9008,5845],{"class":5590},[5429,9010,5848],{"class":5579},[5429,9012,6983],{"class":5446},[5429,9014,5606],{"class":5590},[5429,9016,9017,9019,9021,9023,9025,9027,9029],{"class":5431,"line":5475},[5429,9018,5821],{"class":5579},[5429,9020,5824],{"class":5590},[5429,9022,6994],{"class":5596},[5429,9024,5845],{"class":5590},[5429,9026,5848],{"class":5579},[5429,9028,7001],{"class":5446},[5429,9030,5606],{"class":5590},[5429,9032,9033,9035,9037,9039,9041,9043,9045],{"class":5431,"line":5481},[5429,9034,5821],{"class":5579},[5429,9036,5824],{"class":5590},[5429,9038,8177],{"class":5596},[5429,9040,5845],{"class":5590},[5429,9042,5848],{"class":5579},[5429,9044,8369],{"class":5446},[5429,9046,5606],{"class":5590},[5429,9048,9049],{"class":5431,"line":5487},[5429,9050,5454],{"emptyLinePlaceholder":5453},[5429,9052,9053,9055,9057,9059,9062],{"class":5431,"line":5493},[5429,9054,5898],{"class":5590},[5429,9056,6888],{"class":5442},[5429,9058,5975],{"class":5590},[5429,9060,9061],{"class":5446},"'classified-documents'",[5429,9063,7021],{"class":5590},[5429,9065,9066,9068,9070,9072,9074,9076,9078],{"class":5431,"line":5499},[5429,9067,5898],{"class":5590},[5429,9069,6923],{"class":5442},[5429,9071,5975],{"class":5590},[5429,9073,6940],{"class":5596},[5429,9075,5234],{"class":5590},[5429,9077,8989],{"class":5596},[5429,9079,7021],{"class":5590},[5429,9081,9082,9084,9086,9089],{"class":5431,"line":5505},[5429,9083,5580],{"class":5579},[5429,9085,5583],{"class":5469},[5429,9087,9088],{"class":5586}," ClassifiedDocumentsController",[5429,9090,5591],{"class":5590},[5429,9092,9093,9095,9097,9099,9101,9103,9105],{"class":5431,"line":5510},[5429,9094,5925],{"class":5469},[5429,9096,5975],{"class":5590},[5429,9098,7057],{"class":5469},[5429,9100,5950],{"class":5596},[5429,9102,5600],{"class":5590},[5429,9104,8345],{"class":5586},[5429,9106,7066],{"class":5590},[5429,9108,9109],{"class":5431,"line":5516},[5429,9110,5454],{"emptyLinePlaceholder":5453},[5429,9112,9113,9115,9117,9119,9121],{"class":5431,"line":5527},[5429,9114,7080],{"class":5590},[5429,9116,6893],{"class":5442},[5429,9118,5975],{"class":5590},[5429,9120,7087],{"class":5446},[5429,9122,7021],{"class":5590},[5429,9124,9125,9127,9129,9131,9133],{"class":5431,"line":5532},[5429,9126,7080],{"class":5590},[5429,9128,6976],{"class":5442},[5429,9130,5975],{"class":5590},[5429,9132,6031],{"class":5446},[5429,9134,7021],{"class":5590},[5429,9136,9137,9139,9141,9143,9145,9147,9149,9151,9153,9155,9157],{"class":5431,"line":5538},[5429,9138,5969],{"class":5469},[5429,9140,7108],{"class":5442},[5429,9142,7111],{"class":5590},[5429,9144,6913],{"class":5442},[5429,9146,5975],{"class":5590},[5429,9148,7118],{"class":5446},[5429,9150,6845],{"class":5590},[5429,9152,6186],{"class":5596},[5429,9154,5600],{"class":5590},[5429,9156,5603],{"class":5586},[5429,9158,6092],{"class":5590},[5429,9160,9161,9163,9165,9167,9169,9171,9173,9175,9177],{"class":5431,"line":5547},[5429,9162,6560],{"class":5579},[5429,9164,6257],{"class":5469},[5429,9166,5209],{"class":5590},[5429,9168,6262],{"class":5596},[5429,9170,5209],{"class":5590},[5429,9172,6267],{"class":5442},[5429,9174,5975],{"class":5590},[5429,9176,6186],{"class":5596},[5429,9178,6231],{"class":5590},[5429,9180,9181],{"class":5431,"line":5748},[5429,9182,6570],{"class":5590},[5429,9184,9185],{"class":5431,"line":5760},[5429,9186,5454],{"emptyLinePlaceholder":5453},[5429,9188,9189,9191,9193],{"class":5431,"line":5772},[5429,9190,7080],{"class":5590},[5429,9192,6908],{"class":5442},[5429,9194,5903],{"class":5590},[5429,9196,9197,9199,9202],{"class":5431,"line":5787},[5429,9198,5969],{"class":5469},[5429,9200,9201],{"class":5442}," createDocument",[5429,9203,5928],{"class":5590},[5429,9205,9206,9208,9210,9212,9215,9217,9220],{"class":5431,"line":5799},[5429,9207,7199],{"class":5590},[5429,9209,6918],{"class":5442},[5429,9211,7224],{"class":5590},[5429,9213,9214],{"class":5596},"createDto",[5429,9216,5600],{"class":5590},[5429,9218,9219],{"class":5586},"CreateClassifiedDocumentDto",[5429,9221,5943],{"class":5590},[5429,9223,9224,9226,9228,9230,9232,9234],{"class":5431,"line":6113},[5429,9225,7199],{"class":5590},[5429,9227,6994],{"class":5442},[5429,9229,7224],{"class":5590},[5429,9231,6203],{"class":5596},[5429,9233,5600],{"class":5590},[5429,9235,9236],{"class":5586},"User\n",[5429,9238,9239],{"class":5431,"line":6118},[5429,9240,7237],{"class":5590},[5429,9242,9243],{"class":5431,"line":6144},[5429,9244,9245],{"class":5435},"    \u002F\u002F Користувач може створити документ лише зі своїм рівнем класифікації або вище\n",[5429,9247,9248],{"class":5431,"line":6167},[5429,9249,9250],{"class":5435},"    \u002F\u002F (No Write Down: не можна писати у менш секретні документи)\n",[5429,9252,9253,9255,9257,9259,9261,9263,9265,9267,9269,9271],{"class":5431,"line":6191},[5429,9254,6083],{"class":5579},[5429,9256,5260],{"class":5590},[5429,9258,9214],{"class":5596},[5429,9260,5209],{"class":5590},[5429,9262,8732],{"class":5596},[5429,9264,8725],{"class":5590},[5429,9266,6203],{"class":5596},[5429,9268,5209],{"class":5590},[5429,9270,8722],{"class":5596},[5429,9272,6092],{"class":5590},[5429,9274,9275,9277,9279,9281],{"class":5431,"line":6196},[5429,9276,6217],{"class":5579},[5429,9278,6220],{"class":5469},[5429,9280,6223],{"class":5442},[5429,9282,5928],{"class":5590},[5429,9284,9285],{"class":5431,"line":6214},[5429,9286,9287],{"class":5446},"        'You cannot create documents with classification lower than your clearance level'\n",[5429,9289,9290],{"class":5431,"line":6234},[5429,9291,6544],{"class":5590},[5429,9293,9294],{"class":5431,"line":6239},[5429,9295,6110],{"class":5590},[5429,9297,9298],{"class":5431,"line":6244},[5429,9299,5454],{"emptyLinePlaceholder":5453},[5429,9301,9302],{"class":5431,"line":6276},[5429,9303,9304],{"class":5435},"    \u002F\u002F Користувач не може створити документ з класифікацією вище за свій допуск\n",[5429,9306,9307,9309,9311,9313,9315,9317,9319,9321,9323,9325],{"class":5431,"line":6281},[5429,9308,6083],{"class":5579},[5429,9310,5260],{"class":5590},[5429,9312,9214],{"class":5596},[5429,9314,5209],{"class":5590},[5429,9316,8732],{"class":5596},[5429,9318,8851],{"class":5590},[5429,9320,6203],{"class":5596},[5429,9322,5209],{"class":5590},[5429,9324,8722],{"class":5596},[5429,9326,6092],{"class":5590},[5429,9328,9329,9331,9333,9335],{"class":5431,"line":6293},[5429,9330,6217],{"class":5579},[5429,9332,6220],{"class":5469},[5429,9334,6223],{"class":5442},[5429,9336,5928],{"class":5590},[5429,9338,9339],{"class":5431,"line":6306},[5429,9340,9341],{"class":5446},"        'You cannot create documents with classification higher than your clearance level'\n",[5429,9343,9344],{"class":5431,"line":6311},[5429,9345,6544],{"class":5590},[5429,9347,9348],{"class":5431,"line":6316},[5429,9349,6110],{"class":5590},[5429,9351,9352],{"class":5431,"line":6322},[5429,9353,5454],{"emptyLinePlaceholder":5453},[5429,9355,9356,9358,9360,9362,9364,9366,9369],{"class":5431,"line":6348},[5429,9357,6560],{"class":5579},[5429,9359,6257],{"class":5469},[5429,9361,5209],{"class":5590},[5429,9363,6262],{"class":5596},[5429,9365,5209],{"class":5590},[5429,9367,9368],{"class":5442},"create",[5429,9370,9371],{"class":5590},"({\n",[5429,9373,9374,9377,9379],{"class":5431,"line":6357},[5429,9375,9376],{"class":5590},"      ...",[5429,9378,9214],{"class":5596},[5429,9380,5943],{"class":5590},[5429,9382,9383,9386,9388,9390,9392],{"class":5431,"line":6362},[5429,9384,9385],{"class":5596},"      createdBy:",[5429,9387,6149],{"class":5596},[5429,9389,5209],{"class":5590},[5429,9391,6343],{"class":5596},[5429,9393,5943],{"class":5590},[5429,9395,9396,9399,9402,9404,9406],{"class":5431,"line":6367},[5429,9397,9398],{"class":5596},"      classification:",[5429,9400,9401],{"class":5596}," createDto",[5429,9403,5209],{"class":5590},[5429,9405,8732],{"class":5596},[5429,9407,5943],{"class":5590},[5429,9409,9410],{"class":5431,"line":6373},[5429,9411,9412],{"class":5590},"    });\n",[5429,9414,9415],{"class":5431,"line":6420},[5429,9416,6570],{"class":5590},[5429,9418,9419],{"class":5431,"line":6425},[5429,9420,5683],{"class":5590},[5317,9422,9424],{"id":9423},"переваги-та-недоліки-mac","Переваги та недоліки MAC",[5089,9426,9427],{},[5099,9428,7491],{},[5093,9430,9431,9437,9443,9449],{},[5096,9432,9433,9436],{},[5099,9434,9435],{},"Гарантована відсутність витоків інформації:"," формальна модель запобігає поширенню секретних даних через канали з нижчою класифікацією.",[5096,9438,9439,9442],{},[5099,9440,9441],{},"Централізоване управління безпекою:"," адміністратор має повний контроль над політикою безпеки, користувачі не можуть обійти правила.",[5096,9444,9445,9448],{},[5099,9446,9447],{},"Підходить для високо-регульованих середовищ:"," військові системи, державні установи, фінансові регулятори, медичні системи з HIPAA-вимогами.",[5096,9450,9451,9454],{},[5099,9452,9453],{},"Формальна перевірка:"," можливість математичного доказу властивостей безпеки (наприклад, відсутності потоків інформації між рівнями).",[5089,9456,9457],{},[5099,9458,7522],{},[5093,9460,9461,9473,9479,9485],{},[5096,9462,9463,9466,9467,9469,9470,9472],{},[5099,9464,9465],{},"Негнучкість:"," модель не підтримує контекстних рішень — якщо користувач має рівень ",[5231,9468,7760],{},", він не може прочитати документ ",[5231,9471,7763],{},", навіть якщо це критично для виконання його роботи у конкретній ситуації.",[5096,9474,9475,9478],{},[5099,9476,9477],{},"Висока складність адміністрування:"," призначення та зміна рівнів допуску вимагає залучення адміністраторів безпеки, що створює бюрократичні затримки.",[5096,9480,9481,9484],{},[5099,9482,9483],{},"Обмежена колаборація:"," користувачі з різними рівнями допуску не можуть спільно працювати над документами, що ускладнює міжвідомчу співпрацю.",[5096,9486,9487,9490],{},[5099,9488,9489],{},"Надмірна жорсткість для комерційних систем:"," більшість бізнес-застосунків не потребують такого рівня формалізму, що робить MAC непрактичним надто складним рішенням.",[9492,9493,9494,9495,9497,9498,9500,9501,9504,9505,9508,9509,9512],"caution",{},"MAC модель захищає ",[5099,9496,7883],{}," (запобігання витокам вгору), але ",[5099,9499,7887],{}," (запобігання зміні даних зловмисниками з нижчим рівнем). Для захисту цілісності існує модель Біба (",[5194,9502,9503],{},"Biba Model","), що працює протилежним чином: дозволяє читання вниз (",[5194,9506,9507],{},"No Read Down","), але забороняє запис вгору (",[5194,9510,9511],{},"No Write Up","). Системи, що потребують обох властивостей, комбінують обидві моделі.",[5317,9514,9516],{"id":9515},"типові-сценарії-використання-mac","Типові сценарії використання MAC",[5089,9518,9519],{},[5099,9520,9521],{},"Військові та урядові системи:",[5093,9523,9524,9527],{},[5096,9525,9526],{},"Системи управління державною таємницею (СУД) у Міністерствах оборони та безпеки.",[5096,9528,9529],{},"Обробка класифікованих документів у NATO, ЄС, національних спецслужбах.",[5089,9531,9532],{},[5099,9533,9534],{},"Медичні системи з жорсткими вимогами:",[5093,9536,9537],{},[5096,9538,9539],{},"HIPAA-сумісні системи обробки медичних записів, де рівні доступу визначаються централізованою політикою.",[5089,9541,9542],{},[5099,9543,9544],{},"Фінансові регулятори:",[5093,9546,9547],{},[5096,9548,9549,9550,5234,9553,5234,9556,5234,9558,5209],{},"Системи центральних банків, де документи мають рівні ",[5231,9551,9552],{},"Public",[5231,9554,9555],{},"Internal",[5231,9557,7757],{},[5231,9559,9560],{},"Restricted",[5089,9562,9563],{},[5099,9564,9565],{},"Операційні системи:",[5093,9567,9568,9575],{},[5096,9569,9570,9571,9574],{},"SELinux (",[5194,9572,9573],{},"Security-Enhanced Linux",") — реалізація MAC на рівні ядра Linux.",[5096,9576,9577],{},"Solaris Trusted Extensions, FreeBSD MAC Framework.",[5125,9579],{},[5084,9581,9583],{"id":9582},"rbac-рольовий-контроль-доступу","RBAC: Рольовий контроль доступу",[5089,9585,9586,9589,9590,5260,9592,9594,9595,9597,9598,5234,9600,5234,9602,5234,9604,9607],{},[5099,9587,9588],{},"Role-Based Access Control (RBAC)"," — це модель, у якій права доступу надаються не безпосередньо користувачам, а через проміжний шар ",[5099,9591,5259],{},[5194,9593,5263],{},"). Роль — це іменована сукупність дозволів (",[5194,9596,6387],{},"), що відповідає певній функції у організації (наприклад, ",[5231,9599,5283],{},[5231,9601,7591],{},[5231,9603,7587],{},[5231,9605,9606],{},"billing_manager","). Користувач отримує одну або кілька ролей, і автоматично успадковує всі дозволи, пов'язані з цими ролями.",[5317,9609,9611],{"id":9610},"базові-принципи-rbac","Базові принципи RBAC",[5089,9613,9614],{},[5099,9615,5325],{},[5093,9617,9618,9626,9639,9651],{},[5096,9619,9620,9623,9624,5209],{},[5099,9621,9622],{},"Розділення відповідальностей:"," замість призначення дозволів кожному користувачеві індивідуально, адміністратор визначає ролі один раз та призначає їх користувачам. Якщо потрібно змінити права для всіх редакторів, достатньо змінити дозволи ролі ",[5231,9625,7591],{},[5096,9627,9628,9631,9632,7849,9635,9638],{},[5099,9629,9630],{},"Спрощення адміністрування:"," коли новий співробітник приєднується до команди, йому призначають роль ",[5231,9633,9634],{},"developer",[5231,9636,9637],{},"qa_engineer",", і він автоматично отримує всі необхідні дозволи.",[5096,9640,9641,9644,9645,9647,9648,9650],{},[5099,9642,9643],{},"Ієрархія ролей (RBAC1):"," ролі можуть наслідувати дозволи інших ролей. Наприклад, роль ",[5231,9646,5283],{}," може успадковувати всі дозволи ролі ",[5231,9649,7591],{},", додаючи власні адміністративні права.",[5096,9652,9653,9656,9657,9660,9661,9664,9665,9668],{},[5099,9654,9655],{},"Обмеження (Constraints):"," можливість визначення правил взаємовиключності ролей (",[5194,9658,9659],{},"Separation of Duty",", SoD). Наприклад, один користувач не може одночасно мати ролі ",[5231,9662,9663],{},"accountant"," (створює рахунки) та ",[5231,9666,9667],{},"approver"," (затверджує платежі), щоб запобігти шахрайству.",[5317,9670,9672],{"id":9671},"стандарт-nist-rbac","Стандарт NIST RBAC",[5089,9674,9675,9676,9679],{},"Національний інститут стандартів та технологій США (",[5194,9677,9678],{},"NIST",") визначив чотири рівні RBAC моделі:",[5089,9681,9682,9685],{},[5099,9683,9684],{},"RBAC0 (Core RBAC)"," — базова модель:",[5093,9687,9688,9698,9704],{},[5096,9689,9690,9691,9694,9695,5242],{},"Користувачі (",[5194,9692,9693],{},"Users",") отримують ролі (",[5194,9696,9697],{},"Roles",[5096,9699,9700,9701,5242],{},"Ролі мають дозволи (",[5194,9702,9703],{},"Permissions",[5096,9705,9706,9707,9710,9711,5242],{},"Дозволи визначають операції (",[5194,9708,9709],{},"Operations",") над об'єктами (",[5194,9712,9713],{},"Objects",[5089,9715,9716,9719],{},[5099,9717,9718],{},"RBAC1 (Hierarchical RBAC)"," — додає ієрархію ролей:",[5093,9721,9722,9731],{},[5096,9723,9724,9725,9728,9729,5209],{},"Роль ",[5231,9726,9727],{},"senior_developer"," може успадковувати дозволи ролі ",[5231,9730,9634],{},[5096,9732,9724,9733,9735],{},[5231,9734,5283],{}," успадковує дозволи всіх інших ролей.",[5089,9737,9738,9741],{},[5099,9739,9740],{},"RBAC2 (Constrained RBAC)"," — додає обмеження:",[5093,9743,9744,9750,9757],{},[5096,9745,9746,9747,5242],{},"Взаємовиключність ролей (",[5194,9748,9749],{},"Mutually Exclusive Roles",[5096,9751,9752,9753,9756],{},"Кардинальність ролей (",[5194,9754,9755],{},"Cardinality",") — обмеження кількості користувачів з певною роллю.",[5096,9758,9759,9760,9763],{},"Передумови призначення ролей (",[5194,9761,9762],{},"Prerequisite Roles",") — для отримання ролі A користувач повинен спочатку мати роль B.",[5089,9765,9766,9769],{},[5099,9767,9768],{},"RBAC3 (Symmetric RBAC)"," — комбінує RBAC1 та RBAC2.",[5317,9771,9773],{"id":9772},"візуалізація-rbac-моделі","Візуалізація RBAC моделі",[7894,9775,9776],{},[5420,9777,9779],{"className":7898,"code":9778,"language":7894,"meta":5425,"style":5425},"graph LR\n    U1[User: Alice]\n    U2[User: Bob]\n    U3[User: Charlie]\n    \n    R1[Role: Admin]\n    R2[Role: Editor]\n    R3[Role: Viewer]\n    \n    P1[Permission:\u003Cbr\u002F>create:posts]\n    P2[Permission:\u003Cbr\u002F>edit:posts]\n    P3[Permission:\u003Cbr\u002F>delete:posts]\n    P4[Permission:\u003Cbr\u002F>read:posts]\n    P5[Permission:\u003Cbr\u002F>manage:users]\n    \n    U1 -->|призначена| R1\n    U2 -->|призначена| R2\n    U3 -->|призначена| R3\n    \n    R1 -.->|наслідує| R2\n    R2 -.->|наслідує| R3\n    \n    R1 -->|має| P5\n    R1 -->|має| P3\n    R2 -->|має| P1\n    R2 -->|має| P2\n    R3 -->|має| P4\n    \n    style U1 fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n    style U2 fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n    style U3 fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n    style R1 fill:#ef4444,stroke:#b91c1c,color:#ffffff\n    style R2 fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n    style R3 fill:#10b981,stroke:#047857,color:#ffffff\n",[5231,9780,9781,9786,9791,9796,9801,9805,9810,9815,9820,9824,9829,9834,9839,9844,9849,9853,9858,9863,9868,9872,9877,9882,9886,9891,9896,9901,9906,9911,9915,9920,9925,9930,9935,9940],{"__ignoreMap":5425},[5429,9782,9783],{"class":5431,"line":5432},[5429,9784,9785],{},"graph LR\n",[5429,9787,9788],{"class":5431,"line":5439},[5429,9789,9790],{},"    U1[User: Alice]\n",[5429,9792,9793],{"class":5431,"line":5450},[5429,9794,9795],{},"    U2[User: Bob]\n",[5429,9797,9798],{"class":5431,"line":5457},[5429,9799,9800],{},"    U3[User: Charlie]\n",[5429,9802,9803],{"class":5431,"line":5463},[5429,9804,7941],{},[5429,9806,9807],{"class":5431,"line":5475},[5429,9808,9809],{},"    R1[Role: Admin]\n",[5429,9811,9812],{"class":5431,"line":5481},[5429,9813,9814],{},"    R2[Role: Editor]\n",[5429,9816,9817],{"class":5431,"line":5487},[5429,9818,9819],{},"    R3[Role: Viewer]\n",[5429,9821,9822],{"class":5431,"line":5493},[5429,9823,7941],{},[5429,9825,9826],{"class":5431,"line":5499},[5429,9827,9828],{},"    P1[Permission:\u003Cbr\u002F>create:posts]\n",[5429,9830,9831],{"class":5431,"line":5505},[5429,9832,9833],{},"    P2[Permission:\u003Cbr\u002F>edit:posts]\n",[5429,9835,9836],{"class":5431,"line":5510},[5429,9837,9838],{},"    P3[Permission:\u003Cbr\u002F>delete:posts]\n",[5429,9840,9841],{"class":5431,"line":5516},[5429,9842,9843],{},"    P4[Permission:\u003Cbr\u002F>read:posts]\n",[5429,9845,9846],{"class":5431,"line":5527},[5429,9847,9848],{},"    P5[Permission:\u003Cbr\u002F>manage:users]\n",[5429,9850,9851],{"class":5431,"line":5532},[5429,9852,7941],{},[5429,9854,9855],{"class":5431,"line":5538},[5429,9856,9857],{},"    U1 -->|призначена| R1\n",[5429,9859,9860],{"class":5431,"line":5547},[5429,9861,9862],{},"    U2 -->|призначена| R2\n",[5429,9864,9865],{"class":5431,"line":5748},[5429,9866,9867],{},"    U3 -->|призначена| R3\n",[5429,9869,9870],{"class":5431,"line":5760},[5429,9871,7941],{},[5429,9873,9874],{"class":5431,"line":5772},[5429,9875,9876],{},"    R1 -.->|наслідує| R2\n",[5429,9878,9879],{"class":5431,"line":5787},[5429,9880,9881],{},"    R2 -.->|наслідує| R3\n",[5429,9883,9884],{"class":5431,"line":5799},[5429,9885,7941],{},[5429,9887,9888],{"class":5431,"line":6113},[5429,9889,9890],{},"    R1 -->|має| P5\n",[5429,9892,9893],{"class":5431,"line":6118},[5429,9894,9895],{},"    R1 -->|має| P3\n",[5429,9897,9898],{"class":5431,"line":6144},[5429,9899,9900],{},"    R2 -->|має| P1\n",[5429,9902,9903],{"class":5431,"line":6167},[5429,9904,9905],{},"    R2 -->|має| P2\n",[5429,9907,9908],{"class":5431,"line":6191},[5429,9909,9910],{},"    R3 -->|має| P4\n",[5429,9912,9913],{"class":5431,"line":6196},[5429,9914,7941],{},[5429,9916,9917],{"class":5431,"line":6214},[5429,9918,9919],{},"    style U1 fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n",[5429,9921,9922],{"class":5431,"line":6234},[5429,9923,9924],{},"    style U2 fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n",[5429,9926,9927],{"class":5431,"line":6239},[5429,9928,9929],{},"    style U3 fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n",[5429,9931,9932],{"class":5431,"line":6244},[5429,9933,9934],{},"    style R1 fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[5429,9936,9937],{"class":5431,"line":6276},[5429,9938,9939],{},"    style R2 fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n",[5429,9941,9942],{"class":5431,"line":6281},[5429,9943,9944],{},"    style R3 fill:#10b981,stroke:#047857,color:#ffffff\n",[5089,9946,9947],{},[5099,9948,9949],{},"Пояснення діаграми:",[5093,9951,9952,9975,9994],{},[5096,9953,9954,9957,9958,9961,9962,7619,9965,9968,9969,5234,9972,5242],{},[5099,9955,9956],{},"Alice"," має роль ",[5231,9959,9960],{},"Admin",", що наслідує дозволи ",[5231,9963,9964],{},"Editor",[5231,9966,9967],{},"Viewer",", плюс додає власні адміністративні дозволи (",[5231,9970,9971],{},"manage:users",[5231,9973,9974],{},"delete:posts",[5096,9976,9977,9957,9980,9961,9982,5260,9984,9987,9988,5234,9991,5242],{},[5099,9978,9979],{},"Bob",[5231,9981,9964],{},[5231,9983,9967],{},[5231,9985,9986],{},"read:posts",") та додає можливість створення та редагування (",[5231,9989,9990],{},"create:posts",[5231,9992,9993],{},"edit:posts",[5096,9995,9996,9957,9999,10001,10002,5242],{},[5099,9997,9998],{},"Charlie",[5231,10000,9967],{},", що дозволяє лише перегляд (",[5231,10003,9986],{},[5317,10005,10007],{"id":10006},"реалізація-rbac-у-nestjs-повноцінна-система","Реалізація RBAC у NestJS (повноцінна система)",[5089,10009,10010],{},[5099,10011,5562],{},[5420,10013,10015],{"className":5565,"code":10014,"language":5567,"meta":5425,"style":5425},"\u002F\u002F domain\u002Frole.entity.ts\nexport class Role {\n  id: string;\n  name: string; \u002F\u002F 'admin', 'editor', 'viewer'\n  description: string;\n  permissions: Permission[];\n  createdAt: Date;\n}\n\n\u002F\u002F domain\u002Fpermission.entity.ts\nexport class Permission {\n  id: string;\n  resource: string; \u002F\u002F 'posts', 'users', 'comments'\n  action: string;   \u002F\u002F 'create', 'read', 'update', 'delete'\n  \n  \u002F\u002F Зручний геттер для формування рядка дозволу\n  get fullPermission(): string {\n    return `${this.action}:${this.resource}`;\n  }\n}\n\n\u002F\u002F domain\u002Fuser.entity.ts\nexport class User {\n  id: string;\n  email: string;\n  roles: Role[]; \u002F\u002F Користувач може мати кілька ролей\n  createdAt: Date;\n}\n",[5231,10016,10017,10022,10033,10043,10057,10068,10079,10089,10093,10097,10102,10113,10123,10137,10152,10156,10161,10176,10212,10216,10220,10224,10229,10239,10249,10259,10275,10285],{"__ignoreMap":5425},[5429,10018,10019],{"class":5431,"line":5432},[5429,10020,10021],{"class":5435},"\u002F\u002F domain\u002Frole.entity.ts\n",[5429,10023,10024,10026,10028,10031],{"class":5431,"line":5439},[5429,10025,5580],{"class":5579},[5429,10027,5583],{"class":5469},[5429,10029,10030],{"class":5586}," Role",[5429,10032,5591],{"class":5590},[5429,10034,10035,10037,10039,10041],{"class":5431,"line":5450},[5429,10036,5597],{"class":5596},[5429,10038,5600],{"class":5590},[5429,10040,5603],{"class":5586},[5429,10042,5606],{"class":5590},[5429,10044,10045,10048,10050,10052,10054],{"class":5431,"line":5457},[5429,10046,10047],{"class":5596},"  name",[5429,10049,5600],{"class":5590},[5429,10051,5603],{"class":5586},[5429,10053,5640],{"class":5590},[5429,10055,10056],{"class":5435},"\u002F\u002F 'admin', 'editor', 'viewer'\n",[5429,10058,10059,10062,10064,10066],{"class":5431,"line":5463},[5429,10060,10061],{"class":5596},"  description",[5429,10063,5600],{"class":5590},[5429,10065,5603],{"class":5586},[5429,10067,5606],{"class":5590},[5429,10069,10070,10072,10074,10077],{"class":5431,"line":5475},[5429,10071,5670],{"class":5596},[5429,10073,5600],{"class":5590},[5429,10075,10076],{"class":5586},"Permission",[5429,10078,5678],{"class":5590},[5429,10080,10081,10083,10085,10087],{"class":5431,"line":5481},[5429,10082,5648],{"class":5596},[5429,10084,5600],{"class":5590},[5429,10086,5653],{"class":5586},[5429,10088,5606],{"class":5590},[5429,10090,10091],{"class":5431,"line":5487},[5429,10092,5683],{"class":5590},[5429,10094,10095],{"class":5431,"line":5493},[5429,10096,5454],{"emptyLinePlaceholder":5453},[5429,10098,10099],{"class":5431,"line":5499},[5429,10100,10101],{"class":5435},"\u002F\u002F domain\u002Fpermission.entity.ts\n",[5429,10103,10104,10106,10108,10111],{"class":5431,"line":5505},[5429,10105,5580],{"class":5579},[5429,10107,5583],{"class":5469},[5429,10109,10110],{"class":5586}," Permission",[5429,10112,5591],{"class":5590},[5429,10114,10115,10117,10119,10121],{"class":5431,"line":5510},[5429,10116,5597],{"class":5596},[5429,10118,5600],{"class":5590},[5429,10120,5603],{"class":5586},[5429,10122,5606],{"class":5590},[5429,10124,10125,10128,10130,10132,10134],{"class":5431,"line":5516},[5429,10126,10127],{"class":5596},"  resource",[5429,10129,5600],{"class":5590},[5429,10131,5603],{"class":5586},[5429,10133,5640],{"class":5590},[5429,10135,10136],{"class":5435},"\u002F\u002F 'posts', 'users', 'comments'\n",[5429,10138,10139,10142,10144,10146,10149],{"class":5431,"line":5527},[5429,10140,10141],{"class":5596},"  action",[5429,10143,5600],{"class":5590},[5429,10145,5603],{"class":5586},[5429,10147,10148],{"class":5590},";   ",[5429,10150,10151],{"class":5435},"\u002F\u002F 'create', 'read', 'update', 'delete'\n",[5429,10153,10154],{"class":5431,"line":5532},[5429,10155,5660],{"class":5590},[5429,10157,10158],{"class":5431,"line":5538},[5429,10159,10160],{"class":5435},"  \u002F\u002F Зручний геттер для формування рядка дозволу\n",[5429,10162,10163,10166,10169,10172,10174],{"class":5431,"line":5547},[5429,10164,10165],{"class":5469},"  get",[5429,10167,10168],{"class":5442}," fullPermission",[5429,10170,10171],{"class":5590},"(): ",[5429,10173,5603],{"class":5586},[5429,10175,5591],{"class":5590},[5429,10177,10178,10180,10183,10185,10187,10189,10192,10194,10196,10198,10200,10202,10205,10207,10210],{"class":5431,"line":5748},[5429,10179,6560],{"class":5579},[5429,10181,10182],{"class":5446}," `",[5429,10184,6530],{"class":5469},[5429,10186,6016],{"class":5469},[5429,10188,5209],{"class":8757},[5429,10190,10191],{"class":5596},"action",[5429,10193,6535],{"class":5469},[5429,10195,5418],{"class":5446},[5429,10197,6530],{"class":5469},[5429,10199,6016],{"class":5469},[5429,10201,5209],{"class":8757},[5429,10203,10204],{"class":5596},"resource",[5429,10206,6535],{"class":5469},[5429,10208,10209],{"class":5446},"`",[5429,10211,5606],{"class":5590},[5429,10213,10214],{"class":5431,"line":5760},[5429,10215,6570],{"class":5590},[5429,10217,10218],{"class":5431,"line":5772},[5429,10219,5683],{"class":5590},[5429,10221,10222],{"class":5431,"line":5787},[5429,10223,5454],{"emptyLinePlaceholder":5453},[5429,10225,10226],{"class":5431,"line":5799},[5429,10227,10228],{"class":5435},"\u002F\u002F domain\u002Fuser.entity.ts\n",[5429,10230,10231,10233,10235,10237],{"class":5431,"line":6113},[5429,10232,5580],{"class":5579},[5429,10234,5583],{"class":5469},[5429,10236,8225],{"class":5586},[5429,10238,5591],{"class":5590},[5429,10240,10241,10243,10245,10247],{"class":5431,"line":6118},[5429,10242,5597],{"class":5596},[5429,10244,5600],{"class":5590},[5429,10246,5603],{"class":5586},[5429,10248,5606],{"class":5590},[5429,10250,10251,10253,10255,10257],{"class":5431,"line":6144},[5429,10252,8242],{"class":5596},[5429,10254,5600],{"class":5590},[5429,10256,5603],{"class":5586},[5429,10258,5606],{"class":5590},[5429,10260,10261,10264,10266,10269,10272],{"class":5431,"line":6167},[5429,10262,10263],{"class":5596},"  roles",[5429,10265,5600],{"class":5590},[5429,10267,10268],{"class":5586},"Role",[5429,10270,10271],{"class":5590},"[]; ",[5429,10273,10274],{"class":5435},"\u002F\u002F Користувач може мати кілька ролей\n",[5429,10276,10277,10279,10281,10283],{"class":5431,"line":6191},[5429,10278,5648],{"class":5596},[5429,10280,5600],{"class":5590},[5429,10282,5653],{"class":5586},[5429,10284,5606],{"class":5590},[5429,10286,10287],{"class":5431,"line":6196},[5429,10288,5683],{"class":5590},[5089,10290,10291],{},[5099,10292,10293],{},"Сервіс для перевірки дозволів:",[5420,10295,10297],{"className":5565,"code":10296,"language":5567,"meta":5425,"style":5425},"\u002F\u002F services\u002Fauthorization.service.ts\nimport { Injectable } from '@nestjs\u002Fcommon';\nimport { UserService } from '.\u002Fuser.service';\n\n@Injectable()\nexport class AuthorizationService {\n  constructor(private userService: UserService) {}\n\n  \u002F**\n   * Перевіряє, чи має користувач необхідний дозвіл через свої ролі\n   *\u002F\n  async userHasPermission(userId: string, requiredPermission: string): Promise\u003Cboolean> {\n    const user = await this.userService.findByIdWithRoles(userId);\n\n    if (!user || !user.roles) {\n      return false;\n    }\n\n    \u002F\u002F Збираємо всі дозволи з усіх ролей користувача\n    const allPermissions = user.roles.flatMap(role => \n      role.permissions.map(p => p.fullPermission)\n    );\n\n    return allPermissions.includes(requiredPermission);\n  }\n\n  \u002F**\n   * Перевіряє, чи має користувач хоча б один із вказаних дозволів\n   *\u002F\n  async userHasAnyPermission(userId: string, permissions: string[]): Promise\u003Cboolean> {\n    const checks = await Promise.all(\n      permissions.map(p => this.userHasPermission(userId, p))\n    );\n\n    return checks.some(result => result === true);\n  }\n\n  \u002F**\n   * Перевіряє, чи має користувач всі вказані дозволи\n   *\u002F\n  async userHasAllPermissions(userId: string, permissions: string[]): Promise\u003Cboolean> {\n    const checks = await Promise.all(\n      permissions.map(p => this.userHasPermission(userId, p))\n    );\n\n    return checks.every(result => result === true);\n  }\n}\n",[5231,10298,10299,10304,10320,10338,10342,10350,10361,10378,10382,10387,10392,10397,10431,10460,10464,10482,10490,10494,10498,10503,10533,10562,10566,10570,10587,10591,10595,10599,10604,10608,10642,10663,10696,10700,10704,10732,10736,10740,10744,10749,10753,10786,10804,10834,10838,10842,10867,10871],{"__ignoreMap":5425},[5429,10300,10301],{"class":5431,"line":5432},[5429,10302,10303],{"class":5435},"\u002F\u002F services\u002Fauthorization.service.ts\n",[5429,10305,10306,10308,10310,10312,10314,10316,10318],{"class":5431,"line":5439},[5429,10307,5821],{"class":5579},[5429,10309,5824],{"class":5590},[5429,10311,5827],{"class":5596},[5429,10313,5845],{"class":5590},[5429,10315,5848],{"class":5579},[5429,10317,5851],{"class":5446},[5429,10319,5606],{"class":5590},[5429,10321,10322,10324,10326,10329,10331,10333,10336],{"class":5431,"line":5450},[5429,10323,5821],{"class":5579},[5429,10325,5824],{"class":5590},[5429,10327,10328],{"class":5596},"UserService",[5429,10330,5845],{"class":5590},[5429,10332,5848],{"class":5579},[5429,10334,10335],{"class":5446}," '.\u002Fuser.service'",[5429,10337,5606],{"class":5590},[5429,10339,10340],{"class":5431,"line":5457},[5429,10341,5454],{"emptyLinePlaceholder":5453},[5429,10343,10344,10346,10348],{"class":5431,"line":5463},[5429,10345,5898],{"class":5590},[5429,10347,5827],{"class":5442},[5429,10349,5903],{"class":5590},[5429,10351,10352,10354,10356,10359],{"class":5431,"line":5475},[5429,10353,5580],{"class":5579},[5429,10355,5583],{"class":5469},[5429,10357,10358],{"class":5586}," AuthorizationService",[5429,10360,5591],{"class":5590},[5429,10362,10363,10365,10367,10369,10372,10374,10376],{"class":5431,"line":5481},[5429,10364,5925],{"class":5469},[5429,10366,5975],{"class":5590},[5429,10368,7057],{"class":5469},[5429,10370,10371],{"class":5596}," userService",[5429,10373,5600],{"class":5590},[5429,10375,10328],{"class":5586},[5429,10377,7066],{"class":5590},[5429,10379,10380],{"class":5431,"line":5487},[5429,10381,5454],{"emptyLinePlaceholder":5453},[5429,10383,10384],{"class":5431,"line":5493},[5429,10385,10386],{"class":5435},"  \u002F**\n",[5429,10388,10389],{"class":5431,"line":5499},[5429,10390,10391],{"class":5435},"   * Перевіряє, чи має користувач необхідний дозвіл через свої ролі\n",[5429,10393,10394],{"class":5431,"line":5505},[5429,10395,10396],{"class":5435},"   *\u002F\n",[5429,10398,10399,10401,10404,10406,10408,10410,10412,10414,10417,10419,10421,10423,10425,10427,10429],{"class":5431,"line":5510},[5429,10400,5969],{"class":5469},[5429,10402,10403],{"class":5442}," userHasPermission",[5429,10405,5975],{"class":5590},[5429,10407,6407],{"class":5596},[5429,10409,5600],{"class":5590},[5429,10411,5603],{"class":5586},[5429,10413,5234],{"class":5590},[5429,10415,10416],{"class":5596},"requiredPermission",[5429,10418,5600],{"class":5590},[5429,10420,5603],{"class":5586},[5429,10422,5985],{"class":5590},[5429,10424,5988],{"class":5586},[5429,10426,5991],{"class":5590},[5429,10428,5743],{"class":5586},[5429,10430,5996],{"class":5590},[5429,10432,10433,10435,10438,10440,10442,10444,10446,10449,10451,10454,10456,10458],{"class":5431,"line":5516},[5429,10434,6006],{"class":5469},[5429,10436,10437],{"class":6009}," user",[5429,10439,6013],{"class":5590},[5429,10441,6254],{"class":5579},[5429,10443,6257],{"class":5469},[5429,10445,5209],{"class":5590},[5429,10447,10448],{"class":5596},"userService",[5429,10450,5209],{"class":5590},[5429,10452,10453],{"class":5442},"findByIdWithRoles",[5429,10455,5975],{"class":5590},[5429,10457,6407],{"class":5596},[5429,10459,6231],{"class":5590},[5429,10461,10462],{"class":5431,"line":5527},[5429,10463,5454],{"emptyLinePlaceholder":5453},[5429,10465,10466,10468,10470,10472,10474,10476,10478,10480],{"class":5431,"line":5532},[5429,10467,6083],{"class":5579},[5429,10469,6086],{"class":5590},[5429,10471,6159],{"class":5596},[5429,10473,6206],{"class":5590},[5429,10475,6159],{"class":5596},[5429,10477,5209],{"class":5590},[5429,10479,5263],{"class":5596},[5429,10481,6092],{"class":5590},[5429,10483,10484,10486,10488],{"class":5431,"line":5538},[5429,10485,6097],{"class":5579},[5429,10487,6298],{"class":5469},[5429,10489,5606],{"class":5590},[5429,10491,10492],{"class":5431,"line":5547},[5429,10493,6110],{"class":5590},[5429,10495,10496],{"class":5431,"line":5748},[5429,10497,5454],{"emptyLinePlaceholder":5453},[5429,10499,10500],{"class":5431,"line":5760},[5429,10501,10502],{"class":5435},"    \u002F\u002F Збираємо всі дозволи з усіх ролей користувача\n",[5429,10504,10505,10507,10510,10512,10514,10516,10518,10520,10523,10525,10528,10530],{"class":5431,"line":5772},[5429,10506,6006],{"class":5469},[5429,10508,10509],{"class":6009}," allPermissions",[5429,10511,6013],{"class":5590},[5429,10513,6159],{"class":5596},[5429,10515,5209],{"class":5590},[5429,10517,5263],{"class":5596},[5429,10519,5209],{"class":5590},[5429,10521,10522],{"class":5442},"flatMap",[5429,10524,5975],{"class":5590},[5429,10526,10527],{"class":5596},"role",[5429,10529,6399],{"class":5469},[5429,10531,10532],{"class":5590}," \n",[5429,10534,10535,10538,10540,10542,10544,10547,10549,10551,10553,10555,10557,10560],{"class":5431,"line":5787},[5429,10536,10537],{"class":5596},"      role",[5429,10539,5209],{"class":5590},[5429,10541,6387],{"class":5596},[5429,10543,5209],{"class":5590},[5429,10545,10546],{"class":5442},"map",[5429,10548,5975],{"class":5590},[5429,10550,5089],{"class":5596},[5429,10552,6399],{"class":5469},[5429,10554,6402],{"class":5596},[5429,10556,5209],{"class":5590},[5429,10558,10559],{"class":5596},"fullPermission",[5429,10561,7021],{"class":5590},[5429,10563,10564],{"class":5431,"line":5799},[5429,10565,6074],{"class":5590},[5429,10567,10568],{"class":5431,"line":6113},[5429,10569,5454],{"emptyLinePlaceholder":5453},[5429,10571,10572,10574,10576,10578,10581,10583,10585],{"class":5431,"line":6118},[5429,10573,6560],{"class":5579},[5429,10575,10509],{"class":5596},[5429,10577,5209],{"class":5590},[5429,10579,10580],{"class":5442},"includes",[5429,10582,5975],{"class":5590},[5429,10584,10416],{"class":5596},[5429,10586,6231],{"class":5590},[5429,10588,10589],{"class":5431,"line":6144},[5429,10590,6570],{"class":5590},[5429,10592,10593],{"class":5431,"line":6167},[5429,10594,5454],{"emptyLinePlaceholder":5453},[5429,10596,10597],{"class":5431,"line":6191},[5429,10598,10386],{"class":5435},[5429,10600,10601],{"class":5431,"line":6196},[5429,10602,10603],{"class":5435},"   * Перевіряє, чи має користувач хоча б один із вказаних дозволів\n",[5429,10605,10606],{"class":5431,"line":6214},[5429,10607,10396],{"class":5435},[5429,10609,10610,10612,10615,10617,10619,10621,10623,10625,10627,10629,10631,10634,10636,10638,10640],{"class":5431,"line":6234},[5429,10611,5969],{"class":5469},[5429,10613,10614],{"class":5442}," userHasAnyPermission",[5429,10616,5975],{"class":5590},[5429,10618,6407],{"class":5596},[5429,10620,5600],{"class":5590},[5429,10622,5603],{"class":5586},[5429,10624,5234],{"class":5590},[5429,10626,6387],{"class":5596},[5429,10628,5600],{"class":5590},[5429,10630,5603],{"class":5586},[5429,10632,10633],{"class":5590},"[]): ",[5429,10635,5988],{"class":5586},[5429,10637,5991],{"class":5590},[5429,10639,5743],{"class":5586},[5429,10641,5996],{"class":5590},[5429,10643,10644,10646,10649,10651,10653,10656,10658,10661],{"class":5431,"line":6239},[5429,10645,6006],{"class":5469},[5429,10647,10648],{"class":6009}," checks",[5429,10650,6013],{"class":5590},[5429,10652,6254],{"class":5579},[5429,10654,10655],{"class":5586}," Promise",[5429,10657,5209],{"class":5590},[5429,10659,10660],{"class":5442},"all",[5429,10662,5928],{"class":5590},[5429,10664,10665,10668,10670,10672,10674,10676,10678,10680,10682,10685,10687,10689,10691,10693],{"class":5431,"line":6244},[5429,10666,10667],{"class":5596},"      permissions",[5429,10669,5209],{"class":5590},[5429,10671,10546],{"class":5442},[5429,10673,5975],{"class":5590},[5429,10675,5089],{"class":5596},[5429,10677,6399],{"class":5469},[5429,10679,6257],{"class":5469},[5429,10681,5209],{"class":5590},[5429,10683,10684],{"class":5442},"userHasPermission",[5429,10686,5975],{"class":5590},[5429,10688,6407],{"class":5596},[5429,10690,5234],{"class":5590},[5429,10692,5089],{"class":5596},[5429,10694,10695],{"class":5590},"))\n",[5429,10697,10698],{"class":5431,"line":6276},[5429,10699,6074],{"class":5590},[5429,10701,10702],{"class":5431,"line":6281},[5429,10703,5454],{"emptyLinePlaceholder":5453},[5429,10705,10706,10708,10710,10712,10715,10717,10720,10722,10725,10727,10730],{"class":5431,"line":6293},[5429,10707,6560],{"class":5579},[5429,10709,10648],{"class":5596},[5429,10711,5209],{"class":5590},[5429,10713,10714],{"class":5442},"some",[5429,10716,5975],{"class":5590},[5429,10718,10719],{"class":5596},"result",[5429,10721,6399],{"class":5469},[5429,10723,10724],{"class":5596}," result",[5429,10726,6336],{"class":5590},[5429,10728,10729],{"class":5469},"true",[5429,10731,6231],{"class":5590},[5429,10733,10734],{"class":5431,"line":6306},[5429,10735,6570],{"class":5590},[5429,10737,10738],{"class":5431,"line":6311},[5429,10739,5454],{"emptyLinePlaceholder":5453},[5429,10741,10742],{"class":5431,"line":6316},[5429,10743,10386],{"class":5435},[5429,10745,10746],{"class":5431,"line":6322},[5429,10747,10748],{"class":5435},"   * Перевіряє, чи має користувач всі вказані дозволи\n",[5429,10750,10751],{"class":5431,"line":6348},[5429,10752,10396],{"class":5435},[5429,10754,10755,10757,10760,10762,10764,10766,10768,10770,10772,10774,10776,10778,10780,10782,10784],{"class":5431,"line":6357},[5429,10756,5969],{"class":5469},[5429,10758,10759],{"class":5442}," userHasAllPermissions",[5429,10761,5975],{"class":5590},[5429,10763,6407],{"class":5596},[5429,10765,5600],{"class":5590},[5429,10767,5603],{"class":5586},[5429,10769,5234],{"class":5590},[5429,10771,6387],{"class":5596},[5429,10773,5600],{"class":5590},[5429,10775,5603],{"class":5586},[5429,10777,10633],{"class":5590},[5429,10779,5988],{"class":5586},[5429,10781,5991],{"class":5590},[5429,10783,5743],{"class":5586},[5429,10785,5996],{"class":5590},[5429,10787,10788,10790,10792,10794,10796,10798,10800,10802],{"class":5431,"line":6362},[5429,10789,6006],{"class":5469},[5429,10791,10648],{"class":6009},[5429,10793,6013],{"class":5590},[5429,10795,6254],{"class":5579},[5429,10797,10655],{"class":5586},[5429,10799,5209],{"class":5590},[5429,10801,10660],{"class":5442},[5429,10803,5928],{"class":5590},[5429,10805,10806,10808,10810,10812,10814,10816,10818,10820,10822,10824,10826,10828,10830,10832],{"class":5431,"line":6367},[5429,10807,10667],{"class":5596},[5429,10809,5209],{"class":5590},[5429,10811,10546],{"class":5442},[5429,10813,5975],{"class":5590},[5429,10815,5089],{"class":5596},[5429,10817,6399],{"class":5469},[5429,10819,6257],{"class":5469},[5429,10821,5209],{"class":5590},[5429,10823,10684],{"class":5442},[5429,10825,5975],{"class":5590},[5429,10827,6407],{"class":5596},[5429,10829,5234],{"class":5590},[5429,10831,5089],{"class":5596},[5429,10833,10695],{"class":5590},[5429,10835,10836],{"class":5431,"line":6373},[5429,10837,6074],{"class":5590},[5429,10839,10840],{"class":5431,"line":6420},[5429,10841,5454],{"emptyLinePlaceholder":5453},[5429,10843,10844,10846,10848,10850,10853,10855,10857,10859,10861,10863,10865],{"class":5431,"line":6425},[5429,10845,6560],{"class":5579},[5429,10847,10648],{"class":5596},[5429,10849,5209],{"class":5590},[5429,10851,10852],{"class":5442},"every",[5429,10854,5975],{"class":5590},[5429,10856,10719],{"class":5596},[5429,10858,6399],{"class":5469},[5429,10860,10724],{"class":5596},[5429,10862,6336],{"class":5590},[5429,10864,10729],{"class":5469},[5429,10866,6231],{"class":5590},[5429,10868,10869],{"class":5431,"line":6437},[5429,10870,6570],{"class":5590},[5429,10872,10873],{"class":5431,"line":6453},[5429,10874,5683],{"class":5590},[5089,10876,10877],{},[5099,10878,10879],{},"Guard для перевірки RBAC дозволів:",[5420,10881,10883],{"className":5565,"code":10882,"language":5567,"meta":5425,"style":5425},"\u002F\u002F guards\u002Frbac-authorization.guard.ts\nimport { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs\u002Fcommon';\nimport { Reflector } from '@nestjs\u002Fcore';\nimport { AuthorizationService } from '..\u002Fservices\u002Fauthorization.service';\n\n@Injectable()\nexport class RbacAuthorizationGuard implements CanActivate {\n  constructor(\n    private reflector: Reflector,\n    private authorizationService: AuthorizationService\n  ) {}\n\n  async canActivate(context: ExecutionContext): Promise\u003Cboolean> {\n    \u002F\u002F Витягуємо необхідні дозволи з метаданих декоратора\n    const requiredPermissions = this.reflector.get\u003Cstring[]>(\n      'permissions',\n      context.getHandler()\n    );\n\n    if (!requiredPermissions || requiredPermissions.length === 0) {\n      return true; \u002F\u002F Якщо дозволи не вказані, пропускаємо перевірку\n    }\n\n    const request = context.switchToHttp().getRequest();\n    const currentUser = request.user;\n\n    if (!currentUser) {\n      throw new ForbiddenException('User not authenticated');\n    }\n\n    \u002F\u002F Перевіряємо, чи має користувач хоча б один із необхідних дозволів\n    const hasPermission = await this.authorizationService.userHasAnyPermission(\n      currentUser.sub,\n      requiredPermissions\n    );\n\n    if (!hasPermission) {\n      throw new ForbiddenException(\n        `Access denied: required permissions are [${requiredPermissions.join(', ')}]`\n      );\n    }\n\n    return true;\n  }\n}\n",[5231,10884,10885,10890,10918,10934,10952,10956,10964,10979,10985,10997,11009,11013,11017,11041,11046,11072,11079,11089,11093,11097,11122,11133,11137,11141,11161,11177,11181,11191,11206,11210,11214,11219,11243,11254,11259,11263,11267,11277,11287,11314,11318,11322,11326,11334,11338],{"__ignoreMap":5425},[5429,10886,10887],{"class":5431,"line":5432},[5429,10888,10889],{"class":5435},"\u002F\u002F guards\u002Frbac-authorization.guard.ts\n",[5429,10891,10892,10894,10896,10898,10900,10902,10904,10906,10908,10910,10912,10914,10916],{"class":5431,"line":5439},[5429,10893,5821],{"class":5579},[5429,10895,5824],{"class":5590},[5429,10897,5827],{"class":5596},[5429,10899,5234],{"class":5590},[5429,10901,5832],{"class":5596},[5429,10903,5234],{"class":5590},[5429,10905,5837],{"class":5596},[5429,10907,5234],{"class":5590},[5429,10909,5842],{"class":5596},[5429,10911,5845],{"class":5590},[5429,10913,5848],{"class":5579},[5429,10915,5851],{"class":5446},[5429,10917,5606],{"class":5590},[5429,10919,10920,10922,10924,10926,10928,10930,10932],{"class":5431,"line":5450},[5429,10921,5821],{"class":5579},[5429,10923,5824],{"class":5590},[5429,10925,5862],{"class":5596},[5429,10927,5845],{"class":5590},[5429,10929,5848],{"class":5579},[5429,10931,5869],{"class":5446},[5429,10933,5606],{"class":5590},[5429,10935,10936,10938,10940,10943,10945,10947,10950],{"class":5431,"line":5457},[5429,10937,5821],{"class":5579},[5429,10939,5824],{"class":5590},[5429,10941,10942],{"class":5596},"AuthorizationService",[5429,10944,5845],{"class":5590},[5429,10946,5848],{"class":5579},[5429,10948,10949],{"class":5446}," '..\u002Fservices\u002Fauthorization.service'",[5429,10951,5606],{"class":5590},[5429,10953,10954],{"class":5431,"line":5463},[5429,10955,5454],{"emptyLinePlaceholder":5453},[5429,10957,10958,10960,10962],{"class":5431,"line":5475},[5429,10959,5898],{"class":5590},[5429,10961,5827],{"class":5442},[5429,10963,5903],{"class":5590},[5429,10965,10966,10968,10970,10973,10975,10977],{"class":5431,"line":5481},[5429,10967,5580],{"class":5579},[5429,10969,5583],{"class":5469},[5429,10971,10972],{"class":5586}," RbacAuthorizationGuard",[5429,10974,5915],{"class":5469},[5429,10976,5918],{"class":5586},[5429,10978,5591],{"class":5590},[5429,10980,10981,10983],{"class":5431,"line":5487},[5429,10982,5925],{"class":5469},[5429,10984,5928],{"class":5590},[5429,10986,10987,10989,10991,10993,10995],{"class":5431,"line":5493},[5429,10988,5933],{"class":5469},[5429,10990,5936],{"class":5596},[5429,10992,5600],{"class":5590},[5429,10994,5862],{"class":5586},[5429,10996,5943],{"class":5590},[5429,10998,10999,11001,11004,11006],{"class":5431,"line":5499},[5429,11000,5933],{"class":5469},[5429,11002,11003],{"class":5596}," authorizationService",[5429,11005,5600],{"class":5590},[5429,11007,11008],{"class":5586},"AuthorizationService\n",[5429,11010,11011],{"class":5431,"line":5505},[5429,11012,5960],{"class":5590},[5429,11014,11015],{"class":5431,"line":5510},[5429,11016,5454],{"emptyLinePlaceholder":5453},[5429,11018,11019,11021,11023,11025,11027,11029,11031,11033,11035,11037,11039],{"class":5431,"line":5516},[5429,11020,5969],{"class":5469},[5429,11022,5972],{"class":5442},[5429,11024,5975],{"class":5590},[5429,11026,5978],{"class":5596},[5429,11028,5600],{"class":5590},[5429,11030,5837],{"class":5586},[5429,11032,5985],{"class":5590},[5429,11034,5988],{"class":5586},[5429,11036,5991],{"class":5590},[5429,11038,5743],{"class":5586},[5429,11040,5996],{"class":5590},[5429,11042,11043],{"class":5431,"line":5527},[5429,11044,11045],{"class":5435},"    \u002F\u002F Витягуємо необхідні дозволи з метаданих декоратора\n",[5429,11047,11048,11050,11053,11055,11057,11059,11061,11063,11065,11067,11069],{"class":5431,"line":5532},[5429,11049,6006],{"class":5469},[5429,11051,11052],{"class":6009}," requiredPermissions",[5429,11054,6013],{"class":5590},[5429,11056,6016],{"class":5469},[5429,11058,5209],{"class":5590},[5429,11060,6021],{"class":5596},[5429,11062,5209],{"class":5590},[5429,11064,6026],{"class":5442},[5429,11066,5991],{"class":5590},[5429,11068,5603],{"class":5586},[5429,11070,11071],{"class":5590},"[]>(\n",[5429,11073,11074,11077],{"class":5431,"line":5538},[5429,11075,11076],{"class":5446},"      'permissions'",[5429,11078,5943],{"class":5590},[5429,11080,11081,11083,11085,11087],{"class":5431,"line":5547},[5429,11082,6062],{"class":5596},[5429,11084,5209],{"class":5590},[5429,11086,6067],{"class":5442},[5429,11088,5903],{"class":5590},[5429,11090,11091],{"class":5431,"line":5748},[5429,11092,6074],{"class":5590},[5429,11094,11095],{"class":5431,"line":5760},[5429,11096,5454],{"emptyLinePlaceholder":5453},[5429,11098,11099,11101,11103,11106,11109,11111,11113,11116,11118,11120],{"class":5431,"line":5772},[5429,11100,6083],{"class":5579},[5429,11102,6086],{"class":5590},[5429,11104,11105],{"class":5596},"requiredPermissions",[5429,11107,11108],{"class":5590}," || ",[5429,11110,11105],{"class":5596},[5429,11112,5209],{"class":5590},[5429,11114,11115],{"class":5596},"length",[5429,11117,6336],{"class":5590},[5429,11119,8075],{"class":5521},[5429,11121,6092],{"class":5590},[5429,11123,11124,11126,11128,11130],{"class":5431,"line":5787},[5429,11125,6097],{"class":5579},[5429,11127,6100],{"class":5469},[5429,11129,5640],{"class":5590},[5429,11131,11132],{"class":5435},"\u002F\u002F Якщо дозволи не вказані, пропускаємо перевірку\n",[5429,11134,11135],{"class":5431,"line":5799},[5429,11136,6110],{"class":5590},[5429,11138,11139],{"class":5431,"line":6113},[5429,11140,5454],{"emptyLinePlaceholder":5453},[5429,11142,11143,11145,11147,11149,11151,11153,11155,11157,11159],{"class":5431,"line":6118},[5429,11144,6006],{"class":5469},[5429,11146,6123],{"class":6009},[5429,11148,6013],{"class":5590},[5429,11150,5978],{"class":5596},[5429,11152,5209],{"class":5590},[5429,11154,6132],{"class":5442},[5429,11156,6135],{"class":5590},[5429,11158,6138],{"class":5442},[5429,11160,6141],{"class":5590},[5429,11162,11163,11165,11167,11169,11171,11173,11175],{"class":5431,"line":6144},[5429,11164,6006],{"class":5469},[5429,11166,6149],{"class":6009},[5429,11168,6013],{"class":5590},[5429,11170,6154],{"class":5596},[5429,11172,5209],{"class":5590},[5429,11174,6159],{"class":5596},[5429,11176,5606],{"class":5590},[5429,11178,11179],{"class":5431,"line":6167},[5429,11180,5454],{"emptyLinePlaceholder":5453},[5429,11182,11183,11185,11187,11189],{"class":5431,"line":6191},[5429,11184,6083],{"class":5579},[5429,11186,6086],{"class":5590},[5429,11188,6203],{"class":5596},[5429,11190,6092],{"class":5590},[5429,11192,11193,11195,11197,11199,11201,11204],{"class":5431,"line":6196},[5429,11194,6217],{"class":5579},[5429,11196,6220],{"class":5469},[5429,11198,6223],{"class":5442},[5429,11200,5975],{"class":5590},[5429,11202,11203],{"class":5446},"'User not authenticated'",[5429,11205,6231],{"class":5590},[5429,11207,11208],{"class":5431,"line":6214},[5429,11209,6110],{"class":5590},[5429,11211,11212],{"class":5431,"line":6234},[5429,11213,5454],{"emptyLinePlaceholder":5453},[5429,11215,11216],{"class":5431,"line":6239},[5429,11217,11218],{"class":5435},"    \u002F\u002F Перевіряємо, чи має користувач хоча б один із необхідних дозволів\n",[5429,11220,11221,11223,11225,11227,11229,11231,11233,11236,11238,11241],{"class":5431,"line":6244},[5429,11222,6006],{"class":5469},[5429,11224,6474],{"class":6009},[5429,11226,6013],{"class":5590},[5429,11228,6254],{"class":5579},[5429,11230,6257],{"class":5469},[5429,11232,5209],{"class":5590},[5429,11234,11235],{"class":5596},"authorizationService",[5429,11237,5209],{"class":5590},[5429,11239,11240],{"class":5442},"userHasAnyPermission",[5429,11242,5928],{"class":5590},[5429,11244,11245,11248,11250,11252],{"class":5431,"line":6276},[5429,11246,11247],{"class":5596},"      currentUser",[5429,11249,5209],{"class":5590},[5429,11251,6343],{"class":5596},[5429,11253,5943],{"class":5590},[5429,11255,11256],{"class":5431,"line":6281},[5429,11257,11258],{"class":5596},"      requiredPermissions\n",[5429,11260,11261],{"class":5431,"line":6293},[5429,11262,6074],{"class":5590},[5429,11264,11265],{"class":5431,"line":6306},[5429,11266,5454],{"emptyLinePlaceholder":5453},[5429,11268,11269,11271,11273,11275],{"class":5431,"line":6311},[5429,11270,6083],{"class":5579},[5429,11272,6086],{"class":5590},[5429,11274,6508],{"class":5596},[5429,11276,6092],{"class":5590},[5429,11278,11279,11281,11283,11285],{"class":5431,"line":6316},[5429,11280,6217],{"class":5579},[5429,11282,6220],{"class":5469},[5429,11284,6223],{"class":5442},[5429,11286,5928],{"class":5590},[5429,11288,11289,11292,11294,11296,11298,11301,11303,11306,11309,11311],{"class":5431,"line":6322},[5429,11290,11291],{"class":5446},"        `Access denied: required permissions are [",[5429,11293,6530],{"class":5469},[5429,11295,11105],{"class":5596},[5429,11297,5209],{"class":8757},[5429,11299,11300],{"class":5442},"join",[5429,11302,5975],{"class":8757},[5429,11304,11305],{"class":5446},"', '",[5429,11307,11308],{"class":8757},")",[5429,11310,6535],{"class":5469},[5429,11312,11313],{"class":5446},"]`\n",[5429,11315,11316],{"class":5431,"line":6348},[5429,11317,6544],{"class":5590},[5429,11319,11320],{"class":5431,"line":6357},[5429,11321,6110],{"class":5590},[5429,11323,11324],{"class":5431,"line":6362},[5429,11325,5454],{"emptyLinePlaceholder":5453},[5429,11327,11328,11330,11332],{"class":5431,"line":6367},[5429,11329,6560],{"class":5579},[5429,11331,6100],{"class":5469},[5429,11333,5606],{"class":5590},[5429,11335,11336],{"class":5431,"line":6373},[5429,11337,6570],{"class":5590},[5429,11339,11340],{"class":5431,"line":6420},[5429,11341,5683],{"class":5590},[5089,11343,11344],{},[5099,11345,11346],{},"Декоратор для вказівки необхідних дозволів:",[5420,11348,11350],{"className":5565,"code":11349,"language":5567,"meta":5425,"style":5425},"\u002F\u002F decorators\u002Frequire-permissions.decorator.ts\nimport { SetMetadata } from '@nestjs\u002Fcommon';\n\n\u002F**\n * Декоратор для вказівки необхідних дозволів у форматі \"action:resource\"\n * Приклад: @RequirePermissions('create:posts', 'edit:posts')\n *\u002F\nexport const RequirePermissions = (...permissions: string[]) =>\n  SetMetadata('permissions', permissions);\n",[5231,11351,11352,11357,11373,11377,11382,11387,11392,11397,11420],{"__ignoreMap":5425},[5429,11353,11354],{"class":5431,"line":5432},[5429,11355,11356],{"class":5435},"\u002F\u002F decorators\u002Frequire-permissions.decorator.ts\n",[5429,11358,11359,11361,11363,11365,11367,11369,11371],{"class":5431,"line":5439},[5429,11360,5821],{"class":5579},[5429,11362,5824],{"class":5590},[5429,11364,6799],{"class":5596},[5429,11366,5845],{"class":5590},[5429,11368,5848],{"class":5579},[5429,11370,5851],{"class":5446},[5429,11372,5606],{"class":5590},[5429,11374,11375],{"class":5431,"line":5450},[5429,11376,5454],{"emptyLinePlaceholder":5453},[5429,11378,11379],{"class":5431,"line":5457},[5429,11380,11381],{"class":5435},"\u002F**\n",[5429,11383,11384],{"class":5431,"line":5463},[5429,11385,11386],{"class":5435}," * Декоратор для вказівки необхідних дозволів у форматі \"action:resource\"\n",[5429,11388,11389],{"class":5431,"line":5475},[5429,11390,11391],{"class":5435}," * Приклад: @RequirePermissions('create:posts', 'edit:posts')\n",[5429,11393,11394],{"class":5431,"line":5481},[5429,11395,11396],{"class":5435}," *\u002F\n",[5429,11398,11399,11401,11403,11406,11409,11411,11413,11415,11418],{"class":5431,"line":5487},[5429,11400,5580],{"class":5579},[5429,11402,6818],{"class":5469},[5429,11404,11405],{"class":5442}," RequirePermissions",[5429,11407,11408],{"class":5590}," = (...",[5429,11410,6387],{"class":5596},[5429,11412,5600],{"class":5590},[5429,11414,5603],{"class":5586},[5429,11416,11417],{"class":5590},"[]) ",[5429,11419,6848],{"class":5469},[5429,11421,11422,11424,11426,11429,11431,11433],{"class":5431,"line":5493},[5429,11423,6853],{"class":5442},[5429,11425,5975],{"class":5590},[5429,11427,11428],{"class":5446},"'permissions'",[5429,11430,5234],{"class":5590},[5429,11432,6387],{"class":5596},[5429,11434,6231],{"class":5590},[5089,11436,11437],{},[5099,11438,11439],{},"Контролер із застосуванням RBAC:",[5420,11441,11443],{"className":5565,"code":11442,"language":5567,"meta":5425,"style":5425},"\u002F\u002F controllers\u002Fposts.controller.ts\nimport { Controller, Get, Post, Put, Delete, Param, Body, UseGuards } from '@nestjs\u002Fcommon';\nimport { AuthGuard } from '..\u002Fguards\u002Fauth.guard';\nimport { RbacAuthorizationGuard } from '..\u002Fguards\u002Frbac-authorization.guard';\nimport { RequirePermissions } from '..\u002Fdecorators\u002Frequire-permissions.decorator';\n\n@Controller('posts')\n@UseGuards(AuthGuard, RbacAuthorizationGuard)\nexport class PostsController {\n  constructor(private postsService: PostsService) {}\n\n  \u002F\u002F Публічний ендпоінт — дозволи не вимагаються\n  @Get()\n  async getAllPosts() {\n    return this.postsService.findAll();\n  }\n\n  \u002F\u002F Вимагає дозвіл на читання постів\n  @Get(':id')\n  @RequirePermissions('read:posts')\n  async getPost(@Param('id') id: string) {\n    return this.postsService.findById(id);\n  }\n\n  \u002F\u002F Вимагає дозвіл на створення постів\n  @Post()\n  @RequirePermissions('create:posts')\n  async createPost(@Body() createDto: CreatePostDto) {\n    return this.postsService.create(createDto);\n  }\n\n  \u002F\u002F Вимагає дозвіл на редагування постів\n  @Put(':id')\n  @RequirePermissions('edit:posts')\n  async updatePost(@Param('id') id: string, @Body() updateDto: UpdatePostDto) {\n    return this.postsService.update(id, updateDto);\n  }\n\n  \u002F\u002F Вимагає дозвіл на видалення постів (зазвичай лише admin або moderator)\n  @Delete(':id')\n  @RequirePermissions('delete:posts')\n  async deletePost(@Param('id') id: string) {\n    return this.postsService.delete(id);\n  }\n\n  \u002F\u002F Ендпоінт адміністрування — вимагає кілька дозволів одночасно\n  @Post(':id\u002Fpublish')\n  @RequirePermissions('edit:posts', 'publish:posts')\n  async publishPost(@Param('id') id: string) {\n    return this.postsService.publish(id);\n  }\n}\n",[5231,11444,11445,11450,11494,11510,11528,11546,11550,11563,11579,11590,11608,11612,11617,11625,11635,11653,11657,11661,11666,11678,11691,11716,11736,11740,11744,11749,11757,11770,11792,11812,11816,11820,11825,11837,11850,11889,11913,11917,11921,11926,11938,11951,11976,11996,12000,12004,12009,12022,12039,12064,12085,12089],{"__ignoreMap":5425},[5429,11446,11447],{"class":5431,"line":5432},[5429,11448,11449],{"class":5435},"\u002F\u002F controllers\u002Fposts.controller.ts\n",[5429,11451,11452,11454,11456,11458,11460,11462,11464,11466,11468,11470,11472,11474,11476,11478,11480,11482,11484,11486,11488,11490,11492],{"class":5431,"line":5439},[5429,11453,5821],{"class":5579},[5429,11455,5824],{"class":5590},[5429,11457,6888],{"class":5596},[5429,11459,5234],{"class":5590},[5429,11461,6893],{"class":5596},[5429,11463,5234],{"class":5590},[5429,11465,6908],{"class":5596},[5429,11467,5234],{"class":5590},[5429,11469,6898],{"class":5596},[5429,11471,5234],{"class":5590},[5429,11473,6903],{"class":5596},[5429,11475,5234],{"class":5590},[5429,11477,6913],{"class":5596},[5429,11479,5234],{"class":5590},[5429,11481,6918],{"class":5596},[5429,11483,5234],{"class":5590},[5429,11485,6923],{"class":5596},[5429,11487,5845],{"class":5590},[5429,11489,5848],{"class":5579},[5429,11491,5851],{"class":5446},[5429,11493,5606],{"class":5590},[5429,11495,11496,11498,11500,11502,11504,11506,11508],{"class":5431,"line":5450},[5429,11497,5821],{"class":5579},[5429,11499,5824],{"class":5590},[5429,11501,6940],{"class":5596},[5429,11503,5845],{"class":5590},[5429,11505,5848],{"class":5579},[5429,11507,6947],{"class":5446},[5429,11509,5606],{"class":5590},[5429,11511,11512,11514,11516,11519,11521,11523,11526],{"class":5431,"line":5457},[5429,11513,5821],{"class":5579},[5429,11515,5824],{"class":5590},[5429,11517,11518],{"class":5596},"RbacAuthorizationGuard",[5429,11520,5845],{"class":5590},[5429,11522,5848],{"class":5579},[5429,11524,11525],{"class":5446}," '..\u002Fguards\u002Frbac-authorization.guard'",[5429,11527,5606],{"class":5590},[5429,11529,11530,11532,11534,11537,11539,11541,11544],{"class":5431,"line":5463},[5429,11531,5821],{"class":5579},[5429,11533,5824],{"class":5590},[5429,11535,11536],{"class":5596},"RequirePermissions",[5429,11538,5845],{"class":5590},[5429,11540,5848],{"class":5579},[5429,11542,11543],{"class":5446}," '..\u002Fdecorators\u002Frequire-permissions.decorator'",[5429,11545,5606],{"class":5590},[5429,11547,11548],{"class":5431,"line":5475},[5429,11549,5454],{"emptyLinePlaceholder":5453},[5429,11551,11552,11554,11556,11558,11561],{"class":5431,"line":5481},[5429,11553,5898],{"class":5590},[5429,11555,6888],{"class":5442},[5429,11557,5975],{"class":5590},[5429,11559,11560],{"class":5446},"'posts'",[5429,11562,7021],{"class":5590},[5429,11564,11565,11567,11569,11571,11573,11575,11577],{"class":5431,"line":5487},[5429,11566,5898],{"class":5590},[5429,11568,6923],{"class":5442},[5429,11570,5975],{"class":5590},[5429,11572,6940],{"class":5596},[5429,11574,5234],{"class":5590},[5429,11576,11518],{"class":5596},[5429,11578,7021],{"class":5590},[5429,11580,11581,11583,11585,11588],{"class":5431,"line":5493},[5429,11582,5580],{"class":5579},[5429,11584,5583],{"class":5469},[5429,11586,11587],{"class":5586}," PostsController",[5429,11589,5591],{"class":5590},[5429,11591,11592,11594,11596,11598,11601,11603,11606],{"class":5431,"line":5499},[5429,11593,5925],{"class":5469},[5429,11595,5975],{"class":5590},[5429,11597,7057],{"class":5469},[5429,11599,11600],{"class":5596}," postsService",[5429,11602,5600],{"class":5590},[5429,11604,11605],{"class":5586},"PostsService",[5429,11607,7066],{"class":5590},[5429,11609,11610],{"class":5431,"line":5505},[5429,11611,5454],{"emptyLinePlaceholder":5453},[5429,11613,11614],{"class":5431,"line":5510},[5429,11615,11616],{"class":5435},"  \u002F\u002F Публічний ендпоінт — дозволи не вимагаються\n",[5429,11618,11619,11621,11623],{"class":5431,"line":5516},[5429,11620,7080],{"class":5590},[5429,11622,6893],{"class":5442},[5429,11624,5903],{"class":5590},[5429,11626,11627,11629,11632],{"class":5431,"line":5527},[5429,11628,5969],{"class":5469},[5429,11630,11631],{"class":5442}," getAllPosts",[5429,11633,11634],{"class":5590},"() {\n",[5429,11636,11637,11639,11641,11643,11646,11648,11651],{"class":5431,"line":5532},[5429,11638,6560],{"class":5579},[5429,11640,6257],{"class":5469},[5429,11642,5209],{"class":5590},[5429,11644,11645],{"class":5596},"postsService",[5429,11647,5209],{"class":5590},[5429,11649,11650],{"class":5442},"findAll",[5429,11652,6141],{"class":5590},[5429,11654,11655],{"class":5431,"line":5538},[5429,11656,6570],{"class":5590},[5429,11658,11659],{"class":5431,"line":5547},[5429,11660,5454],{"emptyLinePlaceholder":5453},[5429,11662,11663],{"class":5431,"line":5748},[5429,11664,11665],{"class":5435},"  \u002F\u002F Вимагає дозвіл на читання постів\n",[5429,11667,11668,11670,11672,11674,11676],{"class":5431,"line":5760},[5429,11669,7080],{"class":5590},[5429,11671,6893],{"class":5442},[5429,11673,5975],{"class":5590},[5429,11675,7087],{"class":5446},[5429,11677,7021],{"class":5590},[5429,11679,11680,11682,11684,11686,11689],{"class":5431,"line":5772},[5429,11681,7080],{"class":5590},[5429,11683,11536],{"class":5442},[5429,11685,5975],{"class":5590},[5429,11687,11688],{"class":5446},"'read:posts'",[5429,11690,7021],{"class":5590},[5429,11692,11693,11695,11698,11700,11702,11704,11706,11708,11710,11712,11714],{"class":5431,"line":5787},[5429,11694,5969],{"class":5469},[5429,11696,11697],{"class":5442}," getPost",[5429,11699,7111],{"class":5590},[5429,11701,6913],{"class":5442},[5429,11703,5975],{"class":5590},[5429,11705,7118],{"class":5446},[5429,11707,6845],{"class":5590},[5429,11709,6186],{"class":5596},[5429,11711,5600],{"class":5590},[5429,11713,5603],{"class":5586},[5429,11715,6092],{"class":5590},[5429,11717,11718,11720,11722,11724,11726,11728,11730,11732,11734],{"class":5431,"line":5799},[5429,11719,6560],{"class":5579},[5429,11721,6257],{"class":5469},[5429,11723,5209],{"class":5590},[5429,11725,11645],{"class":5596},[5429,11727,5209],{"class":5590},[5429,11729,6267],{"class":5442},[5429,11731,5975],{"class":5590},[5429,11733,6186],{"class":5596},[5429,11735,6231],{"class":5590},[5429,11737,11738],{"class":5431,"line":6113},[5429,11739,6570],{"class":5590},[5429,11741,11742],{"class":5431,"line":6118},[5429,11743,5454],{"emptyLinePlaceholder":5453},[5429,11745,11746],{"class":5431,"line":6144},[5429,11747,11748],{"class":5435},"  \u002F\u002F Вимагає дозвіл на створення постів\n",[5429,11750,11751,11753,11755],{"class":5431,"line":6167},[5429,11752,7080],{"class":5590},[5429,11754,6908],{"class":5442},[5429,11756,5903],{"class":5590},[5429,11758,11759,11761,11763,11765,11768],{"class":5431,"line":6191},[5429,11760,7080],{"class":5590},[5429,11762,11536],{"class":5442},[5429,11764,5975],{"class":5590},[5429,11766,11767],{"class":5446},"'create:posts'",[5429,11769,7021],{"class":5590},[5429,11771,11772,11774,11777,11779,11781,11783,11785,11787,11790],{"class":5431,"line":6196},[5429,11773,5969],{"class":5469},[5429,11775,11776],{"class":5442}," createPost",[5429,11778,7111],{"class":5590},[5429,11780,6918],{"class":5442},[5429,11782,7224],{"class":5590},[5429,11784,9214],{"class":5596},[5429,11786,5600],{"class":5590},[5429,11788,11789],{"class":5586},"CreatePostDto",[5429,11791,6092],{"class":5590},[5429,11793,11794,11796,11798,11800,11802,11804,11806,11808,11810],{"class":5431,"line":6214},[5429,11795,6560],{"class":5579},[5429,11797,6257],{"class":5469},[5429,11799,5209],{"class":5590},[5429,11801,11645],{"class":5596},[5429,11803,5209],{"class":5590},[5429,11805,9368],{"class":5442},[5429,11807,5975],{"class":5590},[5429,11809,9214],{"class":5596},[5429,11811,6231],{"class":5590},[5429,11813,11814],{"class":5431,"line":6234},[5429,11815,6570],{"class":5590},[5429,11817,11818],{"class":5431,"line":6239},[5429,11819,5454],{"emptyLinePlaceholder":5453},[5429,11821,11822],{"class":5431,"line":6244},[5429,11823,11824],{"class":5435},"  \u002F\u002F Вимагає дозвіл на редагування постів\n",[5429,11826,11827,11829,11831,11833,11835],{"class":5431,"line":6276},[5429,11828,7080],{"class":5590},[5429,11830,6898],{"class":5442},[5429,11832,5975],{"class":5590},[5429,11834,7087],{"class":5446},[5429,11836,7021],{"class":5590},[5429,11838,11839,11841,11843,11845,11848],{"class":5431,"line":6281},[5429,11840,7080],{"class":5590},[5429,11842,11536],{"class":5442},[5429,11844,5975],{"class":5590},[5429,11846,11847],{"class":5446},"'edit:posts'",[5429,11849,7021],{"class":5590},[5429,11851,11852,11854,11857,11859,11861,11863,11865,11867,11869,11871,11873,11876,11878,11880,11882,11884,11887],{"class":5431,"line":6293},[5429,11853,5969],{"class":5469},[5429,11855,11856],{"class":5442}," updatePost",[5429,11858,7111],{"class":5590},[5429,11860,6913],{"class":5442},[5429,11862,5975],{"class":5590},[5429,11864,7118],{"class":5446},[5429,11866,6845],{"class":5590},[5429,11868,6186],{"class":5596},[5429,11870,5600],{"class":5590},[5429,11872,5603],{"class":5586},[5429,11874,11875],{"class":5590},", @",[5429,11877,6918],{"class":5442},[5429,11879,7224],{"class":5590},[5429,11881,7227],{"class":5596},[5429,11883,5600],{"class":5590},[5429,11885,11886],{"class":5586},"UpdatePostDto",[5429,11888,6092],{"class":5590},[5429,11890,11891,11893,11895,11897,11899,11901,11903,11905,11907,11909,11911],{"class":5431,"line":6306},[5429,11892,6560],{"class":5579},[5429,11894,6257],{"class":5469},[5429,11896,5209],{"class":5590},[5429,11898,11645],{"class":5596},[5429,11900,5209],{"class":5590},[5429,11902,7252],{"class":5442},[5429,11904,5975],{"class":5590},[5429,11906,6186],{"class":5596},[5429,11908,5234],{"class":5590},[5429,11910,7227],{"class":5596},[5429,11912,6231],{"class":5590},[5429,11914,11915],{"class":5431,"line":6311},[5429,11916,6570],{"class":5590},[5429,11918,11919],{"class":5431,"line":6316},[5429,11920,5454],{"emptyLinePlaceholder":5453},[5429,11922,11923],{"class":5431,"line":6322},[5429,11924,11925],{"class":5435},"  \u002F\u002F Вимагає дозвіл на видалення постів (зазвичай лише admin або moderator)\n",[5429,11927,11928,11930,11932,11934,11936],{"class":5431,"line":6348},[5429,11929,7080],{"class":5590},[5429,11931,6903],{"class":5442},[5429,11933,5975],{"class":5590},[5429,11935,7087],{"class":5446},[5429,11937,7021],{"class":5590},[5429,11939,11940,11942,11944,11946,11949],{"class":5431,"line":6357},[5429,11941,7080],{"class":5590},[5429,11943,11536],{"class":5442},[5429,11945,5975],{"class":5590},[5429,11947,11948],{"class":5446},"'delete:posts'",[5429,11950,7021],{"class":5590},[5429,11952,11953,11955,11958,11960,11962,11964,11966,11968,11970,11972,11974],{"class":5431,"line":6362},[5429,11954,5969],{"class":5469},[5429,11956,11957],{"class":5442}," deletePost",[5429,11959,7111],{"class":5590},[5429,11961,6913],{"class":5442},[5429,11963,5975],{"class":5590},[5429,11965,7118],{"class":5446},[5429,11967,6845],{"class":5590},[5429,11969,6186],{"class":5596},[5429,11971,5600],{"class":5590},[5429,11973,5603],{"class":5586},[5429,11975,6092],{"class":5590},[5429,11977,11978,11980,11982,11984,11986,11988,11990,11992,11994],{"class":5431,"line":6367},[5429,11979,6560],{"class":5579},[5429,11981,6257],{"class":5469},[5429,11983,5209],{"class":5590},[5429,11985,11645],{"class":5596},[5429,11987,5209],{"class":5590},[5429,11989,7339],{"class":5442},[5429,11991,5975],{"class":5590},[5429,11993,6186],{"class":5596},[5429,11995,6231],{"class":5590},[5429,11997,11998],{"class":5431,"line":6373},[5429,11999,6570],{"class":5590},[5429,12001,12002],{"class":5431,"line":6420},[5429,12003,5454],{"emptyLinePlaceholder":5453},[5429,12005,12006],{"class":5431,"line":6425},[5429,12007,12008],{"class":5435},"  \u002F\u002F Ендпоінт адміністрування — вимагає кілька дозволів одночасно\n",[5429,12010,12011,12013,12015,12017,12020],{"class":5431,"line":6437},[5429,12012,7080],{"class":5590},[5429,12014,6908],{"class":5442},[5429,12016,5975],{"class":5590},[5429,12018,12019],{"class":5446},"':id\u002Fpublish'",[5429,12021,7021],{"class":5590},[5429,12023,12024,12026,12028,12030,12032,12034,12037],{"class":5431,"line":6453},[5429,12025,7080],{"class":5590},[5429,12027,11536],{"class":5442},[5429,12029,5975],{"class":5590},[5429,12031,11847],{"class":5446},[5429,12033,5234],{"class":5590},[5429,12035,12036],{"class":5446},"'publish:posts'",[5429,12038,7021],{"class":5590},[5429,12040,12041,12043,12046,12048,12050,12052,12054,12056,12058,12060,12062],{"class":5431,"line":6458},[5429,12042,5969],{"class":5469},[5429,12044,12045],{"class":5442}," publishPost",[5429,12047,7111],{"class":5590},[5429,12049,6913],{"class":5442},[5429,12051,5975],{"class":5590},[5429,12053,7118],{"class":5446},[5429,12055,6845],{"class":5590},[5429,12057,6186],{"class":5596},[5429,12059,5600],{"class":5590},[5429,12061,5603],{"class":5586},[5429,12063,6092],{"class":5590},[5429,12065,12066,12068,12070,12072,12074,12076,12079,12081,12083],{"class":5431,"line":6463},[5429,12067,6560],{"class":5579},[5429,12069,6257],{"class":5469},[5429,12071,5209],{"class":5590},[5429,12073,11645],{"class":5596},[5429,12075,5209],{"class":5590},[5429,12077,12078],{"class":5442},"publish",[5429,12080,5975],{"class":5590},[5429,12082,6186],{"class":5596},[5429,12084,6231],{"class":5590},[5429,12086,12087],{"class":5431,"line":6469},[5429,12088,6570],{"class":5590},[5429,12090,12091],{"class":5431,"line":6496},[5429,12092,5683],{"class":5590},[5317,12094,12096],{"id":12095},"переваги-та-недоліки-rbac","Переваги та недоліки RBAC",[5089,12098,12099],{},[5099,12100,7491],{},[5093,12102,12103,12109,12125,12131,12137],{},[5096,12104,12105,12108],{},[5099,12106,12107],{},"Спрощене адміністрування:"," призначення ролей набагато простіше за призначення індивідуальних дозволів кожному користувачеві. При зміні відповідальностей команди достатньо змінити дозволи ролі.",[5096,12110,12111,12114,12115,5234,12117,5234,12119,5234,12122,5242],{},[5099,12112,12113],{},"Відповідність організаційній структурі:"," ролі природно відображають посади та функції у компанії (",[5231,12116,9634],{},[5231,12118,9637],{},[5231,12120,12121],{},"project_manager",[5231,12123,12124],{},"billing_admin",[5096,12126,12127,12130],{},[5099,12128,12129],{},"Масштабованість:"," для системи з 1000 користувачів достатньо 10–20 ролей замість індивідуальних налаштувань для кожного.",[5096,12132,12133,12136],{},[5099,12134,12135],{},"Аудит та комплаєнс:"," легко відповісти на питання «Які користувачі мають доступ до фінансових даних?» — достатньо знайти всіх, хто має відповідну роль.",[5096,12138,12139,12142],{},[5099,12140,12141],{},"Підтримка ієрархії:"," старші ролі автоматично успадковують дозволи молодших, що зменшує дублювання конфігурацій.",[5089,12144,12145],{},[5099,12146,7522],{},[5093,12148,12149,12155,12173,12179],{},[5096,12150,12151,12154],{},[5099,12152,12153],{},"Недостатня гранулярність для складних сценаріїв:"," RBAC погано справляється з правилами виду «Користувач може редагувати лише власні пости» або «Доступ дозволений лише у робочі години».",[5096,12156,12157,12160,12161,5234,12164,5234,12167,12170,12171,5209],{},[5099,12158,12159],{},"Вибух кількості ролей (Role Explosion):"," у великих організаціях кількість ролей може зрости до сотень через необхідність покривати всі комбінації дозволів. Наприклад, ",[5231,12162,12163],{},"editor_marketing",[5231,12165,12166],{},"editor_engineering",[5231,12168,12169],{},"editor_billing"," замість однієї ролі ",[5231,12172,7591],{},[5096,12174,12175,12178],{},[5099,12176,12177],{},"Статичність:"," ролі визначаються заздалегідь і не враховують динамічний контекст виконання запиту (час, місцезнаходження, стан ресурсу).",[5096,12180,12181,12184],{},[5099,12182,12183],{},"Проблема тимчасових дозволів:"," якщо користувачеві потрібен короткостроковий доступ для виконання конкретної задачі, доводиться або створювати тимчасову роль, або надавати постійну роль з надмірними правами.",[12186,12187,12188,12191,12192,12194,12195,12198,12199,12201,12202,5209],"tip",{},[5099,12189,12190],{},"Гібридний підхід:"," багато систем комбінують RBAC з перевіркою власності ресурсу. Наприклад, роль ",[5231,12193,7591],{}," дозволяє редагувати пости, але додаткова перевірка у сервісному шарі гарантує, що користувач може редагувати лише ",[5099,12196,12197],{},"свої"," пости, якщо він не має ролі ",[5231,12200,5283],{},". Це називається ",[5099,12203,12204],{},"RBAC + Resource-Based Authorization",[5317,12206,12208],{"id":12207},"типові-сценарії-використання-rbac","Типові сценарії використання RBAC",[5089,12210,12211],{},[5099,12212,12213],{},"Корпоративні застосунки:",[5093,12215,12216,12227,12230],{},[5096,12217,12218,12219,5234,12222,5234,12225,5209],{},"CRM системи (Salesforce, HubSpot) — ролі ",[5231,12220,12221],{},"sales_rep",[5231,12223,12224],{},"sales_manager",[5231,12226,5283],{},[5096,12228,12229],{},"ERP системи (SAP, Oracle) — ролі для різних департаментів та рівнів управління.",[5096,12231,12232,12233,5234,12235,5234,12238,12240],{},"Системи управління проєктами (Jira, Asana) — ролі ",[5231,12234,7587],{},[5231,12236,12237],{},"member",[5231,12239,5283],{}," на рівні проєкту.",[5089,12242,12243],{},[5099,12244,12245],{},"Платформи для розробників:",[5093,12247,12248,12262],{},[5096,12249,12250,12251,5234,12253,12255,12256,5234,12258,5234,12260,5242],{},"GitHub — ролі на рівні організації (",[5231,12252,5311],{},[5231,12254,12237],{},") та репозиторію (",[5231,12257,5283],{},[5231,12259,5286],{},[5231,12261,5289],{},[5096,12263,12264,12265,5234,12268,5234,12271,5234,12274,5234,12277,5209],{},"GitLab — ролі ",[5231,12266,12267],{},"Guest",[5231,12269,12270],{},"Reporter",[5231,12272,12273],{},"Developer",[5231,12275,12276],{},"Maintainer",[5231,12278,12279],{},"Owner",[5089,12281,12282],{},[5099,12283,12284],{},"Хмарні платформи:",[5093,12286,12287,12290],{},[5096,12288,12289],{},"AWS IAM — ролі для EC2 інстансів, Lambda функцій, користувачів.",[5096,12291,12292,12293,5234,12295,5234,12297,12299],{},"Google Cloud IAM — предвизначені ролі (",[5231,12294,9967],{},[5231,12296,9964],{},[5231,12298,12279],{},") та кастомні ролі.",[5125,12301],{},[5084,12303,12305],{"id":12304},"abac-атрибутивний-контроль-доступу","ABAC: Атрибутивний контроль доступу",[5089,12307,12308,12311,12312,5260,12314,12316],{},[5099,12309,12310],{},"Attribute-Based Access Control (ABAC)"," — це найгнучкіша та найскладніша модель, у якій рішення про доступ приймається динамічно на основі ",[5099,12313,5272],{},[5194,12315,5275],{},") чотирьох категорій:",[5219,12318,12319,12328,12337,12346],{},[5096,12320,12321,5260,12324,12327],{},[5099,12322,12323],{},"Атрибути суб'єкта",[5194,12325,12326],{},"subject attributes",") — властивості користувача: роль, відділ, рівень допуску, вік облікового запису, підтверджений email.",[5096,12329,12330,5260,12333,12336],{},[5099,12331,12332],{},"Атрибути об'єкта",[5194,12334,12335],{},"object\u002Fresource attributes",") — властивості ресурсу: тип документа, власник, рівень конфіденційності, дата створення.",[5096,12338,12339,5260,12342,12345],{},[5099,12340,12341],{},"Атрибути дії",[5194,12343,12344],{},"action attributes",") — тип операції: читання, запис, видалення, експорт.",[5096,12347,12348,5260,12351,12354],{},[5099,12349,12350],{},"Атрибути контексту",[5194,12352,12353],{},"context\u002Fenvironment attributes",") — умови виконання: час доби, день тижня, IP-адреса, геолокація, стан сесії.",[5317,12356,12358],{"id":12357},"базові-принципи-abac","Базові принципи ABAC",[5089,12360,12361],{},[5099,12362,5325],{},[5093,12364,12365,12386,12392,12403],{},[5096,12366,12367,12370,12371,5260,12374,12377,12378,12381,12382,12385],{},[5099,12368,12369],{},"Динамічне прийняття рішень:"," замість статичних списків дозволів система оцінює ",[5099,12372,12373],{},"політику",[5194,12375,12376],{},"policy",") — набір правил виду «ЯКЩО користувач з відділу ",[5231,12379,12380],{},"engineering"," звертається до документа типу ",[5231,12383,12384],{},"technical_spec"," у робочі години з офісної IP, ТО дозволити читання та редагування».",[5096,12387,12388,12391],{},[5099,12389,12390],{},"Виразність складних правил:"," ABAC дозволяє виражати правила, що неможливо реалізувати в RBAC. Наприклад: «Лікар може переглядати медичні записи пацієнтів, призначених йому у цьому місяці, лише з робочої станції у клініці, та лише у робочі години».",[5096,12393,12394,12397,12398,5234,12400,12402],{},[5099,12395,12396],{},"Гранулярний контроль:"," замість широких ролей (",[5231,12399,5283],{},[5231,12401,7591],{},") можна визначити точні умови для кожного ресурсу.",[5096,12404,12405,12408],{},[5099,12406,12407],{},"Відсутність заздалегідь визначених ролей:"," система не потребує створення ролей — всі рішення базуються на атрибутах, що вже існують у базі даних.",[5317,12410,12412],{"id":12411},"приклад-політики-abac","Приклад політики ABAC",[5089,12414,12415],{},"Розглянемо політику для системи управління медичними записами:",[5089,12417,12418],{},[5099,12419,12420],{},"Політика 1: Доступ лікаря до записів пацієнтів",[5420,12422,12427],{"className":12423,"code":12425,"language":12426},[12424],"language-text","ПРАВИЛО: Дозволити читання медичного запису\nЯКЩО:\n  - subject.role == \"doctor\"\n  - subject.department == resource.departmentAssigned\n  - subject.licenseStatus == \"active\"\n  - context.time BETWEEN 08:00 AND 20:00\n  - context.location == \"clinic_network\"\n  - resource.patientId IN subject.assignedPatients\n","text",[5231,12428,12425],{"__ignoreMap":5425},[5089,12430,12431],{},[5099,12432,12433],{},"Політика 2: Експорт даних для дослідників",[5420,12435,12438],{"className":12436,"code":12437,"language":12426},[12424],"ПРАВИЛО: Дозволити експорт знеособлених даних\nЯКЩО:\n  - subject.role == \"researcher\"\n  - subject.hasEthicsApproval == true\n  - resource.type == \"anonymized_dataset\"\n  - action == \"export\"\n  - context.approvalExpiryDate > context.currentDate\n",[5231,12439,12437],{"__ignoreMap":5425},[5317,12441,12443],{"id":12442},"візуалізація-abac-моделі","Візуалізація ABAC моделі",[7894,12445,12446],{},[5420,12447,12449],{"className":7898,"code":12448,"language":7894,"meta":5425,"style":5425},"graph TB\n    subgraph \"Джерела атрибутів\"\n        S[Subject Attributes\u003Cbr\u002F>роль, відділ,\u003Cbr\u002F>рівень допуску]\n        O[Object Attributes\u003Cbr\u002F>тип, власник,\u003Cbr\u002F>конфіденційність]\n        A[Action Attributes\u003Cbr\u002F>читання, запис,\u003Cbr\u002F>видалення, експорт]\n        C[Context Attributes\u003Cbr\u002F>час, місце,\u003Cbr\u002F>IP, стан сесії]\n    end\n    \n    PDP[Policy Decision Point\u003Cbr\u002F>Точка прийняття рішень]\n    PEP[Policy Enforcement Point\u003Cbr\u002F>Точка застосування рішень]\n    \n    S --> PDP\n    O --> PDP\n    A --> PDP\n    C --> PDP\n    \n    PDP -->|PERMIT \u002F DENY| PEP\n    PEP -->|Allow Access| RES[Protected Resource]\n    PEP -->|Block Access| DENY[403 Forbidden]\n    \n    style S fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n    style O fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n    style A fill:#10b981,stroke:#047857,color:#ffffff\n    style C fill:#f59e0b,stroke:#b45309,color:#ffffff\n    style PDP fill:#ef4444,stroke:#b91c1c,color:#ffffff\n    style RES fill:#10b981,stroke:#047857,color:#ffffff\n    style DENY fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[5231,12450,12451,12455,12460,12465,12470,12475,12480,12484,12488,12493,12498,12502,12507,12512,12517,12522,12526,12531,12536,12541,12545,12550,12555,12560,12565,12570,12575],{"__ignoreMap":5425},[5429,12452,12453],{"class":5431,"line":5432},[5429,12454,7906],{},[5429,12456,12457],{"class":5431,"line":5439},[5429,12458,12459],{},"    subgraph \"Джерела атрибутів\"\n",[5429,12461,12462],{"class":5431,"line":5450},[5429,12463,12464],{},"        S[Subject Attributes\u003Cbr\u002F>роль, відділ,\u003Cbr\u002F>рівень допуску]\n",[5429,12466,12467],{"class":5431,"line":5457},[5429,12468,12469],{},"        O[Object Attributes\u003Cbr\u002F>тип, власник,\u003Cbr\u002F>конфіденційність]\n",[5429,12471,12472],{"class":5431,"line":5463},[5429,12473,12474],{},"        A[Action Attributes\u003Cbr\u002F>читання, запис,\u003Cbr\u002F>видалення, експорт]\n",[5429,12476,12477],{"class":5431,"line":5475},[5429,12478,12479],{},"        C[Context Attributes\u003Cbr\u002F>час, місце,\u003Cbr\u002F>IP, стан сесії]\n",[5429,12481,12482],{"class":5431,"line":5481},[5429,12483,7936],{},[5429,12485,12486],{"class":5431,"line":5487},[5429,12487,7941],{},[5429,12489,12490],{"class":5431,"line":5493},[5429,12491,12492],{},"    PDP[Policy Decision Point\u003Cbr\u002F>Точка прийняття рішень]\n",[5429,12494,12495],{"class":5431,"line":5499},[5429,12496,12497],{},"    PEP[Policy Enforcement Point\u003Cbr\u002F>Точка застосування рішень]\n",[5429,12499,12500],{"class":5431,"line":5505},[5429,12501,7941],{},[5429,12503,12504],{"class":5431,"line":5510},[5429,12505,12506],{},"    S --> PDP\n",[5429,12508,12509],{"class":5431,"line":5516},[5429,12510,12511],{},"    O --> PDP\n",[5429,12513,12514],{"class":5431,"line":5527},[5429,12515,12516],{},"    A --> PDP\n",[5429,12518,12519],{"class":5431,"line":5532},[5429,12520,12521],{},"    C --> PDP\n",[5429,12523,12524],{"class":5431,"line":5538},[5429,12525,7941],{},[5429,12527,12528],{"class":5431,"line":5547},[5429,12529,12530],{},"    PDP -->|PERMIT \u002F DENY| PEP\n",[5429,12532,12533],{"class":5431,"line":5748},[5429,12534,12535],{},"    PEP -->|Allow Access| RES[Protected Resource]\n",[5429,12537,12538],{"class":5431,"line":5760},[5429,12539,12540],{},"    PEP -->|Block Access| DENY[403 Forbidden]\n",[5429,12542,12543],{"class":5431,"line":5772},[5429,12544,7941],{},[5429,12546,12547],{"class":5431,"line":5787},[5429,12548,12549],{},"    style S fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n",[5429,12551,12552],{"class":5431,"line":5799},[5429,12553,12554],{},"    style O fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n",[5429,12556,12557],{"class":5431,"line":6113},[5429,12558,12559],{},"    style A fill:#10b981,stroke:#047857,color:#ffffff\n",[5429,12561,12562],{"class":5431,"line":6118},[5429,12563,12564],{},"    style C fill:#f59e0b,stroke:#b45309,color:#ffffff\n",[5429,12566,12567],{"class":5431,"line":6144},[5429,12568,12569],{},"    style PDP fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[5429,12571,12572],{"class":5431,"line":6167},[5429,12573,12574],{},"    style RES fill:#10b981,stroke:#047857,color:#ffffff\n",[5429,12576,12577],{"class":5431,"line":6191},[5429,12578,12579],{},"    style DENY fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[5089,12581,12582],{},[5099,12583,12584],{},"Пояснення компонентів:",[5093,12586,12587,12601],{},[5096,12588,12589,12592,12593,12596,12597,12600],{},[5099,12590,12591],{},"PDP (Policy Decision Point):"," компонент, що оцінює політики та приймає рішення ",[5231,12594,12595],{},"PERMIT"," (дозволити) або ",[5231,12598,12599],{},"DENY"," (відхилити).",[5096,12602,12603,12606,12607,5209],{},[5099,12604,12605],{},"PEP (Policy Enforcement Point):"," компонент, що застосовує рішення PDP — пропускає запит далі або повертає ",[5231,12608,12609],{},"403 Forbidden",[5317,12611,12613],{"id":12612},"реалізація-abac-у-nestjs-спрощена","Реалізація ABAC у NestJS (спрощена)",[5089,12615,12616,12617,12620],{},"Повноцінна реалізація ABAC вимагає спеціалізованих бібліотек (наприклад, ",[5099,12618,12619],{},"CASL"," — про неї детально у наступній лекції). Розглянемо концептуальну реалізацію для ілюстрації принципів:",[5089,12622,12623],{},[5099,12624,12625],{},"Інтерфейс політики:",[5420,12627,12629],{"className":5565,"code":12628,"language":5567,"meta":5425,"style":5425},"\u002F\u002F domain\u002Fpolicy.interface.ts\nexport interface AbacPolicy {\n  name: string;\n  description: string;\n  \n  \u002F**\n   * Оцінює, чи дозволяє політика виконання дії\n   * @returns true якщо дозволено, false якщо заборонено\n   *\u002F\n  evaluate(context: AbacContext): Promise\u003Cboolean>;\n}\n\nexport interface AbacContext {\n  subject: {\n    userId: string;\n    email: string;\n    roles: string[];\n    department: string;\n    emailVerified: boolean;\n  };\n  resource: {\n    id: string;\n    type: string;\n    ownerId: string;\n    confidentialityLevel: number;\n  };\n  action: string; \u002F\u002F 'read', 'write', 'delete', 'export'\n  environment: {\n    time: Date;\n    ipAddress: string;\n    userAgent: string;\n  };\n}\n",[5231,12630,12631,12636,12648,12658,12668,12672,12676,12681,12692,12696,12721,12725,12729,12740,12748,12759,12770,12781,12792,12803,12808,12814,12825,12836,12847,12859,12863,12876,12883,12894,12905,12916,12920],{"__ignoreMap":5425},[5429,12632,12633],{"class":5431,"line":5432},[5429,12634,12635],{"class":5435},"\u002F\u002F domain\u002Fpolicy.interface.ts\n",[5429,12637,12638,12640,12643,12646],{"class":5431,"line":5439},[5429,12639,5580],{"class":5579},[5429,12641,12642],{"class":5469}," interface",[5429,12644,12645],{"class":5586}," AbacPolicy",[5429,12647,5591],{"class":5590},[5429,12649,12650,12652,12654,12656],{"class":5431,"line":5450},[5429,12651,10047],{"class":5596},[5429,12653,5600],{"class":5590},[5429,12655,5603],{"class":5586},[5429,12657,5606],{"class":5590},[5429,12659,12660,12662,12664,12666],{"class":5431,"line":5457},[5429,12661,10061],{"class":5596},[5429,12663,5600],{"class":5590},[5429,12665,5603],{"class":5586},[5429,12667,5606],{"class":5590},[5429,12669,12670],{"class":5431,"line":5463},[5429,12671,5660],{"class":5590},[5429,12673,12674],{"class":5431,"line":5475},[5429,12675,10386],{"class":5435},[5429,12677,12678],{"class":5431,"line":5481},[5429,12679,12680],{"class":5435},"   * Оцінює, чи дозволяє політика виконання дії\n",[5429,12682,12683,12686,12689],{"class":5431,"line":5487},[5429,12684,12685],{"class":5435},"   * ",[5429,12687,12688],{"class":5469},"@returns",[5429,12690,12691],{"class":5435}," true якщо дозволено, false якщо заборонено\n",[5429,12693,12694],{"class":5431,"line":5493},[5429,12695,10396],{"class":5435},[5429,12697,12698,12701,12703,12705,12707,12710,12712,12714,12716,12718],{"class":5431,"line":5499},[5429,12699,12700],{"class":5442},"  evaluate",[5429,12702,5975],{"class":5590},[5429,12704,5978],{"class":5596},[5429,12706,5600],{"class":5590},[5429,12708,12709],{"class":5586},"AbacContext",[5429,12711,5985],{"class":5590},[5429,12713,5988],{"class":5586},[5429,12715,5991],{"class":5590},[5429,12717,5743],{"class":5586},[5429,12719,12720],{"class":5590},">;\n",[5429,12722,12723],{"class":5431,"line":5505},[5429,12724,5683],{"class":5590},[5429,12726,12727],{"class":5431,"line":5510},[5429,12728,5454],{"emptyLinePlaceholder":5453},[5429,12730,12731,12733,12735,12738],{"class":5431,"line":5516},[5429,12732,5580],{"class":5579},[5429,12734,12642],{"class":5469},[5429,12736,12737],{"class":5586}," AbacContext",[5429,12739,5591],{"class":5590},[5429,12741,12742,12745],{"class":5431,"line":5527},[5429,12743,12744],{"class":5596},"  subject",[5429,12746,12747],{"class":5590},": {\n",[5429,12749,12750,12753,12755,12757],{"class":5431,"line":5532},[5429,12751,12752],{"class":5596},"    userId",[5429,12754,5600],{"class":5590},[5429,12756,5603],{"class":5586},[5429,12758,5606],{"class":5590},[5429,12760,12761,12764,12766,12768],{"class":5431,"line":5538},[5429,12762,12763],{"class":5596},"    email",[5429,12765,5600],{"class":5590},[5429,12767,5603],{"class":5586},[5429,12769,5606],{"class":5590},[5429,12771,12772,12775,12777,12779],{"class":5431,"line":5547},[5429,12773,12774],{"class":5596},"    roles",[5429,12776,5600],{"class":5590},[5429,12778,5603],{"class":5586},[5429,12780,5678],{"class":5590},[5429,12782,12783,12786,12788,12790],{"class":5431,"line":5748},[5429,12784,12785],{"class":5596},"    department",[5429,12787,5600],{"class":5590},[5429,12789,5603],{"class":5586},[5429,12791,5606],{"class":5590},[5429,12793,12794,12797,12799,12801],{"class":5431,"line":5760},[5429,12795,12796],{"class":5596},"    emailVerified",[5429,12798,5600],{"class":5590},[5429,12800,5743],{"class":5586},[5429,12802,5606],{"class":5590},[5429,12804,12805],{"class":5431,"line":5772},[5429,12806,12807],{"class":5590},"  };\n",[5429,12809,12810,12812],{"class":5431,"line":5787},[5429,12811,10127],{"class":5596},[5429,12813,12747],{"class":5590},[5429,12815,12816,12819,12821,12823],{"class":5431,"line":5799},[5429,12817,12818],{"class":5596},"    id",[5429,12820,5600],{"class":5590},[5429,12822,5603],{"class":5586},[5429,12824,5606],{"class":5590},[5429,12826,12827,12830,12832,12834],{"class":5431,"line":6113},[5429,12828,12829],{"class":5596},"    type",[5429,12831,5600],{"class":5590},[5429,12833,5603],{"class":5586},[5429,12835,5606],{"class":5590},[5429,12837,12838,12841,12843,12845],{"class":5431,"line":6118},[5429,12839,12840],{"class":5596},"    ownerId",[5429,12842,5600],{"class":5590},[5429,12844,5603],{"class":5586},[5429,12846,5606],{"class":5590},[5429,12848,12849,12852,12854,12857],{"class":5431,"line":6144},[5429,12850,12851],{"class":5596},"    confidentialityLevel",[5429,12853,5600],{"class":5590},[5429,12855,12856],{"class":5586},"number",[5429,12858,5606],{"class":5590},[5429,12860,12861],{"class":5431,"line":6167},[5429,12862,12807],{"class":5590},[5429,12864,12865,12867,12869,12871,12873],{"class":5431,"line":6191},[5429,12866,10141],{"class":5596},[5429,12868,5600],{"class":5590},[5429,12870,5603],{"class":5586},[5429,12872,5640],{"class":5590},[5429,12874,12875],{"class":5435},"\u002F\u002F 'read', 'write', 'delete', 'export'\n",[5429,12877,12878,12881],{"class":5431,"line":6196},[5429,12879,12880],{"class":5596},"  environment",[5429,12882,12747],{"class":5590},[5429,12884,12885,12888,12890,12892],{"class":5431,"line":6214},[5429,12886,12887],{"class":5596},"    time",[5429,12889,5600],{"class":5590},[5429,12891,5653],{"class":5586},[5429,12893,5606],{"class":5590},[5429,12895,12896,12899,12901,12903],{"class":5431,"line":6234},[5429,12897,12898],{"class":5596},"    ipAddress",[5429,12900,5600],{"class":5590},[5429,12902,5603],{"class":5586},[5429,12904,5606],{"class":5590},[5429,12906,12907,12910,12912,12914],{"class":5431,"line":6239},[5429,12908,12909],{"class":5596},"    userAgent",[5429,12911,5600],{"class":5590},[5429,12913,5603],{"class":5586},[5429,12915,5606],{"class":5590},[5429,12917,12918],{"class":5431,"line":6244},[5429,12919,12807],{"class":5590},[5429,12921,12922],{"class":5431,"line":6276},[5429,12923,5683],{"class":5590},[5089,12925,12926],{},[5099,12927,12928],{},"Приклад конкретної політики:",[5420,12930,12932],{"className":5565,"code":12931,"language":5567,"meta":5425,"style":5425},"\u002F\u002F policies\u002Fdocument-access.policy.ts\nimport { Injectable } from '@nestjs\u002Fcommon';\nimport { AbacPolicy, AbacContext } from '..\u002Fdomain\u002Fpolicy.interface';\n\n@Injectable()\nexport class DocumentAccessPolicy implements AbacPolicy {\n  name = 'DocumentAccessPolicy';\n  description = 'Користувач може редагувати документи свого відділу у робочі години';\n\n  async evaluate(context: AbacContext): Promise\u003Cboolean> {\n    const { subject, resource, action, environment } = context;\n\n    \u002F\u002F Правило 1: Власник має всі права\n    if (resource.ownerId === subject.userId) {\n      return true;\n    }\n\n    \u002F\u002F Правило 2: Документи можна редагувати лише у робочі години (8:00 - 18:00)\n    if (action === 'write' || action === 'delete') {\n      const hour = environment.time.getHours();\n      if (hour \u003C 8 || hour >= 18) {\n        return false; \u002F\u002F Поза робочими годинами — заборонено\n      }\n    }\n\n    \u002F\u002F Правило 3: Користувачі можуть читати документи з рівнем конфіденційності \u003C= 2\n    if (action === 'read' && resource.confidentialityLevel \u003C= 2) {\n      return true;\n    }\n\n    \u002F\u002F Правило 4: Адміністратори мають повні права\n    if (subject.roles.includes('admin')) {\n      return true;\n    }\n\n    \u002F\u002F Правило 5: Експорт дозволений лише з підтвердженим email\n    if (action === 'export' && !subject.emailVerified) {\n      return false;\n    }\n\n    \u002F\u002F За замовчуванням — відхилити\n    return false;\n  }\n}\n",[5231,12933,12934,12939,12955,12977,12981,12989,13004,13015,13026,13030,13055,13084,13088,13093,13115,13123,13127,13131,13136,13158,13182,13208,13219,13223,13227,13231,13236,13265,13273,13277,13281,13286,13310,13318,13322,13326,13331,13356,13364,13368,13372,13377,13385,13389],{"__ignoreMap":5425},[5429,12935,12936],{"class":5431,"line":5432},[5429,12937,12938],{"class":5435},"\u002F\u002F policies\u002Fdocument-access.policy.ts\n",[5429,12940,12941,12943,12945,12947,12949,12951,12953],{"class":5431,"line":5439},[5429,12942,5821],{"class":5579},[5429,12944,5824],{"class":5590},[5429,12946,5827],{"class":5596},[5429,12948,5845],{"class":5590},[5429,12950,5848],{"class":5579},[5429,12952,5851],{"class":5446},[5429,12954,5606],{"class":5590},[5429,12956,12957,12959,12961,12964,12966,12968,12970,12972,12975],{"class":5431,"line":5450},[5429,12958,5821],{"class":5579},[5429,12960,5824],{"class":5590},[5429,12962,12963],{"class":5596},"AbacPolicy",[5429,12965,5234],{"class":5590},[5429,12967,12709],{"class":5596},[5429,12969,5845],{"class":5590},[5429,12971,5848],{"class":5579},[5429,12973,12974],{"class":5446}," '..\u002Fdomain\u002Fpolicy.interface'",[5429,12976,5606],{"class":5590},[5429,12978,12979],{"class":5431,"line":5457},[5429,12980,5454],{"emptyLinePlaceholder":5453},[5429,12982,12983,12985,12987],{"class":5431,"line":5463},[5429,12984,5898],{"class":5590},[5429,12986,5827],{"class":5442},[5429,12988,5903],{"class":5590},[5429,12990,12991,12993,12995,12998,13000,13002],{"class":5431,"line":5475},[5429,12992,5580],{"class":5579},[5429,12994,5583],{"class":5469},[5429,12996,12997],{"class":5586}," DocumentAccessPolicy",[5429,12999,5915],{"class":5469},[5429,13001,12645],{"class":5586},[5429,13003,5591],{"class":5590},[5429,13005,13006,13008,13010,13013],{"class":5431,"line":5481},[5429,13007,10047],{"class":5596},[5429,13009,6013],{"class":5590},[5429,13011,13012],{"class":5446},"'DocumentAccessPolicy'",[5429,13014,5606],{"class":5590},[5429,13016,13017,13019,13021,13024],{"class":5431,"line":5487},[5429,13018,10061],{"class":5596},[5429,13020,6013],{"class":5590},[5429,13022,13023],{"class":5446},"'Користувач може редагувати документи свого відділу у робочі години'",[5429,13025,5606],{"class":5590},[5429,13027,13028],{"class":5431,"line":5493},[5429,13029,5454],{"emptyLinePlaceholder":5453},[5429,13031,13032,13034,13037,13039,13041,13043,13045,13047,13049,13051,13053],{"class":5431,"line":5499},[5429,13033,5969],{"class":5469},[5429,13035,13036],{"class":5442}," evaluate",[5429,13038,5975],{"class":5590},[5429,13040,5978],{"class":5596},[5429,13042,5600],{"class":5590},[5429,13044,12709],{"class":5586},[5429,13046,5985],{"class":5590},[5429,13048,5988],{"class":5586},[5429,13050,5991],{"class":5590},[5429,13052,5743],{"class":5586},[5429,13054,5996],{"class":5590},[5429,13056,13057,13059,13061,13064,13066,13068,13070,13072,13074,13077,13080,13082],{"class":5431,"line":5505},[5429,13058,6006],{"class":5469},[5429,13060,5824],{"class":5590},[5429,13062,13063],{"class":6009},"subject",[5429,13065,5234],{"class":5590},[5429,13067,10204],{"class":6009},[5429,13069,5234],{"class":5590},[5429,13071,10191],{"class":6009},[5429,13073,5234],{"class":5590},[5429,13075,13076],{"class":6009},"environment",[5429,13078,13079],{"class":5590}," } = ",[5429,13081,5978],{"class":5596},[5429,13083,5606],{"class":5590},[5429,13085,13086],{"class":5431,"line":5510},[5429,13087,5454],{"emptyLinePlaceholder":5453},[5429,13089,13090],{"class":5431,"line":5516},[5429,13091,13092],{"class":5435},"    \u002F\u002F Правило 1: Власник має всі права\n",[5429,13094,13095,13097,13099,13101,13103,13105,13107,13109,13111,13113],{"class":5431,"line":5527},[5429,13096,6083],{"class":5579},[5429,13098,5260],{"class":5590},[5429,13100,10204],{"class":5596},[5429,13102,5209],{"class":5590},[5429,13104,6333],{"class":5596},[5429,13106,6336],{"class":5590},[5429,13108,13063],{"class":5596},[5429,13110,5209],{"class":5590},[5429,13112,6407],{"class":5596},[5429,13114,6092],{"class":5590},[5429,13116,13117,13119,13121],{"class":5431,"line":5532},[5429,13118,6097],{"class":5579},[5429,13120,6100],{"class":5469},[5429,13122,5606],{"class":5590},[5429,13124,13125],{"class":5431,"line":5538},[5429,13126,6110],{"class":5590},[5429,13128,13129],{"class":5431,"line":5547},[5429,13130,5454],{"emptyLinePlaceholder":5453},[5429,13132,13133],{"class":5431,"line":5748},[5429,13134,13135],{"class":5435},"    \u002F\u002F Правило 2: Документи можна редагувати лише у робочі години (8:00 - 18:00)\n",[5429,13137,13138,13140,13142,13144,13146,13148,13150,13152,13154,13156],{"class":5431,"line":5760},[5429,13139,6083],{"class":5579},[5429,13141,5260],{"class":5590},[5429,13143,10191],{"class":5596},[5429,13145,6336],{"class":5590},[5429,13147,6037],{"class":5446},[5429,13149,11108],{"class":5590},[5429,13151,10191],{"class":5596},[5429,13153,6336],{"class":5590},[5429,13155,6042],{"class":5446},[5429,13157,6092],{"class":5590},[5429,13159,13160,13163,13166,13168,13170,13172,13175,13177,13180],{"class":5431,"line":5772},[5429,13161,13162],{"class":5469},"      const",[5429,13164,13165],{"class":6009}," hour",[5429,13167,6013],{"class":5590},[5429,13169,13076],{"class":5596},[5429,13171,5209],{"class":5590},[5429,13173,13174],{"class":5596},"time",[5429,13176,5209],{"class":5590},[5429,13178,13179],{"class":5442},"getHours",[5429,13181,6141],{"class":5590},[5429,13183,13184,13186,13188,13191,13193,13196,13198,13200,13203,13206],{"class":5431,"line":5787},[5429,13185,8713],{"class":5579},[5429,13187,5260],{"class":5590},[5429,13189,13190],{"class":5596},"hour",[5429,13192,8725],{"class":5590},[5429,13194,13195],{"class":5521},"8",[5429,13197,11108],{"class":5590},[5429,13199,13190],{"class":5596},[5429,13201,13202],{"class":5590}," >= ",[5429,13204,13205],{"class":5521},"18",[5429,13207,6092],{"class":5590},[5429,13209,13210,13212,13214,13216],{"class":5431,"line":5799},[5429,13211,6662],{"class":5579},[5429,13213,6298],{"class":5469},[5429,13215,5640],{"class":5590},[5429,13217,13218],{"class":5435},"\u002F\u002F Поза робочими годинами — заборонено\n",[5429,13220,13221],{"class":5431,"line":6113},[5429,13222,8809],{"class":5590},[5429,13224,13225],{"class":5431,"line":6118},[5429,13226,6110],{"class":5590},[5429,13228,13229],{"class":5431,"line":6144},[5429,13230,5454],{"emptyLinePlaceholder":5453},[5429,13232,13233],{"class":5431,"line":6167},[5429,13234,13235],{"class":5435},"    \u002F\u002F Правило 3: Користувачі можуть читати документи з рівнем конфіденційності \u003C= 2\n",[5429,13237,13238,13240,13242,13244,13246,13248,13251,13253,13255,13258,13261,13263],{"class":5431,"line":6191},[5429,13239,6083],{"class":5579},[5429,13241,5260],{"class":5590},[5429,13243,10191],{"class":5596},[5429,13245,6336],{"class":5590},[5429,13247,6031],{"class":5446},[5429,13249,13250],{"class":5590}," && ",[5429,13252,10204],{"class":5596},[5429,13254,5209],{"class":5590},[5429,13256,13257],{"class":5596},"confidentialityLevel",[5429,13259,13260],{"class":5590}," \u003C= ",[5429,13262,8099],{"class":5521},[5429,13264,6092],{"class":5590},[5429,13266,13267,13269,13271],{"class":5431,"line":6196},[5429,13268,6097],{"class":5579},[5429,13270,6100],{"class":5469},[5429,13272,5606],{"class":5590},[5429,13274,13275],{"class":5431,"line":6214},[5429,13276,6110],{"class":5590},[5429,13278,13279],{"class":5431,"line":6234},[5429,13280,5454],{"emptyLinePlaceholder":5453},[5429,13282,13283],{"class":5431,"line":6239},[5429,13284,13285],{"class":5435},"    \u002F\u002F Правило 4: Адміністратори мають повні права\n",[5429,13287,13288,13290,13292,13294,13296,13298,13300,13302,13304,13307],{"class":5431,"line":6244},[5429,13289,6083],{"class":5579},[5429,13291,5260],{"class":5590},[5429,13293,13063],{"class":5596},[5429,13295,5209],{"class":5590},[5429,13297,5263],{"class":5596},[5429,13299,5209],{"class":5590},[5429,13301,10580],{"class":5442},[5429,13303,5975],{"class":5590},[5429,13305,13306],{"class":5446},"'admin'",[5429,13308,13309],{"class":5590},")) {\n",[5429,13311,13312,13314,13316],{"class":5431,"line":6276},[5429,13313,6097],{"class":5579},[5429,13315,6100],{"class":5469},[5429,13317,5606],{"class":5590},[5429,13319,13320],{"class":5431,"line":6281},[5429,13321,6110],{"class":5590},[5429,13323,13324],{"class":5431,"line":6293},[5429,13325,5454],{"emptyLinePlaceholder":5453},[5429,13327,13328],{"class":5431,"line":6306},[5429,13329,13330],{"class":5435},"    \u002F\u002F Правило 5: Експорт дозволений лише з підтвердженим email\n",[5429,13332,13333,13335,13337,13339,13341,13344,13347,13349,13351,13354],{"class":5431,"line":6311},[5429,13334,6083],{"class":5579},[5429,13336,5260],{"class":5590},[5429,13338,10191],{"class":5596},[5429,13340,6336],{"class":5590},[5429,13342,13343],{"class":5446},"'export'",[5429,13345,13346],{"class":5590}," && !",[5429,13348,13063],{"class":5596},[5429,13350,5209],{"class":5590},[5429,13352,13353],{"class":5596},"emailVerified",[5429,13355,6092],{"class":5590},[5429,13357,13358,13360,13362],{"class":5431,"line":6316},[5429,13359,6097],{"class":5579},[5429,13361,6298],{"class":5469},[5429,13363,5606],{"class":5590},[5429,13365,13366],{"class":5431,"line":6322},[5429,13367,6110],{"class":5590},[5429,13369,13370],{"class":5431,"line":6348},[5429,13371,5454],{"emptyLinePlaceholder":5453},[5429,13373,13374],{"class":5431,"line":6357},[5429,13375,13376],{"class":5435},"    \u002F\u002F За замовчуванням — відхилити\n",[5429,13378,13379,13381,13383],{"class":5431,"line":6362},[5429,13380,6560],{"class":5579},[5429,13382,6298],{"class":5469},[5429,13384,5606],{"class":5590},[5429,13386,13387],{"class":5431,"line":6367},[5429,13388,6570],{"class":5590},[5429,13390,13391],{"class":5431,"line":6373},[5429,13392,5683],{"class":5590},[5089,13394,13395],{},[5099,13396,13397],{},"Guard для застосування ABAC політик:",[5420,13399,13401],{"className":5565,"code":13400,"language":5567,"meta":5425,"style":5425},"\u002F\u002F guards\u002Fabac-authorization.guard.ts\nimport { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs\u002Fcommon';\nimport { Reflector } from '@nestjs\u002Fcore';\nimport { AbacPolicy, AbacContext } from '..\u002Fdomain\u002Fpolicy.interface';\nimport { DocumentService } from '..\u002Fservices\u002Fdocument.service';\n\n@Injectable()\nexport class AbacAuthorizationGuard implements CanActivate {\n  constructor(\n    private reflector: Reflector,\n    private documentService: DocumentService,\n    private policies: AbacPolicy[] \u002F\u002F Список зареєстрованих політик\n  ) {}\n\n  async canActivate(context: ExecutionContext): Promise\u003Cboolean> {\n    const action = this.reflector.get\u003Cstring>('action', context.getHandler());\n\n    if (!action) {\n      return true;\n    }\n\n    const request = context.switchToHttp().getRequest();\n    const currentUser = request.user;\n    const resourceId = request.params.id;\n\n    if (!currentUser || !resourceId) {\n      throw new ForbiddenException('Missing authentication or resource ID');\n    }\n\n    \u002F\u002F Завантажуємо ресурс для отримання його атрибутів\n    const resource = await this.documentService.findById(resourceId);\n\n    if (!resource) {\n      return false;\n    }\n\n    \u002F\u002F Формуємо контекст для оцінки політик\n    const abacContext: AbacContext = {\n      subject: {\n        userId: currentUser.sub,\n        email: currentUser.email,\n        roles: currentUser.roles || [],\n        department: currentUser.department,\n        emailVerified: currentUser.email_verified,\n      },\n      resource: {\n        id: resource.id,\n        type: resource.type,\n        ownerId: resource.ownerId,\n        confidentialityLevel: resource.confidentialityLevel,\n      },\n      action: action,\n      environment: {\n        time: new Date(),\n        ipAddress: request.ip,\n        userAgent: request.headers['user-agent'],\n      },\n    };\n\n    \u002F\u002F Оцінюємо всі політики — доступ дозволяється, якщо хоча б одна політика повертає true\n    const evaluations = await Promise.all(\n      this.policies.map(policy => policy.evaluate(abacContext))\n    );\n\n    const isAllowed = evaluations.some(result => result === true);\n\n    if (!isAllowed) {\n      throw new ForbiddenException(\n        `Access denied: no policy permits ${action} operation on this resource`\n      );\n    }\n\n    return true;\n  }\n}\n",[5231,13402,13403,13408,13436,13452,13472,13488,13492,13500,13515,13521,13533,13545,13562,13566,13570,13594,13632,13636,13646,13654,13658,13662,13682,13698,13719,13723,13738,13753,13757,13761,13766,13793,13797,13807,13815,13819,13823,13828,13842,13849,13862,13876,13890,13904,13918,13923,13930,13943,13957,13970,13983,13987,13996,14003,14016,14030,14050,14054,14059,14063,14068,14087,14122,14126,14130,14160,14164,14175,14185,14199,14203,14207,14211,14219,14223],{"__ignoreMap":5425},[5429,13404,13405],{"class":5431,"line":5432},[5429,13406,13407],{"class":5435},"\u002F\u002F guards\u002Fabac-authorization.guard.ts\n",[5429,13409,13410,13412,13414,13416,13418,13420,13422,13424,13426,13428,13430,13432,13434],{"class":5431,"line":5439},[5429,13411,5821],{"class":5579},[5429,13413,5824],{"class":5590},[5429,13415,5827],{"class":5596},[5429,13417,5234],{"class":5590},[5429,13419,5832],{"class":5596},[5429,13421,5234],{"class":5590},[5429,13423,5837],{"class":5596},[5429,13425,5234],{"class":5590},[5429,13427,5842],{"class":5596},[5429,13429,5845],{"class":5590},[5429,13431,5848],{"class":5579},[5429,13433,5851],{"class":5446},[5429,13435,5606],{"class":5590},[5429,13437,13438,13440,13442,13444,13446,13448,13450],{"class":5431,"line":5450},[5429,13439,5821],{"class":5579},[5429,13441,5824],{"class":5590},[5429,13443,5862],{"class":5596},[5429,13445,5845],{"class":5590},[5429,13447,5848],{"class":5579},[5429,13449,5869],{"class":5446},[5429,13451,5606],{"class":5590},[5429,13453,13454,13456,13458,13460,13462,13464,13466,13468,13470],{"class":5431,"line":5457},[5429,13455,5821],{"class":5579},[5429,13457,5824],{"class":5590},[5429,13459,12963],{"class":5596},[5429,13461,5234],{"class":5590},[5429,13463,12709],{"class":5596},[5429,13465,5845],{"class":5590},[5429,13467,5848],{"class":5579},[5429,13469,12974],{"class":5446},[5429,13471,5606],{"class":5590},[5429,13473,13474,13476,13478,13480,13482,13484,13486],{"class":5431,"line":5463},[5429,13475,5821],{"class":5579},[5429,13477,5824],{"class":5590},[5429,13479,5880],{"class":5596},[5429,13481,5845],{"class":5590},[5429,13483,5848],{"class":5579},[5429,13485,5887],{"class":5446},[5429,13487,5606],{"class":5590},[5429,13489,13490],{"class":5431,"line":5475},[5429,13491,5454],{"emptyLinePlaceholder":5453},[5429,13493,13494,13496,13498],{"class":5431,"line":5481},[5429,13495,5898],{"class":5590},[5429,13497,5827],{"class":5442},[5429,13499,5903],{"class":5590},[5429,13501,13502,13504,13506,13509,13511,13513],{"class":5431,"line":5487},[5429,13503,5580],{"class":5579},[5429,13505,5583],{"class":5469},[5429,13507,13508],{"class":5586}," AbacAuthorizationGuard",[5429,13510,5915],{"class":5469},[5429,13512,5918],{"class":5586},[5429,13514,5591],{"class":5590},[5429,13516,13517,13519],{"class":5431,"line":5493},[5429,13518,5925],{"class":5469},[5429,13520,5928],{"class":5590},[5429,13522,13523,13525,13527,13529,13531],{"class":5431,"line":5499},[5429,13524,5933],{"class":5469},[5429,13526,5936],{"class":5596},[5429,13528,5600],{"class":5590},[5429,13530,5862],{"class":5586},[5429,13532,5943],{"class":5590},[5429,13534,13535,13537,13539,13541,13543],{"class":5431,"line":5505},[5429,13536,5933],{"class":5469},[5429,13538,5950],{"class":5596},[5429,13540,5600],{"class":5590},[5429,13542,5880],{"class":5586},[5429,13544,5943],{"class":5590},[5429,13546,13547,13549,13552,13554,13556,13559],{"class":5431,"line":5510},[5429,13548,5933],{"class":5469},[5429,13550,13551],{"class":5596}," policies",[5429,13553,5600],{"class":5590},[5429,13555,12963],{"class":5586},[5429,13557,13558],{"class":5590},"[] ",[5429,13560,13561],{"class":5435},"\u002F\u002F Список зареєстрованих політик\n",[5429,13563,13564],{"class":5431,"line":5516},[5429,13565,5960],{"class":5590},[5429,13567,13568],{"class":5431,"line":5527},[5429,13569,5454],{"emptyLinePlaceholder":5453},[5429,13571,13572,13574,13576,13578,13580,13582,13584,13586,13588,13590,13592],{"class":5431,"line":5532},[5429,13573,5969],{"class":5469},[5429,13575,5972],{"class":5442},[5429,13577,5975],{"class":5590},[5429,13579,5978],{"class":5596},[5429,13581,5600],{"class":5590},[5429,13583,5837],{"class":5586},[5429,13585,5985],{"class":5590},[5429,13587,5988],{"class":5586},[5429,13589,5991],{"class":5590},[5429,13591,5743],{"class":5586},[5429,13593,5996],{"class":5590},[5429,13595,13596,13598,13601,13603,13605,13607,13609,13611,13613,13615,13617,13619,13622,13624,13626,13628,13630],{"class":5431,"line":5538},[5429,13597,6006],{"class":5469},[5429,13599,13600],{"class":6009}," action",[5429,13602,6013],{"class":5590},[5429,13604,6016],{"class":5469},[5429,13606,5209],{"class":5590},[5429,13608,6021],{"class":5596},[5429,13610,5209],{"class":5590},[5429,13612,6026],{"class":5442},[5429,13614,5991],{"class":5590},[5429,13616,5603],{"class":5586},[5429,13618,8489],{"class":5590},[5429,13620,13621],{"class":5446},"'action'",[5429,13623,5234],{"class":5590},[5429,13625,5978],{"class":5596},[5429,13627,5209],{"class":5590},[5429,13629,6067],{"class":5442},[5429,13631,8502],{"class":5590},[5429,13633,13634],{"class":5431,"line":5547},[5429,13635,5454],{"emptyLinePlaceholder":5453},[5429,13637,13638,13640,13642,13644],{"class":5431,"line":5748},[5429,13639,6083],{"class":5579},[5429,13641,6086],{"class":5590},[5429,13643,10191],{"class":5596},[5429,13645,6092],{"class":5590},[5429,13647,13648,13650,13652],{"class":5431,"line":5760},[5429,13649,6097],{"class":5579},[5429,13651,6100],{"class":5469},[5429,13653,5606],{"class":5590},[5429,13655,13656],{"class":5431,"line":5772},[5429,13657,6110],{"class":5590},[5429,13659,13660],{"class":5431,"line":5787},[5429,13661,5454],{"emptyLinePlaceholder":5453},[5429,13663,13664,13666,13668,13670,13672,13674,13676,13678,13680],{"class":5431,"line":5799},[5429,13665,6006],{"class":5469},[5429,13667,6123],{"class":6009},[5429,13669,6013],{"class":5590},[5429,13671,5978],{"class":5596},[5429,13673,5209],{"class":5590},[5429,13675,6132],{"class":5442},[5429,13677,6135],{"class":5590},[5429,13679,6138],{"class":5442},[5429,13681,6141],{"class":5590},[5429,13683,13684,13686,13688,13690,13692,13694,13696],{"class":5431,"line":6113},[5429,13685,6006],{"class":5469},[5429,13687,6149],{"class":6009},[5429,13689,6013],{"class":5590},[5429,13691,6154],{"class":5596},[5429,13693,5209],{"class":5590},[5429,13695,6159],{"class":5596},[5429,13697,5606],{"class":5590},[5429,13699,13700,13702,13705,13707,13709,13711,13713,13715,13717],{"class":5431,"line":6118},[5429,13701,6006],{"class":5469},[5429,13703,13704],{"class":6009}," resourceId",[5429,13706,6013],{"class":5590},[5429,13708,6154],{"class":5596},[5429,13710,5209],{"class":5590},[5429,13712,6181],{"class":5596},[5429,13714,5209],{"class":5590},[5429,13716,6186],{"class":5596},[5429,13718,5606],{"class":5590},[5429,13720,13721],{"class":5431,"line":6144},[5429,13722,5454],{"emptyLinePlaceholder":5453},[5429,13724,13725,13727,13729,13731,13733,13736],{"class":5431,"line":6167},[5429,13726,6083],{"class":5579},[5429,13728,6086],{"class":5590},[5429,13730,6203],{"class":5596},[5429,13732,6206],{"class":5590},[5429,13734,13735],{"class":5596},"resourceId",[5429,13737,6092],{"class":5590},[5429,13739,13740,13742,13744,13746,13748,13751],{"class":5431,"line":6191},[5429,13741,6217],{"class":5579},[5429,13743,6220],{"class":5469},[5429,13745,6223],{"class":5442},[5429,13747,5975],{"class":5590},[5429,13749,13750],{"class":5446},"'Missing authentication or resource ID'",[5429,13752,6231],{"class":5590},[5429,13754,13755],{"class":5431,"line":6196},[5429,13756,6110],{"class":5590},[5429,13758,13759],{"class":5431,"line":6214},[5429,13760,5454],{"emptyLinePlaceholder":5453},[5429,13762,13763],{"class":5431,"line":6234},[5429,13764,13765],{"class":5435},"    \u002F\u002F Завантажуємо ресурс для отримання його атрибутів\n",[5429,13767,13768,13770,13773,13775,13777,13779,13781,13783,13785,13787,13789,13791],{"class":5431,"line":6239},[5429,13769,6006],{"class":5469},[5429,13771,13772],{"class":6009}," resource",[5429,13774,6013],{"class":5590},[5429,13776,6254],{"class":5579},[5429,13778,6257],{"class":5469},[5429,13780,5209],{"class":5590},[5429,13782,6262],{"class":5596},[5429,13784,5209],{"class":5590},[5429,13786,6267],{"class":5442},[5429,13788,5975],{"class":5590},[5429,13790,13735],{"class":5596},[5429,13792,6231],{"class":5590},[5429,13794,13795],{"class":5431,"line":6244},[5429,13796,5454],{"emptyLinePlaceholder":5453},[5429,13798,13799,13801,13803,13805],{"class":5431,"line":6276},[5429,13800,6083],{"class":5579},[5429,13802,6086],{"class":5590},[5429,13804,10204],{"class":5596},[5429,13806,6092],{"class":5590},[5429,13808,13809,13811,13813],{"class":5431,"line":6281},[5429,13810,6097],{"class":5579},[5429,13812,6298],{"class":5469},[5429,13814,5606],{"class":5590},[5429,13816,13817],{"class":5431,"line":6293},[5429,13818,6110],{"class":5590},[5429,13820,13821],{"class":5431,"line":6306},[5429,13822,5454],{"emptyLinePlaceholder":5453},[5429,13824,13825],{"class":5431,"line":6311},[5429,13826,13827],{"class":5435},"    \u002F\u002F Формуємо контекст для оцінки політик\n",[5429,13829,13830,13832,13835,13837,13839],{"class":5431,"line":6316},[5429,13831,6006],{"class":5469},[5429,13833,13834],{"class":6009}," abacContext",[5429,13836,5600],{"class":5590},[5429,13838,12709],{"class":5586},[5429,13840,13841],{"class":5590}," = {\n",[5429,13843,13844,13847],{"class":5431,"line":6322},[5429,13845,13846],{"class":5596},"      subject:",[5429,13848,5591],{"class":5590},[5429,13850,13851,13854,13856,13858,13860],{"class":5431,"line":6348},[5429,13852,13853],{"class":5596},"        userId:",[5429,13855,6149],{"class":5596},[5429,13857,5209],{"class":5590},[5429,13859,6343],{"class":5596},[5429,13861,5943],{"class":5590},[5429,13863,13864,13867,13869,13871,13874],{"class":5431,"line":6357},[5429,13865,13866],{"class":5596},"        email:",[5429,13868,6149],{"class":5596},[5429,13870,5209],{"class":5590},[5429,13872,13873],{"class":5596},"email",[5429,13875,5943],{"class":5590},[5429,13877,13878,13881,13883,13885,13887],{"class":5431,"line":6362},[5429,13879,13880],{"class":5596},"        roles:",[5429,13882,6149],{"class":5596},[5429,13884,5209],{"class":5590},[5429,13886,5263],{"class":5596},[5429,13888,13889],{"class":5590}," || [],\n",[5429,13891,13892,13895,13897,13899,13902],{"class":5431,"line":6367},[5429,13893,13894],{"class":5596},"        department:",[5429,13896,6149],{"class":5596},[5429,13898,5209],{"class":5590},[5429,13900,13901],{"class":5596},"department",[5429,13903,5943],{"class":5590},[5429,13905,13906,13909,13911,13913,13916],{"class":5431,"line":6373},[5429,13907,13908],{"class":5596},"        emailVerified:",[5429,13910,6149],{"class":5596},[5429,13912,5209],{"class":5590},[5429,13914,13915],{"class":5596},"email_verified",[5429,13917,5943],{"class":5590},[5429,13919,13920],{"class":5431,"line":6420},[5429,13921,13922],{"class":5590},"      },\n",[5429,13924,13925,13928],{"class":5431,"line":6425},[5429,13926,13927],{"class":5596},"      resource:",[5429,13929,5591],{"class":5590},[5429,13931,13932,13935,13937,13939,13941],{"class":5431,"line":6437},[5429,13933,13934],{"class":5596},"        id:",[5429,13936,13772],{"class":5596},[5429,13938,5209],{"class":5590},[5429,13940,6186],{"class":5596},[5429,13942,5943],{"class":5590},[5429,13944,13945,13948,13950,13952,13955],{"class":5431,"line":6453},[5429,13946,13947],{"class":5596},"        type:",[5429,13949,13772],{"class":5596},[5429,13951,5209],{"class":5590},[5429,13953,13954],{"class":5596},"type",[5429,13956,5943],{"class":5590},[5429,13958,13959,13962,13964,13966,13968],{"class":5431,"line":6458},[5429,13960,13961],{"class":5596},"        ownerId:",[5429,13963,13772],{"class":5596},[5429,13965,5209],{"class":5590},[5429,13967,6333],{"class":5596},[5429,13969,5943],{"class":5590},[5429,13971,13972,13975,13977,13979,13981],{"class":5431,"line":6463},[5429,13973,13974],{"class":5596},"        confidentialityLevel:",[5429,13976,13772],{"class":5596},[5429,13978,5209],{"class":5590},[5429,13980,13257],{"class":5596},[5429,13982,5943],{"class":5590},[5429,13984,13985],{"class":5431,"line":6469},[5429,13986,13922],{"class":5590},[5429,13988,13989,13992,13994],{"class":5431,"line":6496},[5429,13990,13991],{"class":5596},"      action:",[5429,13993,13600],{"class":5596},[5429,13995,5943],{"class":5590},[5429,13997,13998,14001],{"class":5431,"line":6501},[5429,13999,14000],{"class":5596},"      environment:",[5429,14002,5591],{"class":5590},[5429,14004,14005,14008,14010,14013],{"class":5431,"line":6513},[5429,14006,14007],{"class":5596},"        time:",[5429,14009,6220],{"class":5469},[5429,14011,14012],{"class":5442}," Date",[5429,14014,14015],{"class":5590},"(),\n",[5429,14017,14018,14021,14023,14025,14028],{"class":5431,"line":6524},[5429,14019,14020],{"class":5596},"        ipAddress:",[5429,14022,6123],{"class":5596},[5429,14024,5209],{"class":5590},[5429,14026,14027],{"class":5596},"ip",[5429,14029,5943],{"class":5590},[5429,14031,14032,14035,14037,14039,14042,14044,14047],{"class":5431,"line":6541},[5429,14033,14034],{"class":5596},"        userAgent:",[5429,14036,6123],{"class":5596},[5429,14038,5209],{"class":5590},[5429,14040,14041],{"class":5596},"headers",[5429,14043,8758],{"class":5590},[5429,14045,14046],{"class":5446},"'user-agent'",[5429,14048,14049],{"class":5590},"],\n",[5429,14051,14052],{"class":5431,"line":6547},[5429,14053,13922],{"class":5590},[5429,14055,14056],{"class":5431,"line":6552},[5429,14057,14058],{"class":5590},"    };\n",[5429,14060,14061],{"class":5431,"line":6557},[5429,14062,5454],{"emptyLinePlaceholder":5453},[5429,14064,14065],{"class":5431,"line":6567},[5429,14066,14067],{"class":5435},"    \u002F\u002F Оцінюємо всі політики — доступ дозволяється, якщо хоча б одна політика повертає true\n",[5429,14069,14070,14072,14075,14077,14079,14081,14083,14085],{"class":5431,"line":6573},[5429,14071,6006],{"class":5469},[5429,14073,14074],{"class":6009}," evaluations",[5429,14076,6013],{"class":5590},[5429,14078,6254],{"class":5579},[5429,14080,10655],{"class":5586},[5429,14082,5209],{"class":5590},[5429,14084,10660],{"class":5442},[5429,14086,5928],{"class":5590},[5429,14088,14089,14092,14094,14097,14099,14101,14103,14105,14107,14110,14112,14115,14117,14120],{"class":5431,"line":6578},[5429,14090,14091],{"class":5469},"      this",[5429,14093,5209],{"class":5590},[5429,14095,14096],{"class":5596},"policies",[5429,14098,5209],{"class":5590},[5429,14100,10546],{"class":5442},[5429,14102,5975],{"class":5590},[5429,14104,12376],{"class":5596},[5429,14106,6399],{"class":5469},[5429,14108,14109],{"class":5596}," policy",[5429,14111,5209],{"class":5590},[5429,14113,14114],{"class":5442},"evaluate",[5429,14116,5975],{"class":5590},[5429,14118,14119],{"class":5596},"abacContext",[5429,14121,10695],{"class":5590},[5429,14123,14124],{"class":5431,"line":6589},[5429,14125,6074],{"class":5590},[5429,14127,14128],{"class":5431,"line":6601},[5429,14129,5454],{"emptyLinePlaceholder":5453},[5429,14131,14132,14134,14137,14139,14142,14144,14146,14148,14150,14152,14154,14156,14158],{"class":5431,"line":6624},[5429,14133,6006],{"class":5469},[5429,14135,14136],{"class":6009}," isAllowed",[5429,14138,6013],{"class":5590},[5429,14140,14141],{"class":5596},"evaluations",[5429,14143,5209],{"class":5590},[5429,14145,10714],{"class":5442},[5429,14147,5975],{"class":5590},[5429,14149,10719],{"class":5596},[5429,14151,6399],{"class":5469},[5429,14153,10724],{"class":5596},[5429,14155,6336],{"class":5590},[5429,14157,10729],{"class":5469},[5429,14159,6231],{"class":5590},[5429,14161,14162],{"class":5431,"line":6634},[5429,14163,5454],{"emptyLinePlaceholder":5453},[5429,14165,14166,14168,14170,14173],{"class":5431,"line":6647},[5429,14167,6083],{"class":5579},[5429,14169,6086],{"class":5590},[5429,14171,14172],{"class":5596},"isAllowed",[5429,14174,6092],{"class":5590},[5429,14176,14177,14179,14181,14183],{"class":5431,"line":6659},[5429,14178,6217],{"class":5579},[5429,14180,6220],{"class":5469},[5429,14182,6223],{"class":5442},[5429,14184,5928],{"class":5590},[5429,14186,14187,14190,14192,14194,14196],{"class":5431,"line":6674},[5429,14188,14189],{"class":5446},"        `Access denied: no policy permits ",[5429,14191,6530],{"class":5469},[5429,14193,10191],{"class":5596},[5429,14195,6535],{"class":5469},[5429,14197,14198],{"class":5446}," operation on this resource`\n",[5429,14200,14201],{"class":5431,"line":6684},[5429,14202,6544],{"class":5590},[5429,14204,14205],{"class":5431,"line":6698},[5429,14206,6110],{"class":5590},[5429,14208,14209],{"class":5431,"line":6708},[5429,14210,5454],{"emptyLinePlaceholder":5453},[5429,14212,14213,14215,14217],{"class":5431,"line":6722},[5429,14214,6560],{"class":5579},[5429,14216,6100],{"class":5469},[5429,14218,5606],{"class":5590},[5429,14220,14221],{"class":5431,"line":6732},[5429,14222,6570],{"class":5590},[5429,14224,14225],{"class":5431,"line":6746},[5429,14226,5683],{"class":5590},[5089,14228,14229],{},[5099,14230,14231],{},"Декоратор для вказівки дії:",[5420,14233,14235],{"className":5565,"code":14234,"language":5567,"meta":5425,"style":5425},"\u002F\u002F decorators\u002Frequire-action.decorator.ts\nimport { SetMetadata } from '@nestjs\u002Fcommon';\n\nexport const RequireAction = (action: string) => SetMetadata('action', action);\n",[5231,14236,14237,14242,14258,14262],{"__ignoreMap":5425},[5429,14238,14239],{"class":5431,"line":5432},[5429,14240,14241],{"class":5435},"\u002F\u002F decorators\u002Frequire-action.decorator.ts\n",[5429,14243,14244,14246,14248,14250,14252,14254,14256],{"class":5431,"line":5439},[5429,14245,5821],{"class":5579},[5429,14247,5824],{"class":5590},[5429,14249,6799],{"class":5596},[5429,14251,5845],{"class":5590},[5429,14253,5848],{"class":5579},[5429,14255,5851],{"class":5446},[5429,14257,5606],{"class":5590},[5429,14259,14260],{"class":5431,"line":5450},[5429,14261,5454],{"emptyLinePlaceholder":5453},[5429,14263,14264,14266,14268,14271,14273,14275,14277,14279,14281,14284,14287,14289,14291,14293,14295],{"class":5431,"line":5457},[5429,14265,5580],{"class":5579},[5429,14267,6818],{"class":5469},[5429,14269,14270],{"class":5442}," RequireAction",[5429,14272,6824],{"class":5590},[5429,14274,10191],{"class":5596},[5429,14276,5600],{"class":5590},[5429,14278,5603],{"class":5586},[5429,14280,6845],{"class":5590},[5429,14282,14283],{"class":5469},"=>",[5429,14285,14286],{"class":5442}," SetMetadata",[5429,14288,5975],{"class":5590},[5429,14290,13621],{"class":5446},[5429,14292,5234],{"class":5590},[5429,14294,10191],{"class":5596},[5429,14296,6231],{"class":5590},[5089,14298,14299],{},[5099,14300,14301],{},"Контролер із застосуванням ABAC:",[5420,14303,14305],{"className":5565,"code":14304,"language":5567,"meta":5425,"style":5425},"\u002F\u002F controllers\u002Fdocuments.controller.ts\nimport { Controller, Get, Put, Delete, Post, Param, Body, UseGuards } from '@nestjs\u002Fcommon';\nimport { AuthGuard } from '..\u002Fguards\u002Fauth.guard';\nimport { AbacAuthorizationGuard } from '..\u002Fguards\u002Fabac-authorization.guard';\nimport { RequireAction } from '..\u002Fdecorators\u002Frequire-action.decorator';\n\n@Controller('documents')\n@UseGuards(AuthGuard, AbacAuthorizationGuard)\nexport class DocumentsController {\n  constructor(private documentService: DocumentService) {}\n\n  @Get(':id')\n  @RequireAction('read')\n  async getDocument(@Param('id') id: string) {\n    return this.documentService.findById(id);\n  }\n\n  @Put(':id')\n  @RequireAction('write')\n  async updateDocument(@Param('id') id: string, @Body() updateDto: UpdateDocumentDto) {\n    return this.documentService.update(id, updateDto);\n  }\n\n  @Delete(':id')\n  @RequireAction('delete')\n  async deleteDocument(@Param('id') id: string) {\n    return this.documentService.delete(id);\n  }\n\n  @Post(':id\u002Fexport')\n  @RequireAction('export')\n  async exportDocument(@Param('id') id: string) {\n    return this.documentService.exportToPdf(id);\n  }\n}\n",[5231,14306,14307,14311,14355,14371,14389,14407,14411,14423,14439,14449,14465,14469,14481,14493,14517,14537,14541,14545,14557,14569,14606,14630,14634,14638,14650,14662,14686,14706,14710,14714,14727,14739,14764,14785,14789],{"__ignoreMap":5425},[5429,14308,14309],{"class":5431,"line":5432},[5429,14310,6879],{"class":5435},[5429,14312,14313,14315,14317,14319,14321,14323,14325,14327,14329,14331,14333,14335,14337,14339,14341,14343,14345,14347,14349,14351,14353],{"class":5431,"line":5439},[5429,14314,5821],{"class":5579},[5429,14316,5824],{"class":5590},[5429,14318,6888],{"class":5596},[5429,14320,5234],{"class":5590},[5429,14322,6893],{"class":5596},[5429,14324,5234],{"class":5590},[5429,14326,6898],{"class":5596},[5429,14328,5234],{"class":5590},[5429,14330,6903],{"class":5596},[5429,14332,5234],{"class":5590},[5429,14334,6908],{"class":5596},[5429,14336,5234],{"class":5590},[5429,14338,6913],{"class":5596},[5429,14340,5234],{"class":5590},[5429,14342,6918],{"class":5596},[5429,14344,5234],{"class":5590},[5429,14346,6923],{"class":5596},[5429,14348,5845],{"class":5590},[5429,14350,5848],{"class":5579},[5429,14352,5851],{"class":5446},[5429,14354,5606],{"class":5590},[5429,14356,14357,14359,14361,14363,14365,14367,14369],{"class":5431,"line":5450},[5429,14358,5821],{"class":5579},[5429,14360,5824],{"class":5590},[5429,14362,6940],{"class":5596},[5429,14364,5845],{"class":5590},[5429,14366,5848],{"class":5579},[5429,14368,6947],{"class":5446},[5429,14370,5606],{"class":5590},[5429,14372,14373,14375,14377,14380,14382,14384,14387],{"class":5431,"line":5457},[5429,14374,5821],{"class":5579},[5429,14376,5824],{"class":5590},[5429,14378,14379],{"class":5596},"AbacAuthorizationGuard",[5429,14381,5845],{"class":5590},[5429,14383,5848],{"class":5579},[5429,14385,14386],{"class":5446}," '..\u002Fguards\u002Fabac-authorization.guard'",[5429,14388,5606],{"class":5590},[5429,14390,14391,14393,14395,14398,14400,14402,14405],{"class":5431,"line":5463},[5429,14392,5821],{"class":5579},[5429,14394,5824],{"class":5590},[5429,14396,14397],{"class":5596},"RequireAction",[5429,14399,5845],{"class":5590},[5429,14401,5848],{"class":5579},[5429,14403,14404],{"class":5446}," '..\u002Fdecorators\u002Frequire-action.decorator'",[5429,14406,5606],{"class":5590},[5429,14408,14409],{"class":5431,"line":5475},[5429,14410,5454],{"emptyLinePlaceholder":5453},[5429,14412,14413,14415,14417,14419,14421],{"class":5431,"line":5481},[5429,14414,5898],{"class":5590},[5429,14416,6888],{"class":5442},[5429,14418,5975],{"class":5590},[5429,14420,7018],{"class":5446},[5429,14422,7021],{"class":5590},[5429,14424,14425,14427,14429,14431,14433,14435,14437],{"class":5431,"line":5487},[5429,14426,5898],{"class":5590},[5429,14428,6923],{"class":5442},[5429,14430,5975],{"class":5590},[5429,14432,6940],{"class":5596},[5429,14434,5234],{"class":5590},[5429,14436,14379],{"class":5596},[5429,14438,7021],{"class":5590},[5429,14440,14441,14443,14445,14447],{"class":5431,"line":5493},[5429,14442,5580],{"class":5579},[5429,14444,5583],{"class":5469},[5429,14446,7046],{"class":5586},[5429,14448,5591],{"class":5590},[5429,14450,14451,14453,14455,14457,14459,14461,14463],{"class":5431,"line":5499},[5429,14452,5925],{"class":5469},[5429,14454,5975],{"class":5590},[5429,14456,7057],{"class":5469},[5429,14458,5950],{"class":5596},[5429,14460,5600],{"class":5590},[5429,14462,5880],{"class":5586},[5429,14464,7066],{"class":5590},[5429,14466,14467],{"class":5431,"line":5505},[5429,14468,5454],{"emptyLinePlaceholder":5453},[5429,14470,14471,14473,14475,14477,14479],{"class":5431,"line":5510},[5429,14472,7080],{"class":5590},[5429,14474,6893],{"class":5442},[5429,14476,5975],{"class":5590},[5429,14478,7087],{"class":5446},[5429,14480,7021],{"class":5590},[5429,14482,14483,14485,14487,14489,14491],{"class":5431,"line":5516},[5429,14484,7080],{"class":5590},[5429,14486,14397],{"class":5442},[5429,14488,5975],{"class":5590},[5429,14490,6031],{"class":5446},[5429,14492,7021],{"class":5590},[5429,14494,14495,14497,14499,14501,14503,14505,14507,14509,14511,14513,14515],{"class":5431,"line":5527},[5429,14496,5969],{"class":5469},[5429,14498,7108],{"class":5442},[5429,14500,7111],{"class":5590},[5429,14502,6913],{"class":5442},[5429,14504,5975],{"class":5590},[5429,14506,7118],{"class":5446},[5429,14508,6845],{"class":5590},[5429,14510,6186],{"class":5596},[5429,14512,5600],{"class":5590},[5429,14514,5603],{"class":5586},[5429,14516,6092],{"class":5590},[5429,14518,14519,14521,14523,14525,14527,14529,14531,14533,14535],{"class":5431,"line":5532},[5429,14520,6560],{"class":5579},[5429,14522,6257],{"class":5469},[5429,14524,5209],{"class":5590},[5429,14526,6262],{"class":5596},[5429,14528,5209],{"class":5590},[5429,14530,6267],{"class":5442},[5429,14532,5975],{"class":5590},[5429,14534,6186],{"class":5596},[5429,14536,6231],{"class":5590},[5429,14538,14539],{"class":5431,"line":5538},[5429,14540,6570],{"class":5590},[5429,14542,14543],{"class":5431,"line":5547},[5429,14544,5454],{"emptyLinePlaceholder":5453},[5429,14546,14547,14549,14551,14553,14555],{"class":5431,"line":5748},[5429,14548,7080],{"class":5590},[5429,14550,6898],{"class":5442},[5429,14552,5975],{"class":5590},[5429,14554,7087],{"class":5446},[5429,14556,7021],{"class":5590},[5429,14558,14559,14561,14563,14565,14567],{"class":5431,"line":5760},[5429,14560,7080],{"class":5590},[5429,14562,14397],{"class":5442},[5429,14564,5975],{"class":5590},[5429,14566,6037],{"class":5446},[5429,14568,7021],{"class":5590},[5429,14570,14571,14573,14575,14577,14579,14581,14583,14585,14587,14589,14591,14593,14595,14597,14599,14601,14604],{"class":5431,"line":5772},[5429,14572,5969],{"class":5469},[5429,14574,7192],{"class":5442},[5429,14576,7111],{"class":5590},[5429,14578,6913],{"class":5442},[5429,14580,5975],{"class":5590},[5429,14582,7118],{"class":5446},[5429,14584,6845],{"class":5590},[5429,14586,6186],{"class":5596},[5429,14588,5600],{"class":5590},[5429,14590,5603],{"class":5586},[5429,14592,11875],{"class":5590},[5429,14594,6918],{"class":5442},[5429,14596,7224],{"class":5590},[5429,14598,7227],{"class":5596},[5429,14600,5600],{"class":5590},[5429,14602,14603],{"class":5586},"UpdateDocumentDto",[5429,14605,6092],{"class":5590},[5429,14607,14608,14610,14612,14614,14616,14618,14620,14622,14624,14626,14628],{"class":5431,"line":5787},[5429,14609,6560],{"class":5579},[5429,14611,6257],{"class":5469},[5429,14613,5209],{"class":5590},[5429,14615,6262],{"class":5596},[5429,14617,5209],{"class":5590},[5429,14619,7252],{"class":5442},[5429,14621,5975],{"class":5590},[5429,14623,6186],{"class":5596},[5429,14625,5234],{"class":5590},[5429,14627,7227],{"class":5596},[5429,14629,6231],{"class":5590},[5429,14631,14632],{"class":5431,"line":5799},[5429,14633,6570],{"class":5590},[5429,14635,14636],{"class":5431,"line":6113},[5429,14637,5454],{"emptyLinePlaceholder":5453},[5429,14639,14640,14642,14644,14646,14648],{"class":5431,"line":6118},[5429,14641,7080],{"class":5590},[5429,14643,6903],{"class":5442},[5429,14645,5975],{"class":5590},[5429,14647,7087],{"class":5446},[5429,14649,7021],{"class":5590},[5429,14651,14652,14654,14656,14658,14660],{"class":5431,"line":6144},[5429,14653,7080],{"class":5590},[5429,14655,14397],{"class":5442},[5429,14657,5975],{"class":5590},[5429,14659,6042],{"class":5446},[5429,14661,7021],{"class":5590},[5429,14663,14664,14666,14668,14670,14672,14674,14676,14678,14680,14682,14684],{"class":5431,"line":6167},[5429,14665,5969],{"class":5469},[5429,14667,7306],{"class":5442},[5429,14669,7111],{"class":5590},[5429,14671,6913],{"class":5442},[5429,14673,5975],{"class":5590},[5429,14675,7118],{"class":5446},[5429,14677,6845],{"class":5590},[5429,14679,6186],{"class":5596},[5429,14681,5600],{"class":5590},[5429,14683,5603],{"class":5586},[5429,14685,6092],{"class":5590},[5429,14687,14688,14690,14692,14694,14696,14698,14700,14702,14704],{"class":5431,"line":6191},[5429,14689,6560],{"class":5579},[5429,14691,6257],{"class":5469},[5429,14693,5209],{"class":5590},[5429,14695,6262],{"class":5596},[5429,14697,5209],{"class":5590},[5429,14699,7339],{"class":5442},[5429,14701,5975],{"class":5590},[5429,14703,6186],{"class":5596},[5429,14705,6231],{"class":5590},[5429,14707,14708],{"class":5431,"line":6196},[5429,14709,6570],{"class":5590},[5429,14711,14712],{"class":5431,"line":6214},[5429,14713,5454],{"emptyLinePlaceholder":5453},[5429,14715,14716,14718,14720,14722,14725],{"class":5431,"line":6234},[5429,14717,7080],{"class":5590},[5429,14719,6908],{"class":5442},[5429,14721,5975],{"class":5590},[5429,14723,14724],{"class":5446},"':id\u002Fexport'",[5429,14726,7021],{"class":5590},[5429,14728,14729,14731,14733,14735,14737],{"class":5431,"line":6239},[5429,14730,7080],{"class":5590},[5429,14732,14397],{"class":5442},[5429,14734,5975],{"class":5590},[5429,14736,13343],{"class":5446},[5429,14738,7021],{"class":5590},[5429,14740,14741,14743,14746,14748,14750,14752,14754,14756,14758,14760,14762],{"class":5431,"line":6244},[5429,14742,5969],{"class":5469},[5429,14744,14745],{"class":5442}," exportDocument",[5429,14747,7111],{"class":5590},[5429,14749,6913],{"class":5442},[5429,14751,5975],{"class":5590},[5429,14753,7118],{"class":5446},[5429,14755,6845],{"class":5590},[5429,14757,6186],{"class":5596},[5429,14759,5600],{"class":5590},[5429,14761,5603],{"class":5586},[5429,14763,6092],{"class":5590},[5429,14765,14766,14768,14770,14772,14774,14776,14779,14781,14783],{"class":5431,"line":6276},[5429,14767,6560],{"class":5579},[5429,14769,6257],{"class":5469},[5429,14771,5209],{"class":5590},[5429,14773,6262],{"class":5596},[5429,14775,5209],{"class":5590},[5429,14777,14778],{"class":5442},"exportToPdf",[5429,14780,5975],{"class":5590},[5429,14782,6186],{"class":5596},[5429,14784,6231],{"class":5590},[5429,14786,14787],{"class":5431,"line":6281},[5429,14788,6570],{"class":5590},[5429,14790,14791],{"class":5431,"line":6293},[5429,14792,5683],{"class":5590},[5317,14794,14796],{"id":14795},"переваги-та-недоліки-abac","Переваги та недоліки ABAC",[5089,14798,14799],{},[5099,14800,7491],{},[5093,14802,14803,14809,14815,14821,14827],{},[5096,14804,14805,14808],{},[5099,14806,14807],{},"Максимальна гнучкість:"," здатність виражати складні багатофакторні правила, що враховують контекст виконання.",[5096,14810,14811,14814],{},[5099,14812,14813],{},"Динамічність:"," політики оцінюються під час виконання запиту, що дозволяє враховувати актуальний стан системи (час, місце, стан сесії).",[5096,14816,14817,14820],{},[5099,14818,14819],{},"Зменшення адміністративного навантаження:"," не потрібно створювати десятки ролей для покриття всіх комбінацій дозволів — достатньо визначити політики один раз.",[5096,14822,14823,14826],{},[5099,14824,14825],{},"Природна підтримка принципу найменших привілеїв:"," кожен запит оцінюється індивідуально, надаючи лише ті дозволи, що необхідні для конкретної операції.",[5096,14828,14829,14832],{},[5099,14830,14831],{},"Відповідність нормативним вимогам:"," GDPR, HIPAA, SOC 2 часто вимагають гранулярного контролю доступу з аудитом умов — ABAC ідеально підходить.",[5089,14834,14835],{},[5099,14836,7522],{},[5093,14838,14839,14845,14851,14857,14869],{},[5096,14840,14841,14844],{},[5099,14842,14843],{},"Висока складність реалізації:"," розробка та підтримка механізму оцінки політик вимагає значних інженерних зусиль.",[5096,14846,14847,14850],{},[5099,14848,14849],{},"Проблеми продуктивності:"," оцінка складних політик для кожного запиту може створювати затримки. Потрібне кешування результатів та оптимізація.",[5096,14852,14853,14856],{},[5099,14854,14855],{},"Складність налагодження:"," коли доступ несподівано відхиляється, важко зрозуміти, яке саме правило у політиці спрацювало. Потрібні розвинені інструменти аудиту та логування.",[5096,14858,14859,14862,14863,5260,14866,5242],{},[5099,14860,14861],{},"Ризик конфліктів політик:"," якщо одна політика дозволяє доступ, а інша — забороняє, система має визначити пріоритет. Зазвичай застосовується принцип ",[5099,14864,14865],{},"«Заборона перемагає»",[5194,14867,14868],{},"Deny Overrides",[5096,14870,14871,14874],{},[5099,14872,14873],{},"Крива навчання:"," команда повинна опанувати нову парадигму мислення про авторизацію, що може уповільнити початковий розвиток.",[9492,14876,14877,14883,14903],{},[5089,14878,14879,14882],{},[5099,14880,14881],{},"Стратегія комбінування дозволів:"," у системах з кількома політиками необхідно визначити, як комбінувати їхні результати. Найпоширеніші стратегії:",[5093,14884,14885,14891,14897],{},[5096,14886,14887,14890],{},[5099,14888,14889],{},"Permit Overrides:"," якщо хоча б одна політика дозволяє доступ — доступ надається (використовується у прикладі вище).",[5096,14892,14893,14896],{},[5099,14894,14895],{},"Deny Overrides:"," якщо хоча б одна політика забороняє доступ — доступ відхиляється (найбезпечніший варіант).",[5096,14898,14899,14902],{},[5099,14900,14901],{},"First Applicable:"," використовується результат першої політики, що дала однозначну відповідь.",[5089,14904,14905],{},"Вибір стратегії впливає на безпеку системи — обирайте обережно.",[5317,14907,14909],{"id":14908},"типові-сценарії-використання-abac","Типові сценарії використання ABAC",[5089,14911,14912],{},[5099,14913,14914],{},"Медичні інформаційні системи:",[5093,14916,14917],{},[5096,14918,14919],{},"Лікарі можуть переглядати записи лише призначених їм пацієнтів, лише з робочих станцій клініки, лише у робочі години.",[5089,14921,14922],{},[5099,14923,14924],{},"Фінансові системи:",[5093,14926,14927],{},[5096,14928,14929],{},"Аналітики можуть експортувати знеособлені фінансові дані, якщо мають активний дозвіл від комплаєнс-відділу, та лише до дати закінчення терміну дії дозволу.",[5089,14931,14932],{},[5099,14933,12284],{},[5093,14935,14936,14939],{},[5096,14937,14938],{},"AWS IAM Policies — JSON-документи, що визначають умови доступу на основі атрибутів IP, часу, MFA-статусу.",[5096,14940,14941],{},"Azure ABAC — контроль доступу до ресурсів Azure на основі тегів та атрибутів.",[5089,14943,14944],{},[5099,14945,14946],{},"Державні системи:",[5093,14948,14949],{},[5096,14950,14951,14952,14955],{},"Доступ до класифікованих документів з перевіркою рівня допуску, відділу, необхідності знати (",[5194,14953,14954],{},"need-to-know","), та контексту (місце, час, мета доступу).",[5125,14957],{},[5084,14959,14961],{"id":14960},"порівняльна-таблиця-моделей","Порівняльна таблиця моделей",[14963,14964,14965],"code-group",{},[5420,14966,14969],{"className":5565,"code":14967,"filename":14968,"language":5567,"meta":5425,"style":5425},"interface AccessControlModel {\n  name: string;\n  complexity: 'Low' | 'Medium' | 'High' | 'Very High';\n  flexibility: 'Low' | 'Medium' | 'High' | 'Very High';\n  adminOverhead: 'Low' | 'Medium' | 'High' | 'Very High';\n  performance: 'Excellent' | 'Good' | 'Fair' | 'Poor';\n  auditability: 'Poor' | 'Fair' | 'Good' | 'Excellent';\n  useCases: string[];\n}\n\nconst models: AccessControlModel[] = [\n  {\n    name: 'DAC',\n    complexity: 'Low',\n    flexibility: 'High',\n    adminOverhead: 'Low',\n    performance: 'Excellent',\n    auditability: 'Poor',\n    useCases: ['Файлові системи', 'Хмарні диски', 'Особисті документи']\n  },\n  {\n    name: 'MAC',\n    complexity: 'High',\n    flexibility: 'Low',\n    adminOverhead: 'Very High',\n    performance: 'Good',\n    auditability: 'Excellent',\n    useCases: ['Військові системи', 'Державна таємниця', 'Медичні записи (HIPAA)']\n  },\n  {\n    name: 'RBAC',\n    complexity: 'Medium',\n    flexibility: 'Medium',\n    adminOverhead: 'Medium',\n    performance: 'Good',\n    auditability: 'Good',\n    useCases: ['Корпоративні застосунки', 'CRM\u002FERP', 'GitHub\u002FGitLab']\n  },\n  {\n    name: 'ABAC',\n    complexity: 'Very High',\n    flexibility: 'Very High',\n    adminOverhead: 'High',\n    performance: 'Fair',\n    auditability: 'Good',\n    useCases: ['Медичні системи', 'Фінансові платформи', 'AWS IAM', 'Zero Trust архітектури']\n  }\n];\n","Порівняння характеристик",[5231,14970,14971,14981,14991,15018,15041,15064,15091,15114,15125,15129,15133,15149,15154,15164,15174,15184,15193,15203,15213,15237,15242,15246,15255,15263,15271,15280,15289,15297,15318,15322,15326,15335,15344,15352,15360,15368,15376,15397,15401,15405,15414,15422,15430,15438,15447,15455,15481,15485],{"__ignoreMap":5425},[5429,14972,14973,14976,14979],{"class":5431,"line":5432},[5429,14974,14975],{"class":5469},"interface",[5429,14977,14978],{"class":5586}," AccessControlModel",[5429,14980,5591],{"class":5590},[5429,14982,14983,14985,14987,14989],{"class":5431,"line":5439},[5429,14984,10047],{"class":5596},[5429,14986,5600],{"class":5590},[5429,14988,5603],{"class":5586},[5429,14990,5606],{"class":5590},[5429,14992,14993,14996,14998,15001,15003,15006,15008,15011,15013,15016],{"class":5431,"line":5450},[5429,14994,14995],{"class":5596},"  complexity",[5429,14997,5600],{"class":5590},[5429,14999,15000],{"class":5446},"'Low'",[5429,15002,6034],{"class":5590},[5429,15004,15005],{"class":5446},"'Medium'",[5429,15007,6034],{"class":5590},[5429,15009,15010],{"class":5446},"'High'",[5429,15012,6034],{"class":5590},[5429,15014,15015],{"class":5446},"'Very High'",[5429,15017,5606],{"class":5590},[5429,15019,15020,15023,15025,15027,15029,15031,15033,15035,15037,15039],{"class":5431,"line":5457},[5429,15021,15022],{"class":5596},"  flexibility",[5429,15024,5600],{"class":5590},[5429,15026,15000],{"class":5446},[5429,15028,6034],{"class":5590},[5429,15030,15005],{"class":5446},[5429,15032,6034],{"class":5590},[5429,15034,15010],{"class":5446},[5429,15036,6034],{"class":5590},[5429,15038,15015],{"class":5446},[5429,15040,5606],{"class":5590},[5429,15042,15043,15046,15048,15050,15052,15054,15056,15058,15060,15062],{"class":5431,"line":5463},[5429,15044,15045],{"class":5596},"  adminOverhead",[5429,15047,5600],{"class":5590},[5429,15049,15000],{"class":5446},[5429,15051,6034],{"class":5590},[5429,15053,15005],{"class":5446},[5429,15055,6034],{"class":5590},[5429,15057,15010],{"class":5446},[5429,15059,6034],{"class":5590},[5429,15061,15015],{"class":5446},[5429,15063,5606],{"class":5590},[5429,15065,15066,15069,15071,15074,15076,15079,15081,15084,15086,15089],{"class":5431,"line":5475},[5429,15067,15068],{"class":5596},"  performance",[5429,15070,5600],{"class":5590},[5429,15072,15073],{"class":5446},"'Excellent'",[5429,15075,6034],{"class":5590},[5429,15077,15078],{"class":5446},"'Good'",[5429,15080,6034],{"class":5590},[5429,15082,15083],{"class":5446},"'Fair'",[5429,15085,6034],{"class":5590},[5429,15087,15088],{"class":5446},"'Poor'",[5429,15090,5606],{"class":5590},[5429,15092,15093,15096,15098,15100,15102,15104,15106,15108,15110,15112],{"class":5431,"line":5481},[5429,15094,15095],{"class":5596},"  auditability",[5429,15097,5600],{"class":5590},[5429,15099,15088],{"class":5446},[5429,15101,6034],{"class":5590},[5429,15103,15083],{"class":5446},[5429,15105,6034],{"class":5590},[5429,15107,15078],{"class":5446},[5429,15109,6034],{"class":5590},[5429,15111,15073],{"class":5446},[5429,15113,5606],{"class":5590},[5429,15115,15116,15119,15121,15123],{"class":5431,"line":5487},[5429,15117,15118],{"class":5596},"  useCases",[5429,15120,5600],{"class":5590},[5429,15122,5603],{"class":5586},[5429,15124,5678],{"class":5590},[5429,15126,15127],{"class":5431,"line":5493},[5429,15128,5683],{"class":5590},[5429,15130,15131],{"class":5431,"line":5499},[5429,15132,5454],{"emptyLinePlaceholder":5453},[5429,15134,15135,15138,15141,15143,15146],{"class":5431,"line":5505},[5429,15136,15137],{"class":5469},"const",[5429,15139,15140],{"class":6009}," models",[5429,15142,5600],{"class":5590},[5429,15144,15145],{"class":5586},"AccessControlModel",[5429,15147,15148],{"class":5590},"[] = [\n",[5429,15150,15151],{"class":5431,"line":5510},[5429,15152,15153],{"class":5590},"  {\n",[5429,15155,15156,15159,15162],{"class":5431,"line":5516},[5429,15157,15158],{"class":5596},"    name:",[5429,15160,15161],{"class":5446}," 'DAC'",[5429,15163,5943],{"class":5590},[5429,15165,15166,15169,15172],{"class":5431,"line":5527},[5429,15167,15168],{"class":5596},"    complexity:",[5429,15170,15171],{"class":5446}," 'Low'",[5429,15173,5943],{"class":5590},[5429,15175,15176,15179,15182],{"class":5431,"line":5532},[5429,15177,15178],{"class":5596},"    flexibility:",[5429,15180,15181],{"class":5446}," 'High'",[5429,15183,5943],{"class":5590},[5429,15185,15186,15189,15191],{"class":5431,"line":5538},[5429,15187,15188],{"class":5596},"    adminOverhead:",[5429,15190,15171],{"class":5446},[5429,15192,5943],{"class":5590},[5429,15194,15195,15198,15201],{"class":5431,"line":5547},[5429,15196,15197],{"class":5596},"    performance:",[5429,15199,15200],{"class":5446}," 'Excellent'",[5429,15202,5943],{"class":5590},[5429,15204,15205,15208,15211],{"class":5431,"line":5748},[5429,15206,15207],{"class":5596},"    auditability:",[5429,15209,15210],{"class":5446}," 'Poor'",[5429,15212,5943],{"class":5590},[5429,15214,15215,15218,15221,15224,15226,15229,15231,15234],{"class":5431,"line":5760},[5429,15216,15217],{"class":5596},"    useCases:",[5429,15219,15220],{"class":5590}," [",[5429,15222,15223],{"class":5446},"'Файлові системи'",[5429,15225,5234],{"class":5590},[5429,15227,15228],{"class":5446},"'Хмарні диски'",[5429,15230,5234],{"class":5590},[5429,15232,15233],{"class":5446},"'Особисті документи'",[5429,15235,15236],{"class":5590},"]\n",[5429,15238,15239],{"class":5431,"line":5772},[5429,15240,15241],{"class":5590},"  },\n",[5429,15243,15244],{"class":5431,"line":5787},[5429,15245,15153],{"class":5590},[5429,15247,15248,15250,15253],{"class":5431,"line":5799},[5429,15249,15158],{"class":5596},[5429,15251,15252],{"class":5446}," 'MAC'",[5429,15254,5943],{"class":5590},[5429,15256,15257,15259,15261],{"class":5431,"line":6113},[5429,15258,15168],{"class":5596},[5429,15260,15181],{"class":5446},[5429,15262,5943],{"class":5590},[5429,15264,15265,15267,15269],{"class":5431,"line":6118},[5429,15266,15178],{"class":5596},[5429,15268,15171],{"class":5446},[5429,15270,5943],{"class":5590},[5429,15272,15273,15275,15278],{"class":5431,"line":6144},[5429,15274,15188],{"class":5596},[5429,15276,15277],{"class":5446}," 'Very High'",[5429,15279,5943],{"class":5590},[5429,15281,15282,15284,15287],{"class":5431,"line":6167},[5429,15283,15197],{"class":5596},[5429,15285,15286],{"class":5446}," 'Good'",[5429,15288,5943],{"class":5590},[5429,15290,15291,15293,15295],{"class":5431,"line":6191},[5429,15292,15207],{"class":5596},[5429,15294,15200],{"class":5446},[5429,15296,5943],{"class":5590},[5429,15298,15299,15301,15303,15306,15308,15311,15313,15316],{"class":5431,"line":6196},[5429,15300,15217],{"class":5596},[5429,15302,15220],{"class":5590},[5429,15304,15305],{"class":5446},"'Військові системи'",[5429,15307,5234],{"class":5590},[5429,15309,15310],{"class":5446},"'Державна таємниця'",[5429,15312,5234],{"class":5590},[5429,15314,15315],{"class":5446},"'Медичні записи (HIPAA)'",[5429,15317,15236],{"class":5590},[5429,15319,15320],{"class":5431,"line":6214},[5429,15321,15241],{"class":5590},[5429,15323,15324],{"class":5431,"line":6234},[5429,15325,15153],{"class":5590},[5429,15327,15328,15330,15333],{"class":5431,"line":6239},[5429,15329,15158],{"class":5596},[5429,15331,15332],{"class":5446}," 'RBAC'",[5429,15334,5943],{"class":5590},[5429,15336,15337,15339,15342],{"class":5431,"line":6244},[5429,15338,15168],{"class":5596},[5429,15340,15341],{"class":5446}," 'Medium'",[5429,15343,5943],{"class":5590},[5429,15345,15346,15348,15350],{"class":5431,"line":6276},[5429,15347,15178],{"class":5596},[5429,15349,15341],{"class":5446},[5429,15351,5943],{"class":5590},[5429,15353,15354,15356,15358],{"class":5431,"line":6281},[5429,15355,15188],{"class":5596},[5429,15357,15341],{"class":5446},[5429,15359,5943],{"class":5590},[5429,15361,15362,15364,15366],{"class":5431,"line":6293},[5429,15363,15197],{"class":5596},[5429,15365,15286],{"class":5446},[5429,15367,5943],{"class":5590},[5429,15369,15370,15372,15374],{"class":5431,"line":6306},[5429,15371,15207],{"class":5596},[5429,15373,15286],{"class":5446},[5429,15375,5943],{"class":5590},[5429,15377,15378,15380,15382,15385,15387,15390,15392,15395],{"class":5431,"line":6311},[5429,15379,15217],{"class":5596},[5429,15381,15220],{"class":5590},[5429,15383,15384],{"class":5446},"'Корпоративні застосунки'",[5429,15386,5234],{"class":5590},[5429,15388,15389],{"class":5446},"'CRM\u002FERP'",[5429,15391,5234],{"class":5590},[5429,15393,15394],{"class":5446},"'GitHub\u002FGitLab'",[5429,15396,15236],{"class":5590},[5429,15398,15399],{"class":5431,"line":6316},[5429,15400,15241],{"class":5590},[5429,15402,15403],{"class":5431,"line":6322},[5429,15404,15153],{"class":5590},[5429,15406,15407,15409,15412],{"class":5431,"line":6348},[5429,15408,15158],{"class":5596},[5429,15410,15411],{"class":5446}," 'ABAC'",[5429,15413,5943],{"class":5590},[5429,15415,15416,15418,15420],{"class":5431,"line":6357},[5429,15417,15168],{"class":5596},[5429,15419,15277],{"class":5446},[5429,15421,5943],{"class":5590},[5429,15423,15424,15426,15428],{"class":5431,"line":6362},[5429,15425,15178],{"class":5596},[5429,15427,15277],{"class":5446},[5429,15429,5943],{"class":5590},[5429,15431,15432,15434,15436],{"class":5431,"line":6367},[5429,15433,15188],{"class":5596},[5429,15435,15181],{"class":5446},[5429,15437,5943],{"class":5590},[5429,15439,15440,15442,15445],{"class":5431,"line":6373},[5429,15441,15197],{"class":5596},[5429,15443,15444],{"class":5446}," 'Fair'",[5429,15446,5943],{"class":5590},[5429,15448,15449,15451,15453],{"class":5431,"line":6420},[5429,15450,15207],{"class":5596},[5429,15452,15286],{"class":5446},[5429,15454,5943],{"class":5590},[5429,15456,15457,15459,15461,15464,15466,15469,15471,15474,15476,15479],{"class":5431,"line":6425},[5429,15458,15217],{"class":5596},[5429,15460,15220],{"class":5590},[5429,15462,15463],{"class":5446},"'Медичні системи'",[5429,15465,5234],{"class":5590},[5429,15467,15468],{"class":5446},"'Фінансові платформи'",[5429,15470,5234],{"class":5590},[5429,15472,15473],{"class":5446},"'AWS IAM'",[5429,15475,5234],{"class":5590},[5429,15477,15478],{"class":5446},"'Zero Trust архітектури'",[5429,15480,15236],{"class":5590},[5429,15482,15483],{"class":5431,"line":6437},[5429,15484,6570],{"class":5590},[5429,15486,15487],{"class":5431,"line":6453},[5429,15488,15489],{"class":5590},"];\n",[15491,15492,15493,15515],"table",{},[15494,15495,15496],"thead",{},[15497,15498,15499,15503,15506,15509,15512],"tr",{},[15500,15501,15502],"th",{},"Характеристика",[15500,15504,15505],{},"DAC",[15500,15507,15508],{},"MAC",[15500,15510,15511],{},"RBAC",[15500,15513,15514],{},"ABAC",[15516,15517,15518,15538,15553,15572,15590,15608,15626],"tbody",{},[15497,15519,15520,15526,15529,15532,15535],{},[15521,15522,15523],"td",{},[5099,15524,15525],{},"Складність",[15521,15527,15528],{},"Низька",[15521,15530,15531],{},"Висока",[15521,15533,15534],{},"Середня",[15521,15536,15537],{},"Дуже висока",[15497,15539,15540,15545,15547,15549,15551],{},[15521,15541,15542],{},[5099,15543,15544],{},"Гнучкість",[15521,15546,15531],{},[15521,15548,15528],{},[15521,15550,15534],{},[15521,15552,15537],{},[15497,15554,15555,15560,15563,15566,15569],{},[15521,15556,15557],{},[5099,15558,15559],{},"Адміністрування",[15521,15561,15562],{},"Мінімальне",[15521,15564,15565],{},"Дуже складне",[15521,15567,15568],{},"Помірне",[15521,15570,15571],{},"Складне",[15497,15573,15574,15579,15582,15585,15587],{},[15521,15575,15576],{},[5099,15577,15578],{},"Продуктивність",[15521,15580,15581],{},"Відмінна",[15521,15583,15584],{},"Хороша",[15521,15586,15584],{},[15521,15588,15589],{},"Задовільна",[15497,15591,15592,15597,15600,15603,15606],{},[15521,15593,15594],{},[5099,15595,15596],{},"Аудит",[15521,15598,15599],{},"Слабкий",[15521,15601,15602],{},"Відмінний",[15521,15604,15605],{},"Хороший",[15521,15607,15605],{},[15497,15609,15610,15615,15618,15621,15624],{},[15521,15611,15612],{},[5099,15613,15614],{},"Централізація",[15521,15616,15617],{},"Децентралізована",[15521,15619,15620],{},"Повністю централізована",[15521,15622,15623],{},"Централізована",[15521,15625,15623],{},[15497,15627,15628,15633,15636,15638,15641],{},[15521,15629,15630],{},[5099,15631,15632],{},"Контекст",[15521,15634,15635],{},"Не підтримується",[15521,15637,15635],{},[15521,15639,15640],{},"Обмежений",[15521,15642,15643],{},"Повна підтримка",[5125,15645],{},[5084,15647,15649],{"id":15648},"критерії-вибору-моделі-авторизації","Критерії вибору моделі авторизації",[5089,15651,15652],{},"При виборі моделі контролю доступу для проєкту необхідно враховувати кілька ключових факторів:",[5317,15654,15656],{"id":15655},"фактор-1-вимоги-до-безпеки-та-комплаєнсу","Фактор 1: Вимоги до безпеки та комплаєнсу",[15658,15659,15660,15664,15674,15677,15681,15686,15689,15693,15698],"steps",{},[5317,15661,15663],{"id":15662},"низькі-вимоги-особисті-проєкти-стартапи-у-mvp-фазі","Низькі вимоги (особисті проєкти, стартапи у MVP-фазі)",[5089,15665,15666,15669,15670,5234,15672,5242],{},[5099,15667,15668],{},"Рекомендація:"," DAC або простий RBAC із кількома ролями (",[5231,15671,5283],{},[5231,15673,6159],{},[5089,15675,15676],{},"Якщо система працює з особистими даними без жорстких нормативних вимог, складні моделі будуть надмірними. Використовуйте просту перевірку власності ресурсу та базові ролі.",[5317,15678,15680],{"id":15679},"середні-вимоги-корпоративні-застосунки-saas-продукти","Середні вимоги (корпоративні застосунки, SaaS-продукти)",[5089,15682,15683,15685],{},[5099,15684,15668],{}," RBAC або RBAC з елементами ABAC.",[5089,15687,15688],{},"Для більшості бізнес-застосунків RBAC є оптимальним балансом між гнучкістю та складністю. Для специфічних випадків (наприклад, перевірка часу або IP) додайте точкові ABAC-правила.",[5317,15690,15692],{"id":15691},"високі-вимоги-фінансовий-сектор-медицина-державний-сектор","Високі вимоги (фінансовий сектор, медицина, державний сектор)",[5089,15694,15695,15697],{},[5099,15696,15668],{}," ABAC або MAC (залежно від типу даних).",[5089,15699,15700],{},"Якщо проєкт підпадає під регуляції GDPR, HIPAA, PCI DSS, SOC 2 — ABAC забезпечить необхідну гранулярність та аудит. Для військових та державних систем з формальною класифікацією — MAC.",[5317,15702,15704],{"id":15703},"фактор-2-масштаб-системи-та-кількість-користувачів","Фактор 2: Масштаб системи та кількість користувачів",[5093,15706,15707,15713,15719],{},[5096,15708,15709,15712],{},[5099,15710,15711],{},"До 100 користувачів:"," DAC або простий RBAC (3–5 ролей) цілком достатньо.",[5096,15714,15715,15718],{},[5099,15716,15717],{},"100–10,000 користувачів:"," RBAC із ієрархією ролей та групами дозволів.",[5096,15720,15721,15724],{},[5099,15722,15723],{},"10,000+ користувачів:"," RBAC з можливістю динамічного призначення ролей або ABAC для зменшення адміністративного навантаження.",[5317,15726,15728],{"id":15727},"фактор-3-динамічність-бізнес-логіки","Фактор 3: Динамічність бізнес-логіки",[5089,15730,15731],{},[5099,15732,15733],{},"Питання для оцінки:",[5093,15735,15736,15739],{},[5096,15737,15738],{},"Чи змінюються правила доступу залежно від часу, місця, стану сесії?",[5096,15740,15741],{},"Чи потрібна підтримка складних умов виду «Доступ дозволений, якщо користувач підтвердив email ТА працює з офісної IP ТА документ створений менше 30 днів тому»?",[5089,15743,15744],{},"Якщо так — ABAC є природним вибором. Якщо правила статичні та базуються лише на ролях — RBAC достатньо.",[5317,15746,15748],{"id":15747},"фактор-4-ресурси-команди","Фактор 4: Ресурси команди",[5089,15750,15751],{},[5099,15752,15753],{},"Реалістична оцінка:",[5093,15755,15756,15762,15768],{},[5096,15757,15758,15761],{},[5099,15759,15760],{},"Команда з 1–2 розробників, обмежений бюджет:"," DAC або базовий RBAC. Складні моделі забиратимуть занадто багато часу на розробку та підтримку.",[5096,15763,15764,15767],{},[5099,15765,15766],{},"Команда 5+ розробників, є досвід із безпекою:"," RBAC або ABAC з використанням готових бібліотек (CASL, Casbin, Open Policy Agent).",[5096,15769,15770,15773],{},[5099,15771,15772],{},"Корпоративна команда безпеки:"," Повноцінний ABAC з централізованим Policy Decision Point (PDP) та інтеграцією з SIEM-системами.",[7555,15775,15776,15779],{},[5099,15777,15778],{},"Пастка передчасної оптимізації:"," не впроваджуйте ABAC «на майбутнє», якщо поточні вимоги покриваються RBAC. Складність системи зростає нелінійно — спочатку реалізуйте простіше рішення, а потім мігруйте до складнішого лише при наявності реальної потреби.",[5125,15781],{},[5084,15783,15785],{"id":15784},"гібридні-підходи-та-комбінування-моделей","Гібридні підходи та комбінування моделей",[5089,15787,15788],{},"У реальних проєктах рідко зустрічається «чиста» реалізація однієї моделі. Найефективніші системи комбінують переваги кількох підходів:",[5317,15790,15792],{"id":15791},"rbac-resource-ownership-найпоширеніший-підхід","RBAC + Resource Ownership (найпоширеніший підхід)",[5089,15794,15795],{},"Використовуйте RBAC для визначення базових дозволів, але додайте перевірку власності ресурсу у сервісному шарі:",[5420,15797,15799],{"className":5565,"code":15798,"language":5567,"meta":5425,"style":5425},"\u002F\u002F services\u002Fposts.service.ts\nasync updatePost(postId: string, updateDto: UpdatePostDto, currentUser: User): Promise\u003CPost> {\n  const post = await this.postsRepository.findById(postId);\n\n  if (!post) {\n    throw new NotFoundException('Post not found');\n  }\n\n  \u002F\u002F Перевірка 1: Адміністратори можуть редагувати будь-які пости\n  if (currentUser.roles.includes('admin')) {\n    return this.postsRepository.update(postId, updateDto);\n  }\n\n  \u002F\u002F Перевірка 2: Звичайні користувачі можуть редагувати лише свої пости\n  if (post.authorId !== currentUser.id) {\n    throw new ForbiddenException('You can only edit your own posts');\n  }\n\n  return this.postsRepository.update(postId, updateDto);\n}\n",[5231,15800,15801,15806,15849,15878,15882,15893,15910,15914,15918,15923,15934,15958,15962,15966,15971,15978,15993,15997,16001,16011],{"__ignoreMap":5425},[5429,15802,15803],{"class":5431,"line":5432},[5429,15804,15805],{"class":5435},"\u002F\u002F services\u002Fposts.service.ts\n",[5429,15807,15808,15811,15813,15815,15818,15820,15822,15824,15826,15828,15830,15832,15834,15836,15839,15841,15843,15845,15847],{"class":5431,"line":5439},[5429,15809,15810],{"class":5596},"async",[5429,15812,11856],{"class":5442},[5429,15814,5975],{"class":5590},[5429,15816,15817],{"class":5596},"postId",[5429,15819,5600],{"class":5590},[5429,15821,5603],{"class":5596},[5429,15823,5234],{"class":5590},[5429,15825,7227],{"class":5596},[5429,15827,5600],{"class":5590},[5429,15829,11886],{"class":5596},[5429,15831,5234],{"class":5590},[5429,15833,6203],{"class":5596},[5429,15835,5600],{"class":5590},[5429,15837,15838],{"class":5596},"User",[5429,15840,5985],{"class":5590},[5429,15842,5988],{"class":5586},[5429,15844,5991],{"class":5590},[5429,15846,6908],{"class":5596},[5429,15848,5996],{"class":5590},[5429,15850,15851,15854,15857,15859,15861,15863,15865,15868,15870,15872,15874,15876],{"class":5431,"line":5450},[5429,15852,15853],{"class":5590},"  const ",[5429,15855,15856],{"class":5596},"post",[5429,15858,6013],{"class":5590},[5429,15860,6254],{"class":5579},[5429,15862,6257],{"class":5469},[5429,15864,5209],{"class":5590},[5429,15866,15867],{"class":5596},"postsRepository",[5429,15869,5209],{"class":5590},[5429,15871,6267],{"class":5442},[5429,15873,5975],{"class":5590},[5429,15875,15817],{"class":5596},[5429,15877,6231],{"class":5590},[5429,15879,15880],{"class":5431,"line":5457},[5429,15881,5454],{"emptyLinePlaceholder":5453},[5429,15883,15884,15887,15889,15891],{"class":5431,"line":5463},[5429,15885,15886],{"class":5442},"  if",[5429,15888,6086],{"class":5590},[5429,15890,15856],{"class":5596},[5429,15892,6092],{"class":5590},[5429,15894,15895,15898,15900,15903,15905,15908],{"class":5431,"line":5475},[5429,15896,15897],{"class":5579},"    throw",[5429,15899,6220],{"class":5469},[5429,15901,15902],{"class":5442}," NotFoundException",[5429,15904,5975],{"class":5590},[5429,15906,15907],{"class":5446},"'Post not found'",[5429,15909,6231],{"class":5590},[5429,15911,15912],{"class":5431,"line":5481},[5429,15913,6570],{"class":5590},[5429,15915,15916],{"class":5431,"line":5487},[5429,15917,5454],{"emptyLinePlaceholder":5453},[5429,15919,15920],{"class":5431,"line":5493},[5429,15921,15922],{"class":5435},"  \u002F\u002F Перевірка 1: Адміністратори можуть редагувати будь-які пости\n",[5429,15924,15925,15927,15930,15932],{"class":5431,"line":5499},[5429,15926,15886],{"class":5442},[5429,15928,15929],{"class":5590}," (currentUser.roles.includes(",[5429,15931,13306],{"class":5446},[5429,15933,13309],{"class":5590},[5429,15935,15936,15938,15940,15942,15944,15946,15948,15950,15952,15954,15956],{"class":5431,"line":5505},[5429,15937,6560],{"class":5579},[5429,15939,6257],{"class":5469},[5429,15941,5209],{"class":5590},[5429,15943,15867],{"class":5596},[5429,15945,5209],{"class":5590},[5429,15947,7252],{"class":5442},[5429,15949,5975],{"class":5590},[5429,15951,15817],{"class":5596},[5429,15953,5234],{"class":5590},[5429,15955,7227],{"class":5596},[5429,15957,6231],{"class":5590},[5429,15959,15960],{"class":5431,"line":5510},[5429,15961,6570],{"class":5590},[5429,15963,15964],{"class":5431,"line":5516},[5429,15965,5454],{"emptyLinePlaceholder":5453},[5429,15967,15968],{"class":5431,"line":5527},[5429,15969,15970],{"class":5435},"  \u002F\u002F Перевірка 2: Звичайні користувачі можуть редагувати лише свої пости\n",[5429,15972,15973,15975],{"class":5431,"line":5532},[5429,15974,15886],{"class":5442},[5429,15976,15977],{"class":5590}," (post.authorId !== currentUser.id) {\n",[5429,15979,15980,15982,15984,15986,15988,15991],{"class":5431,"line":5538},[5429,15981,15897],{"class":5579},[5429,15983,6220],{"class":5469},[5429,15985,6223],{"class":5442},[5429,15987,5975],{"class":5590},[5429,15989,15990],{"class":5446},"'You can only edit your own posts'",[5429,15992,6231],{"class":5590},[5429,15994,15995],{"class":5431,"line":5547},[5429,15996,6570],{"class":5590},[5429,15998,15999],{"class":5431,"line":5748},[5429,16000,5454],{"emptyLinePlaceholder":5453},[5429,16002,16003,16006,16008],{"class":5431,"line":5760},[5429,16004,16005],{"class":5590},"  return this.postsRepository.update(",[5429,16007,15817],{"class":5596},[5429,16009,16010],{"class":5590},", updateDto);\n",[5429,16012,16013],{"class":5431,"line":5772},[5429,16014,5683],{"class":5590},[5317,16016,16018],{"id":16017},"rbac-abac-для-специфічних-випадків","RBAC + ABAC для специфічних випадків",[5089,16020,16021],{},"Використовуйте RBAC для 95% рутинних операцій, але додайте ABAC-політики для критичних або складних випадків:",[5420,16023,16025],{"className":5565,"code":16024,"language":5567,"meta":5425,"style":5425},"\u002F\u002F Звичайні операції — через RBAC Guard\n@Get(':id')\n@RequirePermissions('read:documents')\nasync getDocument(@Param('id') id: string) {\n  return this.documentService.findById(id);\n}\n\n\u002F\u002F Експорт конфіденційних даних — через ABAC Guard з перевіркою контексту\n@Post(':id\u002Fexport-financial-data')\n@UseGuards(AuthGuard, AbacAuthorizationGuard)\n@RequireAction('export_financial')\nasync exportFinancialData(@Param('id') id: string) {\n  return this.documentService.exportFinancialData(id);\n}\n",[5231,16026,16027,16032,16044,16057,16081,16102,16106,16110,16115,16128,16144,16157,16182,16203],{"__ignoreMap":5425},[5429,16028,16029],{"class":5431,"line":5432},[5429,16030,16031],{"class":5435},"\u002F\u002F Звичайні операції — через RBAC Guard\n",[5429,16033,16034,16036,16038,16040,16042],{"class":5431,"line":5439},[5429,16035,5898],{"class":5590},[5429,16037,6893],{"class":5442},[5429,16039,5975],{"class":5590},[5429,16041,7087],{"class":5446},[5429,16043,7021],{"class":5590},[5429,16045,16046,16048,16050,16052,16055],{"class":5431,"line":5450},[5429,16047,5898],{"class":5590},[5429,16049,11536],{"class":5442},[5429,16051,5975],{"class":5590},[5429,16053,16054],{"class":5446},"'read:documents'",[5429,16056,7021],{"class":5590},[5429,16058,16059,16061,16063,16065,16067,16069,16071,16073,16075,16077,16079],{"class":5431,"line":5457},[5429,16060,15810],{"class":5596},[5429,16062,7108],{"class":5442},[5429,16064,7111],{"class":5590},[5429,16066,6913],{"class":5442},[5429,16068,5975],{"class":5590},[5429,16070,7118],{"class":5446},[5429,16072,6845],{"class":5590},[5429,16074,6186],{"class":5596},[5429,16076,5600],{"class":5590},[5429,16078,5603],{"class":5596},[5429,16080,6092],{"class":5590},[5429,16082,16083,16086,16088,16090,16092,16094,16096,16098,16100],{"class":5431,"line":5463},[5429,16084,16085],{"class":5579},"  return",[5429,16087,6257],{"class":5469},[5429,16089,5209],{"class":5590},[5429,16091,6262],{"class":5596},[5429,16093,5209],{"class":5590},[5429,16095,6267],{"class":5442},[5429,16097,5975],{"class":5590},[5429,16099,6186],{"class":5596},[5429,16101,6231],{"class":5590},[5429,16103,16104],{"class":5431,"line":5475},[5429,16105,5683],{"class":5590},[5429,16107,16108],{"class":5431,"line":5481},[5429,16109,5454],{"emptyLinePlaceholder":5453},[5429,16111,16112],{"class":5431,"line":5487},[5429,16113,16114],{"class":5435},"\u002F\u002F Експорт конфіденційних даних — через ABAC Guard з перевіркою контексту\n",[5429,16116,16117,16119,16121,16123,16126],{"class":5431,"line":5493},[5429,16118,5898],{"class":5590},[5429,16120,6908],{"class":5442},[5429,16122,5975],{"class":5590},[5429,16124,16125],{"class":5446},"':id\u002Fexport-financial-data'",[5429,16127,7021],{"class":5590},[5429,16129,16130,16132,16134,16136,16138,16140,16142],{"class":5431,"line":5499},[5429,16131,5898],{"class":5590},[5429,16133,6923],{"class":5442},[5429,16135,5975],{"class":5590},[5429,16137,6940],{"class":5596},[5429,16139,5234],{"class":5590},[5429,16141,14379],{"class":5596},[5429,16143,7021],{"class":5590},[5429,16145,16146,16148,16150,16152,16155],{"class":5431,"line":5505},[5429,16147,5898],{"class":5590},[5429,16149,14397],{"class":5442},[5429,16151,5975],{"class":5590},[5429,16153,16154],{"class":5446},"'export_financial'",[5429,16156,7021],{"class":5590},[5429,16158,16159,16161,16164,16166,16168,16170,16172,16174,16176,16178,16180],{"class":5431,"line":5510},[5429,16160,15810],{"class":5596},[5429,16162,16163],{"class":5442}," exportFinancialData",[5429,16165,7111],{"class":5590},[5429,16167,6913],{"class":5442},[5429,16169,5975],{"class":5590},[5429,16171,7118],{"class":5446},[5429,16173,6845],{"class":5590},[5429,16175,6186],{"class":5596},[5429,16177,5600],{"class":5590},[5429,16179,5603],{"class":5596},[5429,16181,6092],{"class":5590},[5429,16183,16184,16186,16188,16190,16192,16194,16197,16199,16201],{"class":5431,"line":5516},[5429,16185,16085],{"class":5579},[5429,16187,6257],{"class":5469},[5429,16189,5209],{"class":5590},[5429,16191,6262],{"class":5596},[5429,16193,5209],{"class":5590},[5429,16195,16196],{"class":5442},"exportFinancialData",[5429,16198,5975],{"class":5590},[5429,16200,6186],{"class":5596},[5429,16202,6231],{"class":5590},[5429,16204,16205],{"class":5431,"line":5527},[5429,16206,5683],{"class":5590},[5317,16208,16210],{"id":16209},"dac-для-користувацьких-даних-rbac-для-адміністративних-функцій","DAC для користувацьких даних + RBAC для адміністративних функцій",[5093,16212,16213,16216],{},[5096,16214,16215],{},"Користувачі керують доступом до власних документів через DAC (списки дозволів).",[5096,16217,16218,16219,16221],{},"Адміністратори мають глобальний доступ через роль ",[5231,16220,5283],{},", що обходить DAC-перевірки.",[5125,16223],{},[5084,16225,16227],{"id":16226},"інтерактивні-запитання-для-самоперевірки","Інтерактивні запитання для самоперевірки",[16229,16230,16231,16245,16260,16272],"accordion",{},[16232,16233,7866,16236,16238,16239,16241,16242,16244],"accordion-item",{"icon":16234,"label":16235},"i-lucide-help-circle","❓ Чому у моделі Белла-ЛаПадули заборонено писати у файли з нижчою класифікацією?",[5099,16237,7869],{}," запобігає витоку секретної інформації через зниження класифікації. Якщо користувач з рівнем допуску ",[5231,16240,7763],{}," прочитав високосекретні дані та зможе записати їх у файл з класифікацією ",[5231,16243,7754],{},", ці дані стануть доступні всім користувачам з найнижчим рівнем допуску. Модель жертвує гнучкістю заради гарантій конфіденційності.",[16232,16246,16248,16249,16251,16252,16255,16256,16259],{"icon":16234,"label":16247},"❓ Чи може один користувач мати кілька ролей одночасно у RBAC?","Так, це стандартна практика. Наприклад, користувач може бути одночасно ",[5231,16250,9634],{}," (доступ до репозиторіїв коду), ",[5231,16253,16254],{},"billing_viewer"," (перегляд рахунків), та ",[5231,16257,16258],{},"team_lead"," (управління підлеглими). Система об'єднує дозволи з усіх ролей — якщо хоча б одна роль дозволяє операцію, доступ надається.",[16232,16261,16263,16264,16267,16268,16271],{"icon":16234,"label":16262},"❓ Яка різниця між RBAC та ABAC, якщо у ABAC також можна використовувати ролі як атрибути?","У RBAC ролі є ",[5099,16265,16266],{},"первинною"," сутністю — вони визначаються заздалегідь, та користувачі призначаються до них. Рішення про доступ приймається виключно на основі наявності ролі. У ABAC ролі є лише ",[5099,16269,16270],{},"одним із атрибутів"," серед багатьох інших (час, місце, власність ресурсу). Політика ABAC може сказати: «Дозволити, ЯКЩО роль = editor ТА час \u003C 18:00 ТА ресурс належить відділу користувача». RBAC не може виражати такі складні умови.",[16232,16273,16275,16278],{"icon":16234,"label":16274},"❓ Чи потрібно реалізовувати ABAC самостійно або є готові бібліотеки?",[5089,16276,16277],{},"Реалізація ABAC з нуля є складною задачею. Використовуйте готові рішення:",[5093,16279,16280,16285,16291,16297],{},[5096,16281,16282,16284],{},[5099,16283,12619],{}," — TypeScript-бібліотека для декларативної авторизації, інтегрується з NestJS, React, Vue (детально розглянемо у наступній лекції).",[5096,16286,16287,16290],{},[5099,16288,16289],{},"Casbin"," — Go\u002FJava\u002FPython\u002FNode.js фреймворк з підтримкою різних моделей контролю доступу.",[5096,16292,16293,16296],{},[5099,16294,16295],{},"Open Policy Agent (OPA)"," — агент для оцінки політик, написаних мовою Rego, використовується у Kubernetes та мікросервісних архітектурах.",[5096,16298,16299,16302],{},[5099,16300,16301],{},"AWS IAM Policy Engine"," — якщо система працює в AWS, можна використовувати вбудований механізм політик.",[5125,16304],{},[5084,16306,16308],{"id":16307},"підсумок","Підсумок",[5128,16310,16311,16337,16360,16384],{},[5131,16312,16315,16321,16327,16332],{"icon":16313,"title":16314},"i-lucide-user-check","📋 DAC — Дискреційний контроль",[5089,16316,16317,16320],{},[5099,16318,16319],{},"Принцип:"," Власник ресурсу визначає права доступу.",[5089,16322,16323,16326],{},[5099,16324,16325],{},"Коли використовувати:"," Файлові системи, хмарні диски, системи з особистими даними.",[5089,16328,16329,16331],{},[5099,16330,7491],{}," Інтуїтивність, гнучкість, низька складність.",[5089,16333,16334,16336],{},[5099,16335,7522],{}," Ризик неконтрольованого поширення прав, слабкий аудит.",[5131,16338,16340,16345,16350,16355],{"icon":4616,"title":16339},"🔒 MAC — Мандатний контроль",[5089,16341,16342,16344],{},[5099,16343,16319],{}," Централізована політика на основі міток безпеки.",[5089,16346,16347,16349],{},[5099,16348,16325],{}," Військові системи, державна таємниця, високорегульовані середовища.",[5089,16351,16352,16354],{},[5099,16353,7491],{}," Гарантована відсутність витоків, формальна перевірка.",[5089,16356,16357,16359],{},[5099,16358,7522],{}," Негнучкість, висока складність адміністрування.",[5131,16361,16364,16369,16374,16379],{"icon":16362,"title":16363},"i-lucide-users","👥 RBAC — Рольовий контроль",[5089,16365,16366,16368],{},[5099,16367,16319],{}," Права надаються через ролі, що відповідають посадам.",[5089,16370,16371,16373],{},[5099,16372,16325],{}," Корпоративні застосунки, CRM, ERP, більшість бізнес-систем.",[5089,16375,16376,16378],{},[5099,16377,7491],{}," Спрощене адміністрування, відповідність оргструктурі, масштабованість.",[5089,16380,16381,16383],{},[5099,16382,7522],{}," Недостатня гранулярність для складних сценаріїв, вибух кількості ролей.",[5131,16385,16388,16393,16398,16403],{"icon":16386,"title":16387},"i-lucide-settings","🎯 ABAC — Атрибутивний контроль",[5089,16389,16390,16392],{},[5099,16391,16319],{}," Динамічна оцінка політик на основі атрибутів суб'єкта, об'єкта, дії та контексту.",[5089,16394,16395,16397],{},[5099,16396,16325],{}," Складні багатофакторні правила, медичні системи, фінансові платформи, Zero Trust архітектури.",[5089,16399,16400,16402],{},[5099,16401,7491],{}," Максимальна гнучкість, підтримка контексту, природний принцип найменших привілеїв.",[5089,16404,16405,16407],{},[5099,16406,7522],{}," Висока складність, проблеми продуктивності, складність налагодження.",[5089,16409,16410,16413],{},[5099,16411,16412],{},"Рекомендація для студентів:"," розпочніть вивчення з RBAC — це золотий стандарт для більшості проєктів. Після опанування RBAC перейдіть до вивчення ABAC через бібліотеку CASL (детально у наступній лекції). DAC і MAC є специфічними моделями для окремих доменів і не застосовуються у типових веб-застосунках.",[5089,16415,16416],{},"У наступних лекціях ми детально розглянемо практичну реалізацію RBAC у NestJS, інтеграцію з TypeORM для зберігання ролей та дозволів, а також впровадження ABAC через бібліотеку CASL для складних сценаріїв авторизації.",[16418,16419,16420],"style",{},"html pre.shiki code .spJ8K, html code.shiki .spJ8K{--shiki-light:#008000;--shiki-default:#6A9955;--shiki-dark:#6A9955}html pre.shiki code .s8Opu, html code.shiki .s8Opu{--shiki-light:#795E26;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html pre.shiki code .sbdoH, html code.shiki .sbdoH{--shiki-light:#A31515;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .su1O8, html code.shiki .su1O8{--shiki-light:#0000FF;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .sJj4R, html code.shiki .sJj4R{--shiki-light:#098658;--shiki-default:#B5CEA8;--shiki-dark:#B5CEA8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s8xlr, html code.shiki .s8xlr{--shiki-light:#AF00DB;--shiki-default:#C586C0;--shiki-dark:#C586C0}html pre.shiki code .sN1BT, html code.shiki .sN1BT{--shiki-light:#267F99;--shiki-default:#4EC9B0;--shiki-dark:#4EC9B0}html pre.shiki code .sHH4Y, html code.shiki .sHH4Y{--shiki-light:#000000;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .siwwj, html code.shiki .siwwj{--shiki-light:#001080;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .s-QsJ, html code.shiki .s-QsJ{--shiki-light:#0070C1;--shiki-default:#4FC1FF;--shiki-dark:#4FC1FF}html pre.shiki code .sD7JJ, html code.shiki .sD7JJ{--shiki-light:#000000FF;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}",{"title":5425,"searchDepth":5439,"depth":5439,"links":16422},[16423,16424,16425,16432,16440,16448,16456,16457,16466,16471,16472],{"id":5086,"depth":5439,"text":5087},{"id":5188,"depth":5439,"text":5189},{"id":5298,"depth":5439,"text":5299,"children":16426},[16427,16428,16429,16430,16431],{"id":5319,"depth":5450,"text":5320},{"id":5358,"depth":5450,"text":5359},{"id":5553,"depth":5450,"text":5554},{"id":7485,"depth":5450,"text":7486},{"id":7570,"depth":5450,"text":7571},{"id":7693,"depth":5439,"text":7694,"children":16433},[16434,16435,16436,16437,16438,16439],{"id":7714,"depth":5450,"text":7715},{"id":7781,"depth":5450,"text":7782},{"id":7891,"depth":5450,"text":7892},{"id":8035,"depth":5450,"text":8036},{"id":9423,"depth":5450,"text":9424},{"id":9515,"depth":5450,"text":9516},{"id":9582,"depth":5439,"text":9583,"children":16441},[16442,16443,16444,16445,16446,16447],{"id":9610,"depth":5450,"text":9611},{"id":9671,"depth":5450,"text":9672},{"id":9772,"depth":5450,"text":9773},{"id":10006,"depth":5450,"text":10007},{"id":12095,"depth":5450,"text":12096},{"id":12207,"depth":5450,"text":12208},{"id":12304,"depth":5439,"text":12305,"children":16449},[16450,16451,16452,16453,16454,16455],{"id":12357,"depth":5450,"text":12358},{"id":12411,"depth":5450,"text":12412},{"id":12442,"depth":5450,"text":12443},{"id":12612,"depth":5450,"text":12613},{"id":14795,"depth":5450,"text":14796},{"id":14908,"depth":5450,"text":14909},{"id":14960,"depth":5439,"text":14961},{"id":15648,"depth":5439,"text":15649,"children":16458},[16459,16460,16461,16462,16463,16464,16465],{"id":15655,"depth":5450,"text":15656},{"id":15662,"depth":5450,"text":15663},{"id":15679,"depth":5450,"text":15680},{"id":15691,"depth":5450,"text":15692},{"id":15703,"depth":5450,"text":15704},{"id":15727,"depth":5450,"text":15728},{"id":15747,"depth":5450,"text":15748},{"id":15784,"depth":5439,"text":15785,"children":16467},[16468,16469,16470],{"id":15791,"depth":5450,"text":15792},{"id":16017,"depth":5450,"text":16018},{"id":16209,"depth":5450,"text":16210},{"id":16226,"depth":5439,"text":16227},{"id":16307,"depth":5439,"text":16308},"md",null,{},{"title":4621,"description":5425},"B7wNDLAqgLfKa2twMpreYF4nDdt-T5SfmS4n-Ytc3FM",[16479,16480],{"title":4611,"path":4612,"stem":4613,"description":5425,"children":-1},{"title":4625,"path":4626,"stem":4627,"description":5425,"children":-1},1790322267599]