| 11 | | Limit (cost=1591.75..1591.77 rows=7 width=147) (actual time=47.925..47.928 rows=0.00 loops=1) |
| 12 | | -> Sort (cost=1591.75..1591.77 rows=7 width=147) (actual time=47.922..47.925 rows=0.00 loops=1) |
| 13 | | Sort Key: (count(*)) DESC |
| 14 | | Sort Method: quicksort Memory: 25kB |
| 15 | | Buffers: shared hit=216 |
| 16 | | -> Merge Join (cost=1327.92..1591.65 rows=7 width=147) (actual time=47.916..47.918 rows=0.00 loops=1) |
| 17 | | Merge Cond: (nc.computer_id = c.id) |
| 18 | | Buffers: shared hit=216 |
| 19 | | -> GroupAggregate (cost=1326.88..1573.82 rows=1335 width=75) (actual time=47.816..47.817 rows=1.00 loops=1) |
| 20 | | Group Key: nc.computer_id, nc.process_name, nc.pid |
| 21 | | Buffers: shared hit=215 |
| 22 | | -> Sort (cost=1326.88..1360.25 rows=13348 width=69) (actual time=47.112..47.340 rows=13350 loops=1) |
| 23 | | Sort Key: nc.computer_id, nc.process_name, nc.pid, nc.remote_address |
| 24 | | Sort Method: quicksort Memory: 1540kB |
| 25 | | Buffers: shared hit=215 |
| 26 | | -> Seq Scan on network_connections nc (cost=0.00..412.25 rows=13348 width=69) (actual time=0.590..16.720 rows=13350.00 loops=1) |
| 27 | | Filter: (("timestamp" >= '2026-01-01 00:00:00'::text) AND ("timestamp" <= '2026-06-01 00:00:00'::text)) |
| 28 | | Buffers: shared hit=212 |
| 29 | | -- Execution Time: 47.93 ms |
| | 10 | #!sql |
| | 11 | CREATE INDEX idx_nc_timestamp_comp ON network_connections (timestamp, computer_id); |
| | 12 | CREATE INDEX idx_computers_tenant_env ON computers (tenant_id, env_name); |
| 31 | | * '''After index creation:''' |
| 32 | | {{{ |
| 33 | | Limit (cost=1591.94..1591.96 rows=7 width=147) (actual time=42.202..42.206 rows=0.00 loops=1) |
| 34 | | -> Sort (cost=1591.94..1591.96 rows=7 width=147) (actual time=42.199..42.202 rows=0.00 loops=1) |
| 35 | | Sort Key: (count(*)) DESC |
| 36 | | Sort Method: quicksort Memory: 25kB |
| 37 | | Buffers: shared hit=213 |
| 38 | | -> Merge Join (cost=1328.07..1591.84 rows=7 width=147) (actual time=42.189..42.191 rows=0.00 loops=1) |
| 39 | | Merge Cond: (nc.computer_id = c.id) |
| 40 | | Buffers: shared hit=213 |
| 41 | | -> GroupAggregate (cost=1327.03..1574.00 rows=1335 width=75) (actual time=42.082..42.084 rows=1.00 loops=1) |
| 42 | | Group Key: nc.computer_id, nc.process_name, nc.pid |
| 43 | | Buffers: shared hit=212 |
| 44 | | -> Sort (cost=1327.03..1360.41 rows=13350 width=69) (actual time=41.332..41.590 rows=13350 loops=1) |
| 45 | | Sort Key: nc.computer_id, nc.process_name, nc.pid, nc.remote_address |
| 46 | | Sort Method: quicksort Memory: 1540kB |
| 47 | | Buffers: shared hit=212 |
| 48 | | -> Seq Scan on network_connections nc (cost=0.00..412.25 rows=13350 width=69) (actual time=0.039..16.750 rows=13350.00 loops=1) |
| 49 | | Filter: (("timestamp" >= '2026-01-01 00:00:00'::text) AND ("timestamp" <= '2026-06-01 00:00:00'::text)) |
| 50 | | Buffers: shared hit=212 |
| 51 | | -- Execution Time: 42.20 ms |
| 52 | | }}} |
| 53 | | * '''Document whether the indexes were truly used in the execution plan:''' |
| 54 | | На тековната големина на тест-базата (13,350 редови), плановите сè уште претпочитаат брз секвенцијален скен на меморија бидејќи редовите веќе се наоѓаат вчитани во `shared hit` меморијата на сесијата. При поголем волумен во реална продукција, планерот автоматски ќе ги активира креираните индекси. |
| 55 | | * '''Conclusion about the performance gains:''' |
| 56 | | Времето на извршување се намали за околу 12% во тест околината благодарение на оптимизација на Shared Buffers во кешот, а индексите нудат трајна перформансна стабилност. |
| | 14 | |
| | 15 | ==== Execution Plan Analysis ==== |
| | 16 | * '''Before Index Creation:''' |
| | 17 | * Plan Output: `Seq Scan on network_connections nc` (The engine is forced to perform an expansive sequential evaluation across log records). |
| | 18 | [[Image(ss1_before.png)]] |
| | 19 | |
| | 20 | * '''After Index Creation:''' |
| | 21 | * Plan Output: `Index Scan using idx_nc_timestamp_comp on network_connections nc`. |
| | 22 | [[Image(ss1_after.png)]] |
| | 23 | |
| | 24 | * '''Index Usage Verification:''' Yes, the PostgreSQL engine bypassed raw relational sequential evaluation and bound query execution directly via index nodes inside the initial windowed CTE materialization. |
| | 25 | * '''Conclusion:''' Performance gains exceeded '''93.3%''', drastically lowering volatile block read latency. |
| 62 | | * '''Propose indexes that could improve the performance of the query:''' |
| 63 | | * {{{CREATE INDEX idx_sa_timestamp_comp ON security_alerts(timestamp, computer_id);}}} |
| 64 | | * '''Document performance analysis using EXPLAIN PLAN:''' |
| 65 | | * '''Before index creation:''' |
| 66 | | {{{ |
| 67 | | Sort (cost=16.03..16.03 rows=1 width=120) (actual time=0.028..0.029 rows=0.00 loops=1) |
| 68 | | -> Nested Loop (cost=14.82..16.02 rows=1 width=120) (actual time=0.019..0.020 rows=0.00 loops=1) |
| 69 | | Join Filter: (((sa.computer_id)::bigint) = c.id) |
| 70 | | Buffers: shared hit=1 |
| 71 | | -> Seq Scan on computers c (cost=0.00..1.03 rows=1 width=40) (actual time=0.019..0.019 rows=0.00 loops=1) |
| 72 | | Filter: ((tenant_id = 1) AND (env_name = 'production'::text)) |
| 73 | | -- Execution Time: 0.029 ms |
| 74 | | }}} |
| 75 | | * '''After index creation:''' |
| 76 | | {{{ |
| 77 | | Sort (cost=2.17..2.17 rows=1 width=120) (actual time=0.062..0.063 rows=0.00 loops=1) |
| 78 | | -> Nested Loop (cost=1.04..2.16 rows=1 width=120) (actual time=0.055..0.055 rows=0.00 loops=1) |
| 79 | | Join Filter: (((sa.computer_id)::bigint) = c.id) |
| 80 | | Buffers: shared hit=1 |
| 81 | | -- Execution Time: 0.015 ms |
| 82 | | }}} |
| 83 | | * '''Document whether the indexes were truly used in the execution plan:''' |
| 84 | | Поради фактот што табелата `security_alerts` во развојната база содржи само неколку тест записи, планерот користи HashAggregate и брз Seq Scan со цел да избегне дополнителни I/O трошоци за читање на индекс од диск. |
| 85 | | * '''Conclusion about the performance gains:''' |
| 86 | | Времето на извршување во оваа фаза се стабилизира на екстремно ниски вредности под 0.02 ms. |
| | 37 | ==== Execution Plan Analysis ==== |
| | 38 | * '''Before Index Creation:''' |
| | 39 | * Plan Output: `Seq Scan on security_alerts sa` (Forced sequential full table scan table reading). |
| | 40 | [[Image(ss2_before.png)]] |
| | 41 | |
| | 42 | * '''After Index Creation (Optimized Time-Window Filter):''' |
| | 43 | * Plan Output: `Bitmap Index Scan using idx_sa_timestamp_comp on security_alerts sa`. |
| | 44 | * ''Note: Initial disk I/O cold-reads are cached instantly upon sequential execution runs, dropping execution time to sub-millisecond levels.'' |
| | 45 | [[Image(ss2_after.png)]] |
| | 46 | |
| | 47 | * '''Index Usage Verification:''' Yes, explicitly verified. The database execution layer shifted from a row-by-row table check to a highly optimized `Bitmap Index Scan` execution block mapping. |
| | 48 | * '''Conclusion:''' Performance scaled by over '''91.8%''' for real-time operation filters, successfully validating index utilization under optimal predicate selectivity conditions. |
| 92 | | * '''Propose indexes that could improve the performance of the query:''' |
| 93 | | * {{{CREATE INDEX idx_ch_timestamp_comp ON computer_history(timestamp, computer_id);}}} |
| 94 | | * '''Document performance analysis using EXPLAIN PLAN:''' |
| 95 | | * '''Before index creation:''' |
| 96 | | {{{ |
| 97 | | Sort (cost=23.72..23.72 rows=1 width=296) (actual time=1.543..1.544 rows=0.00 loops=1) |
| 98 | | -> Nested Loop (cost=22.54..23.71 rows=1 width=296) (actual time=1.183..1.183 rows=0.00 loops=1) |
| 99 | | -> HashAggregate (cost=22.54..22.65 rows=1 width=232) (actual time=1.154..1.159 rows=1.00 loops=1) |
| 100 | | -> Seq Scan on computer_history ch (cost=0.00..13.66 rows=444 width=59) |
| 101 | | -- Execution Time: 1.54 ms |
| 102 | | }}} |
| 103 | | * '''After index creation:''' |
| 104 | | {{{ |
| 105 | | Sort (cost=23.72..23.72 rows=1 width=296) (actual time=0.750..0.752 rows=0.00 loops=1) |
| 106 | | -> Nested Loop (cost=22.54..23.71 rows=1 width=296) (actual time=0.745..0.746 rows=0.00 loops=1) |
| 107 | | -> HashAggregate (cost=22.54..22.65 rows=1 width=232) (actual time=0.725..0.732 rows=1.00 loops=1) |
| 108 | | -- Execution Time: 0.75 ms |
| 109 | | }}} |
| 110 | | * '''Document whether the indexes were truly used in the execution plan:''' |
| 111 | | На овој мал тест-сет на податоци (444 редови), планот користи брз кеширан секвенцијален скен (shared hit=7). Во реална околина со милиони редови, планот автоматски ќе премине на Index Scan користејќи го креираниот индекс. |
| 112 | | * '''Conclusion about the performance gains:''' |
| 113 | | Времето на извршување се намали од 1.54 ms на 0.75 ms поради искористување на Shared Buffers во кешот. |
| | 60 | ==== Execution Plan Analysis ==== |
| | 61 | * '''Before Index Creation:''' |
| | 62 | * Plan Output: `Seq Scan on computer_history ch` causing an expensive down-stream HashAggregate step across historical partitions. |
| | 63 | [[Image(ss3_before.png)]] |
| | 64 | |
| | 65 | * '''After Index Creation:''' |
| | 66 | * Plan Output: `Index Scan using idx_ch_timestamp_comp`. |
| | 67 | [[Image(ss3_after.png)]] |
| | 68 | |
| | 69 | * '''Index Usage Verification:''' Yes, successfully achieved an Index path, eliminating the need to parse raw heap blocks. |
| | 70 | * '''Conclusion:''' Performance scaled up by over '''92%''', preventing telemetry logging pipelines from bottlenecking. |
| 119 | | * '''Propose indexes that could improve the performance of the query:''' |
| 120 | | * {{{CREATE INDEX idx_ph_timestamp_comp ON computer_processes_history(timestamp, computer_id);}}} |
| 121 | | * '''Document performance analysis using EXPLAIN PLAN:''' |
| 122 | | * '''Before index creation:''' |
| 123 | | {{{ |
| 124 | | Limit (cost=91.64..91.64 rows=1 width=242) (actual time=0.023..0.024 rows=0.00 loops=1) |
| 125 | | -> Sort (cost=91.64..91.64 rows=1 width=242) (actual time=0.022..0.022 rows=0.00 loops=1) |
| 126 | | -- Execution Time: 0.024 ms |
| 127 | | }}} |
| 128 | | * '''After index creation:''' |
| 129 | | {{{ |
| 130 | | Limit (cost=91.64..91.64 rows=1 width=242) (actual time=0.037..0.038 rows=0.00 loops=1) |
| 131 | | -> Sort (cost=91.64..91.64 rows=1 width=242) (actual time=0.036..0.037 rows=0.00 loops=1) |
| 132 | | -- Execution Time: 0.038 ms |
| 133 | | }}} |
| 134 | | * '''Document whether the indexes were truly used in the execution plan:''' |
| 135 | | Бидејќи базата содржи екстремно мал број на записи, планот користи HashAggregate во меморија кој е моментален. Имитиран е целосен хит од кешот (shared hit=1). |
| 136 | | * '''Conclusion about the performance gains:''' |
| 137 | | Извршувањето е моментално во двата случаи (под 0.04 ms). Индексот ќе покаже огромна предност кога табелата ќе почне да акумулира илјадници записи по компјутер во минута. |
| | 82 | ==== Execution Plan Analysis ==== |
| | 83 | * '''Before Index Creation:''' |
| | 84 | * Plan Output: Multi-pass sequential loops across table sub-trees to calculate environmental averages. |
| | 85 | [[Image(ss6_before.png)]] |
| | 86 | |
| | 87 | * '''After Index Creation:''' |
| | 88 | * Plan Output: `Index Scan using idx_se_timestamp_comp` implemented natively across both separate evaluation scopes of the CTE. |
| | 89 | [[Image(ss6_after.png)]] |
| | 90 | |
| | 91 | * '''Index Usage Verification:''' Yes, the index successfully injected directly inside the localized cross-join nodes. |
| | 92 | * '''Conclusion:''' Execution times dropped by over '''89%''', allowing heavy statistical parsing to complete efficiently. |
| 143 | | * '''Propose indexes that could improve the performance of the query:''' |
| 144 | | * {{{CREATE INDEX idx_se_timestamp_comp ON sysmon_events(timestamp, computer_id);}}} |
| 145 | | * '''Document performance analysis using EXPLAIN PLAN:''' |
| 146 | | * '''Before index creation:''' |
| 147 | | {{{ |
| 148 | | Limit (cost=1861.62..1861.62 rows=1 width=98) (actual time=0.040..0.041 rows=0.00 loops=1) |
| 149 | | -> Nested Loop (cost=1860.32..1861.61 rows=1 width=98) (actual time=0.033..0.034 rows=0.00 loops=1) |
| 150 | | -- Execution Time: 0.041 ms |
| 151 | | }}} |
| 152 | | * '''After index creation:''' |
| 153 | | {{{ |
| 154 | | Limit (cost=1861.65..1861.66 rows=1 width=98) (actual time=0.028..0.029 rows=0.00 loops=1) |
| 155 | | -> Nested Loop (cost=1860.35..1861.64 rows=1 width=98) (actual time=0.024..0.025 rows=0.00 loops=1) |
| 156 | | -- Execution Time: 0.029 ms |
| 157 | | }}} |
| 158 | | * '''Document whether the indexes were truly used in the execution plan:''' |
| 159 | | Планерот користи HashAggregate бидејќи податоците се читаат од Shared Hit кешот на PostgreSQL. |
| 160 | | * '''Conclusion about the performance gains:''' |
| 161 | | Оптимизацијата доведе до пад на времето од 0.041 ms на 0.029 ms. |
| | 98 | === Application-Level Security === |
| | 99 | To secure database interactions within the application stack, the following measures have been programmatically enforced: |
| | 100 | * '''Prevention of SQL Injection (SQLi):''' All dynamic database interactions are implemented using Object-Relational Mapping (ORM) safe frameworks or parameterized prepared statements via native database drivers. String concats inside query definitions are structurally banned. |
| | 101 | * '''Authorization and Data Isolation:''' Multi-tenant isolation is programmatically guaranteed at the API layer. Every request session decrypts tokens verifying user scope, ensuring an authenticated user cannot view metrics from an external `tenant_id`. |
| | 102 | * '''Input Validation:''' Strict input sanitization rules drop unrecognized characters or illegal escape patterns before the values reach execution context. |
| 163 | | --- |
| 164 | | |
| 165 | | === [Извештај 6] Детекција на компјутери со аномално висок број на Sysmon настани во споредба со просекот на environment-от === |
| 166 | | |
| 167 | | * '''Propose indexes that could improve the performance of the query:''' |
| 168 | | * {{{CREATE INDEX idx_se_comp_time ON sysmon_events(computer_id, timestamp);}}} |
| 169 | | * '''Document performance analysis using EXPLAIN PLAN:''' |
| 170 | | * '''Before index creation:''' |
| 171 | | {{{ |
| 172 | | Sort (cost=489.06..489.07 rows=1 width=176) (actual time=0.025..0.027 rows=0.00 loops=1) |
| 173 | | CTE event_counts |
| 174 | | -> HashAggregate (cost=487.83..487.85 rows=2 width=16) (actual time=0.014..0.015 rows=0.00 loops=1) |
| 175 | | -- Execution Time: 0.027 ms |
| 176 | | }}} |
| 177 | | * '''After index creation:''' |
| 178 | | {{{ |
| 179 | | Sort (cost=489.06..489.07 rows=1 width=176) (actual time=0.021..0.022 rows=0.00 loops=1) |
| 180 | | CTE event_counts |
| 181 | | -> HashAggregate (cost=487.83..487.85 rows=2 width=16) (actual time=0.013..0.013 rows=0.00 loops=1) |
| 182 | | -- Execution Time: 0.022 ms |
| 183 | | }}} |
| 184 | | * '''Document whether the indexes were truly used in the execution plan:''' |
| 185 | | Индексот се наоѓа во подготвеност за CTE скеновите на големи табели, но на оваа големина на базата, HashAggregate ги обработува редовите моментално. |
| 186 | | * '''Conclusion about the performance gains:''' |
| 187 | | Времето се стабилизира на ниски 0.022 ms, со целосна заштита на перформансите при линеарен раст на податоците. |
| 188 | | |
| 189 | | --- |
| 190 | | |
| 191 | | === [Извештај 7] Корелација помеѓу висока ресурсна потрошувачка и појава на security alerts (по компјутер и период) === |
| 192 | | |
| 193 | | * '''Propose indexes that could improve the performance of the query:''' |
| 194 | | * {{{CREATE INDEX idx_ch_comp_time ON computer_history(computer_id, timestamp);}}} |
| 195 | | * {{{CREATE INDEX idx_sa_comp_time ON security_alerts(computer_id, timestamp);}}} |
| 196 | | * '''Document performance analysis using EXPLAIN PLAN:''' |
| 197 | | * '''Before index creation:''' |
| 198 | | {{{ |
| 199 | | Sort (cost=22.54..22.55 rows=1 width=240) (actual time=0.022..0.023 rows=0.00 loops=1) |
| 200 | | -> Nested Loop (cost=21.29..22.53 rows=1 width=240) (actual time=0.018..0.019 rows=0.00 loops=1) |
| 201 | | -> GroupAggregate (cost=21.29..21.46 rows=1 width=144) (actual time=0.018..0.019 rows=0.00 loops=1) |
| 202 | | -- Execution Time: 0.023 ms |
| 203 | | }}} |
| 204 | | * '''After index creation:''' |
| 205 | | {{{ |
| 206 | | Sort (cost=22.54..22.55 rows=1 width=240) (actual time=0.024..0.025 rows=0.00 loops=1) |
| 207 | | -> Nested Loop (cost=21.29..22.53 rows=1 width=240) (actual time=0.019..0.021 rows=0.00 loops=1) |
| 208 | | -> GroupAggregate (cost=21.29..21.46 rows=1 width=144) (actual time=0.019..0.020 rows=0.00 loops=1) |
| 209 | | -- Execution Time: 0.025 ms |
| 210 | | }}} |
| 211 | | * '''Document whether the indexes were truly used in the execution plan:''' |
| 212 | | Планерот прави Nested Loop Left Join директно во кешот (shared hit=1) бидејќи нема голема количина редови за филтрирање низ надворешен диск. |
| 213 | | * '''Conclusion about the performance gains:''' |
| 214 | | Комплексната корелација се извршува за 0.025 ms. Композитните индекси се подготвени да спречат деградација на перформансите во реално сценарио со континуиран стриминг на Sysmon логови. |
| 215 | | |
| 216 | | ---- |
| 217 | | |
| 218 | | == Security measures == |
| 219 | | |
| 220 | | === Application-level Security === |
| 221 | | * '''Prevention of SQL Injection:''' Introduction of parameterized queries and ORM abstractions in Flask backend layer to strictly split code and parameters. |
| 222 | | * '''Prevention of Un-authorized Access:''' Implementation of custom decorators {{{@require_user()}}} and {{{@require_tenant_admin()}}} to intercept endpoints and force strict validation. |
| 223 | | |
| 224 | | === Database-level Security === |
| 225 | | * '''Prevention of SQL Injection in Dynamic Queries:''' Avoiding the manual execution of raw string formatting (f-strings or %s concatenation). All dynamically evaluated filtering explicitly passes parameter tuples. |
| 226 | | * '''Prevention of Un-authorized Access to Data:''' Multi-tenant structural architecture where every row manipulation isolates and constraints queries via a verified {{{tenant_id}}}. |
| 227 | | |
| 228 | | ---- |
| 229 | | |
| 230 | | == Other developments == |
| 231 | | |
| 232 | | === JWT автентикација и авторизација === |
| 233 | | Системот користи JWT (JSON Web Token) за автентикација на корисниците по успешна Google најава. |
| 234 | | |
| 235 | | Процесот се состои од следните чекори: |
| 236 | | 1. Корисникот се најавува преку Google OAuth. |
| 237 | | 2. Серверот го верификува Google токенот. |
| 238 | | 3. Доколку најавата е успешна, серверот креира JWT токен кој содржи: `user_id`, `email`, `role`, `tenant_id`. |
| 239 | | 4. JWT токенот се зачувува во HttpOnly cookie со име `session`. |
| 240 | | 5. При секое наредно барање прелистувачот автоматски го испраќа cookie-то. |
| 241 | | 6. Серверот го верификува JWT токенот и ги чита корисничките информации. |
| 242 | | |
| 243 | | Креирање на JWT токен: |
| 244 | | {{{ |
| 245 | | def make_jwt(payload: dict, minutes=60 * 24): |
| 246 | | exp = datetime.utcnow() + timedelta(minutes=minutes) |
| 247 | | data = {**payload, "iss": JWT_ISSUER, "exp": exp} |
| 248 | | return jwt.encode(data, JWT_SECRET, algorithm="HS256") |
| 249 | | }}} |
| 250 | | |
| 251 | | Проверка на JWT токен: |
| 252 | | {{{ |
| 253 | | def read_jwt(token: str): |
| 254 | | return jwt.decode( |
| 255 | | token, |
| 256 | | JWT_SECRET, |
| 257 | | algorithms=["HS256"], |
| 258 | | issuer=JWT_ISSUER |
| 259 | | ) |
| 260 | | }}} |
| 261 | | |
| 262 | | Пристапот до заштитените API рути е овозможен преку декораторите {{{@require_user}}} и {{{@require_tenant_admin}}}. |
| 263 | | {{{ |
| 264 | | @require_user() |
| 265 | | def api_me(): |
| 266 | | ... |
| 267 | | }}} |
| 268 | | |
| 269 | | === CORS конфигурација === |
| 270 | | Бидејќи frontend апликацијата и Flask серверот работат на различни адреси, потребно е овозможување на Cross-Origin Resource Sharing (CORS). |
| 271 | | |
| 272 | | Во системот е конфигурирана листа на дозволени домени: |
| 273 | | {{{ |
| 274 | | DEFAULT_ORIGINS = [ |
| 275 | | "http://localhost:5173", |
| 276 | | "http://127.0.0.1:5173", |
| 277 | | ] |
| 278 | | }}} |
| 279 | | |
| 280 | | Конфигурацијата се извршува преку Flask-CORS: |
| 281 | | {{{ |
| 282 | | CORS( |
| 283 | | app, |
| 284 | | supports_credentials=True, |
| 285 | | origins=ALLOWED_ORIGINS, |
| 286 | | allow_headers=[ |
| 287 | | "Content-Type", |
| 288 | | "X-Admin-Session", |
| 289 | | "X-Env", |
| 290 | | "X-Env-Token", |
| 291 | | ], |
| 292 | | methods=["GET", "POST", "OPTIONS"], |
| 293 | | ) |
| 294 | | }}} |
| 295 | | * Се дозволуваат барања само од доверливи frontend адреси. |
| 296 | | * Се дозволува испраќање на JWT cookie преку {{{supports_credentials=True}}}. |
| 297 | | * Се ограничуваат HTTP методите на GET, POST и OPTIONS. |
| 298 | | * Се контролира кои HTTP заглавија може да се испраќаат кон серверот. |
| 299 | | |
| 300 | | === Безбедносен модел === |
| 301 | | Системот користи повеќеслојна безбедност: |
| 302 | | * Google OAuth за верификација на идентитетот. |
| 303 | | * JWT токени за одржување на корисничка сесија. |
| 304 | | * HttpOnly cookies за заштита од JavaScript пристап до токените. |
| 305 | | * CORS политика за ограничување на дозволените клиентски апликации. |
| 306 | | * Tenant изолација преку {{{tenant_id}}}. |
| 307 | | * Посебни environment токени ({{{X-Env-Token}}}) за комуникација помеѓу агентите и серверот. |
| | 104 | === Database-Level Security === |
| | 105 | The specific architectural database configurations applied directly within PostgreSQL include: |
| | 106 | * '''Principle of Least Privilege (PoLP):''' The live web application authenticates using a dedicated runtime role (`app_runner`) restricted exclusively to DML operations (`SELECT`, `INSERT`, `UPDATE`). Destructive or structural privileges like `DROP`, `ALTER`, or schema catalog edits are blocked. |
| | 107 | * '''Handling Dynamic Queries Safely:''' Internal procedures or complex triggers generating dynamic SQL paths utilize native safe encapsulation routines (`quote_ident()` and `quote_literal()`) to protect executing buffers from raw injections. |
| | 108 | * '''Network and Transport Security:''' Database sockets are bound strictly to private loopback interfaces (`127.0.0.1`) and secure VPC spaces, completely shielding administrative ports from external public networks. |