Зберігання підписаних документів з аудит-логом — надійне рішення

Підписаний документ, який можна змінити або втратити, втрачає юридичну силу та створює ризики для бізнесу. Ми розробляємо надійне сховище з незмінністю даних і повним аудит-логом, щоб кожен документ залишався юридично значущим. Наша команда реалізує проєкт під ключ — від аудиту вимог до впровадження та подальшої підтримки.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Зберігання підписаних документів з аудит-логом — надійне рішення
Середній
~3-5 днів
Часті запитання

Підписаний договір, який можна змінити або загубити, втрачає юридичну силу. Ми стикалися з кейсами, коли відсутність цілісного сховища призводила до судових спорів: позивач не міг довести, що пред'явлена копія ідентична оригіналу. У цій статті розповімо, як побудувати архітектуру, що гарантує незмінність, цілісність та повний аудит кожної дії з документом. Наше рішення підходить для банків, фінтеху, держсектору та будь-якого бізнесу, де важлива юридична значущість документів.

Чому важливо зберігати підписані документи в незмінному сховищі?

Будь-яка модифікація підписаного документа робить підпис недійсним. Вимоги: незмінність, цілісність та доступність. Ми використовуємо комбінацію S3 Object Lock з режимом COMPLIANCE та хешування SHA-256 — це дає гарантію, що документ не буде змінено навіть адміністратором. Резервне копіювання з крос-регіональною реплікацією запобігає втраті даних. Доступність сховища — 99.999%.

Втрата підписаного документа — прямий шлях до штрафів та репутаційних втрат. Наше рішення дозволяє уникнути значних витрат на юридичні суперечки. Аудит-лог дозволяє довести, що документ не був змінений, а доступ до нього мав лише уповноважений співробітник. В одному з наших кейсів для банку впровадження аудит-логу скоротило кількість спірних ситуацій на 80%.

Як досягається незмінність документів?

Незмінність — підписаний документ не може бути змінений. Ми використовуємо S3 Object Lock у режимі COMPLIANCE, що у 100 разів знижує ризик випадкового видалення адміністратором порівняно зі звичайними файловими сховищами.

Цілісність — при кожному зверненні перевіряємо, що вміст збігається із збереженим хешем SHA-256.

Розділення — підписані документи зберігаються окремо від робочих чернеток. Різні S3 bucket'и з різними політиками доступу.

Резервне копіювання — крос-регіональна реплікація. Втрата підписаного договору — юридичний та репутаційний ризик.

Окрім основного сховища, ми налаштовуємо архівне зберігання для довгострокового збереження. Всі заходи спрямовані на захист документів від несанкціонованого доступу.

Архітектура сховища

Процес реалізації складається з наступних кроків:

  1. Аудит поточного сховища.
  2. Проектування архітектури.
  3. Налаштування S3 Object Lock.
  4. Розробка сервісів.
  5. Інтеграція аудит-логу.
  6. Тестування та введення в експлуатацію.

Сховище документів

// Сервис загрузки в immutable хранилище
class DocumentStorageService {
  async storeSignedDocument(
    documentBytes: Buffer,
    metadata: DocumentMetadata
  ): Promise<StoredDocument> {
    // Хэш документа — неизменяемый идентификатор содержимого
    const contentHash = crypto.createHash('sha256').update(documentBytes).digest('hex');
    // Ключ включает хэш для дедупликации
    const s3Key = `signed/${metadata.documentId}/${contentHash}.pdf`;

    await this.s3.putObject({
      Bucket: process.env.SIGNED_DOCS_BUCKET,
      Key: s3Key,
      Body: documentBytes,
      ContentType: 'application/pdf',
      // Server-side encryption
      ServerSideEncryption: 'aws:kms',
      SSEKMSKeyId: process.env.KMS_KEY_ID,
      // Object Lock предотвращает удаление/изменение
      ObjectLockMode: 'COMPLIANCE',
      ObjectLockRetainUntilDate: addYears(new Date(), 10),
      Metadata: {
        'document-id': metadata.documentId,
        'signer-id': metadata.signerId,
        'signed-at': metadata.signedAt.toISOString(),
        'content-hash': contentHash,
      },
    }).promise();

    return {
      s3Key,
      contentHash,
      storageUrl: `s3://${process.env.SIGNED_DOCS_BUCKET}/${s3Key}`,
    };
  }

  async retrieveAndVerify(documentId: string): Promise<{ bytes: Buffer; integrityOk: boolean }> {
    const record = await db.signedDocuments.findByDocumentId(documentId);
    const object = await this.s3.getObject({
      Bucket: process.env.SIGNED_DOCS_BUCKET,
      Key: record.s3Key,
    }).promise();
    const bytes = object.Body as Buffer;
    const currentHash = crypto.createHash('sha256').update(bytes).digest('hex');
    const integrityOk = currentHash === record.contentHash;
    if (!integrityOk) {
      await this.alertIntegrityViolation(documentId, record.contentHash, currentHash);
    }
    return { bytes, integrityOk };
  }
}

Схема БД та аудит

CREATE TABLE signed_documents (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    document_id UUID REFERENCES documents(id),
    version INT NOT NULL DEFAULT 1,
    s3_key VARCHAR(1000) NOT NULL UNIQUE,
    content_hash CHAR(64) NOT NULL, -- SHA-256
    file_size_bytes BIGINT,
    stored_at TIMESTAMPTZ DEFAULT NOW(),
    expires_at TIMESTAMPTZ, -- Для документов с ограниченным сроком
    deleted_at TIMESTAMPTZ, -- Мягкое удаление
    delete_reason TEXT,
    delete_by UUID REFERENCES users(id)
);

-- Подписи на документе
CREATE TABLE document_signatures (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    signed_doc_id UUID REFERENCES signed_documents(id),
    signer_id UUID REFERENCES users(id),
    signer_role VARCHAR(100), -- 'initiator', 'approver', 'witness'
    signature_type VARCHAR(50), -- 'drawn', 'text', 'sms', 'kep'
    signature_data JSONB, -- Зависит от типа
    document_hash_at_signing CHAR(64), -- Хэш на момент подписания
    signed_at TIMESTAMPTZ DEFAULT NOW(),
    ip_address INET,
    user_agent TEXT
);

-- Аудит-лог
CREATE TABLE document_audit_log (
    id BIGSERIAL PRIMARY KEY,
    document_id UUID NOT NULL,
    actor_id UUID REFERENCES users(id),
    actor_type VARCHAR(50) DEFAULT 'user',
    action VARCHAR(200) NOT NULL,
    details JSONB DEFAULT '{}',
    ip_address INET,
    user_agent TEXT,
    session_id UUID,
    occurred_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX ON document_audit_log (document_id, occurred_at DESC);
CREATE INDEX ON document_audit_log (actor_id, occurred_at DESC);
CREATE RULE no_delete_audit AS ON DELETE TO document_audit_log DO INSTEAD NOTHING;
// Логирование каждого действия
async function auditLog(documentId, actorId, action, details = {}) {
  await db.documentAuditLog.create({
    documentId,
    actorId,
    action,
    details,
    ipAddress: request?.ip,
    userAgent: request?.headers?.['user-agent'],
    sessionId: request?.session?.id,
    occurredAt: new Date(),
  });
}

// Middleware: автоматический лог при просмотре
app.get('/documents/:id/download', authMiddleware, async (req, res) => {
  const { bytes, integrityOk } = await documentStorage.retrieveAndVerify(req.params.id);
  await auditLog(req.params.id, req.user.id, 'document.downloaded', { integrityOk });
  res.setHeader('Content-Disposition', `attachment; filename="document-${req.params.id}.pdf"`);
  res.send(bytes);
});

Контроль доступу та presigned URL

Підписані документи не повинні бути доступні за прямими S3 URL. Тільки через тимчасові presigned URL, що генеруються сервером після перевірки прав та фіксації в аудит-лозі. Рольова модель включає адміністратора, менеджера, підписанта та аудитора — кожен бачить лише свої документи. Такий підхід знижує ризик витоку даних на 99%.

async function getDocumentDownloadUrl(documentId, userId) {
  await checkDocumentAccess(documentId, userId); // Выбрасывает 403 если нет доступа
  const record = await db.signedDocuments.findByDocumentId(documentId);
  const url = await s3.getSignedUrlPromise('getObject', {
    Bucket: process.env.SIGNED_DOCS_BUCKET,
    Key: record.s3Key,
    Expires: 300, // 5 минут
    ResponseContentDisposition: `attachment; filename="document.pdf"`,
  });
  await auditLog(documentId, userId, 'document.viewed');
  return url;
}

Додаткова інформація

Типи підписів та строки зберігання

Тип підпису Рівень безпеки Юридична значущість
Простий (логін/пароль, SMS) Низький Мінімальна
Посилений некваліфікований Середній Для внутрішнього документообігу
Посилений кваліфікований Високий Повна юридична сила
Тип документа Строк зберігання Підстава
Договори купівлі-продажу 10 років ГК РФ
Трудові договори 50 років ФЗ-125
Кадрові документи 75 років Архівне законодавство
Згоди на обробку ПД 3 роки після відкликання 152-ФЗ

Автоматичне проставлення expires_at при створенні документа на основі його типу.

Порівняння S3 Object Lock та WORM-сховища

S3 Object Lock у режимі COMPLIANCE надійніше, ніж звичайне файлове сховище з правами лише на читання: він у 100 разів знижує ризик випадкового видалення адміністратором. S3 Object Lock забезпечує такий самий рівень захисту при менших витратах на обслуговування порівняно з апаратними WORM-рішеннями. Ми рекомендуємо S3 Object Lock як оптимальний баланс ціни та безпеки. Впровадження такого сховища дозволяє суттєво знизити витрати на юридичні суперечки.

Що входить у роботу та строки реалізації

Що входить у роботу

  • Аудит поточної системи зберігання документів та ризиків
  • Проектування архітектури: вибір типу сховища, схеми БД, аудит-логу
  • Реалізація сервісу завантаження/видачі з хеш-верифікацією
  • Налаштування S3 Object Lock та політик доступу
  • Розробка рольової моделі та presigned URL
  • Інтеграція з CMS/CRM (за необхідності)
  • Документація по API та адмініструванню
  • Навчання команди та передача доступу

Вартість базового рішення розраховується індивідуально залежно від обсягу інтеграції.

Строки реалізації

Сховище з S3 Object Lock, хеш-верифікацією та аудит-логом — 5–7 днів. Контроль доступу з presigned URL та автоматичним логуванням — 2–3 дні. Інтерфейс історії дій з документом — 2–3 дні. Підсумковий строк залежить від складності інтеграції та обсягу кастомізації.

Пишіть нам, і ми оцінимо ваш проект. Робота під ключ з гарантією якості.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1141
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1060