Перейти до вмісту

Що система зберігає і як довго

Політика зберігання даних і аудиту. Живе в репозиторії, а не в локальних нотатках, бо її виконує код (AuditCleanupBackgroundService) і про неї треба знати, читаючи цей код.

Що: KurinAuditEvent — хто, що й коли змінив у курені: підписи точок і статус проби, вмілості, відзначення, перестороги, події календаря, профіль людини, офіси, впорядництво, членства й налаштування куреня. З 1.2.3 сюди ж перенесено колишні ProbeProgressAuditEvent і BadgeProgressAuditEvent; історія на картці проби й вмілості читається з журналу. Скільки: 365 днів від OccurredAtUtc, далі — жорстке видалення пакетами.

Запис зберігає:

Поле Навіщо
ActorUserKey звʼязати з людиною, якщо вона ще існує
ActorName, ActorRole незмінний знімок імені й ролі на момент дії
Area, Action розділ і що саме зроблено
SubjectMemberKey, SubjectMemberName, SubjectGroupKey про кого запис і в якому гуртку людина стояла тоді
SubjectKey, SubjectLabel що саме змінено (проба, подія, офіс)
Changes було → стало для змінених полів
Note необовʼязковий коментар виконавця

Персональних даних журнал не зберігає. Поле з групи «пошта й телефон», «дата народження», «адреса й школа», «контакти батьків» чи «поля краю» записується лише як «змінено» — без старого й нового значення. Інакше журнал став би другою копією цих даних з власним строком.

Імʼя, роль і гурток зберігаються знімком навмисно: запис має лишатися читабельним і тоді, коли людина пішла з куреня або змінила діловодство. Зовнішніх ключів немає — журнал переживає те, що описує. Бачать його ті, кому курінь це дозволив (за замовчуванням уся КВ).

Що: WaitlistEntry (з краєм, який вибрав заявник, — KraiCode), Invitation. Скільки:

  • WaitlistEntry — 30 днів після кінцевого стану (Rejected, або ApprovedForInvitation, чиє запрошення вже використане чи протерміноване);
  • Invitation — 30 днів після UsedAtUtc або ExpiresAtUtc.

Жорстке видалення. Це персональні дані (пошта, імена) людей, які не завершили онбординг — тримати їх довше немає підстави.

Призначення й зняття офісів та впорядництва лягають у журнал дій (§1) на 365 днів. Зміна ролі адміністратора живе в логах застосунку й прибирається зовнішнім провайдером (Application Insights), очікувано — 365 днів.

Що: DuesEntry (операції каси гуртка й куреня) і DuesEntryEvent (слід кожної зміни). Скільки: безстроково. Прибиральник їх не чіпає.

Це гроші: курінь звітує станиці, і запис, на який спирається поданий звіт, не може зникнути через пів року. Тому операцію не видаляють навіть рукою скарбника — її позначають видаленою (DeletedAtUtc), а кожна зміна лишає DuesEntryEvent зі знімком операції після зміни й ключем того, хто її зробив.

Що: DuesConcessionGrant — пільга краю, надана людині на відрізок кварталів, з причиною (Reason — вільний текст про саму людину, наприклад «двоє дітей у курені»). Скільки: поки живе вкладка цього членства. Надану помилково пільгу «Видалити» стирає рядком, без сліду; коли членство прибирають, DuesCleanupEventHandler видаляє її разом із нарахуваннями й пільгами куреня цього членства.

Що: ScoreAttendance (відмітки присутності), ScoreEntry (бали вручну), PrivateScoreEntry (книга КВ) і ScoreTrailEvent (слід кожної зміни відмітки, бала, тарифу, етапу чи запису КВ). Скільки: безстроково, як курінна історія: рейтинг минулих років лишається відкритим.

Відмітку знімають, а запис видаляють позначкою (RemovedAtUtc, DeletedAtUtc), не рядком — слід показує, хто й коли поставив чи зняв бал.

ScoreNotHeldOccurrence («Сходин не було»: подія, повторення, хто й коли) живе, поки її не повернуть або поки на тій події не відмітять когось присутнім, — тоді рядок видаляється. Хто поставив і зняв позначку, памʼятає журнал дій (365 днів).

Що: KraiProfileRevision — кожна збережена версія профілю краю (вмілості, валюта, пояс, формат чисел, поля картки, куди курені передають вкладку, пільги краю). Скільки: безстроково. Рядки лише додаються: чинний профіль — остання ревізія, попередні — його історія, з якої адміністратор відновлює давнішу версію (відновлення теж додає нову ревізію).

Що: приватні поля Member — Address, School, MotherFirstName, MotherLastName, MotherPhone, FatherFirstName, FatherLastName, FatherPhone — і CardExtras (значення власних полів краю, JSON). Скільки: поки існує сама людина. Вихід із куреня їх не стирає.

Приховане поле не стирає значення. Коли край ховає поле картки або прибирає власне поле, а курінь приховує поле у своїй картці (Kurin.HiddenCardFields — лише перелік ключів, без даних), збережене значення лишається в базі: форма, яка поля не показує, нічого не надсилає, і поле не перезаписується. Повернеш поле — значення на місці.

Хто бачить ці поля, а також пошту, телефон і дату народження, вирішує курінь у налаштуваннях («Права й видимість», Kurin.AccessPolicy); сервер віддає приховане порожнім. Те саме правило діє на запис: група, якої редактор не бачить, при збереженні не перезаписується.

Що: випадковий id інсталяції — рядок SystemSettings з ключем Telemetry__InstanceId. Скільки: безстроково; створюється з першим пінгом.

Лічильники запитів і 5xx для пінгу (TelemetryCounters) і заміри часу для /health (RequestTimings, останні 15 хвилин) живуть лише в памʼяті процесу: у базу й логи не пишуться, перезапуск їх обнуляє.

3е. Посилання на календар

Section titled “3е. Посилання на календар”

Що: CalendarFeed — посилання, за яким Google, Apple чи Outlook забирають події людини: лише SHA-256 токена (TokenHash), що в нього входить, і коли календар востаннє його забирав (LastFetchedAtUtc, не частіше разу на годину). Скільки: живе посилання — поки людина його не вимкне чи не замінить, або поки зміна безпеки (пароль, пошта, другий фактор, призупинення) його не вимкне. Вимкнене — 90 днів після RevokedAtUtc: весь цей час за ним віддається календар із повідомленням, що посилання не діє. Далі рядок видаляє прибиральник, і старе посилання відповідає 404. Видалення акаунта забирає рядки каскадом.

Токен у шляху маскується в логах, у записах активності й у телеметрії (SecretPaths).

Що: DismissedDuty — справа, яку людина сховала зі своїх «Справ» на головній: акаунт, ключ справи (вид, курінь, гурток, подія й повторення — ключі, без імен) і її розмір на той час. Скільки: 30 днів після DismissedAtUtc, далі рядок видаляє прибиральник і справа, якщо вона ще чекає, повертається. «Показати приховані» видаляє рядки людини одразу; видалення акаунта забирає їх каскадом.

Записи, привʼязані до активного розслідування безпеки чи розгляду скарги, мали б виключатися з прибирання прапорцем IsRetainedForInvestigation. Не реалізовано: зараз збереження таких записів понад строк робиться руками в базі.

IHostedService, раз на добу в неробочі години (≈03:00 UTC). Видаляє пакетами, щоб не тримати блокувань на таблицях.