Full C++23 framework tree: runtime, observability, security, data, app, realtime, supervisor, clients, CLI, example plus enterprise tenancy, audit, operability, governance, supplychain. Postgres via docker compose for tests.
60 lines
2.2 KiB
C++
60 lines
2.2 KiB
C++
// retention_hold: TTL boundary (89 kept, 91 deleted), grace days, legal holds
|
|
// block deletion, apply honors the pinned policy version only.
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "audit/retention/enforcer.h"
|
|
#include "audit/retention/hold.h"
|
|
#include "audit/retention/policy.h"
|
|
|
|
#define CHECK(c, msg) \
|
|
if (!(c)) { \
|
|
std::cerr << "FAIL retention_hold: " << msg << "\n"; \
|
|
return 1; \
|
|
}
|
|
|
|
int main() {
|
|
using namespace molo::audit::retention;
|
|
Policy policy(7, {{"users", TableRule{90, 0}}, {"logs", TableRule{90, 5}}});
|
|
std::vector<ScannedRow> rows = {
|
|
{"t1", "users", "a", 89}, {"t1", "users", "b", 91}, {"t1", "logs", "c", 93}};
|
|
Hold hold;
|
|
|
|
auto scan = [&](ScannedRow& out) -> bool {
|
|
static std::size_t i = 0;
|
|
if (i >= rows.size()) {
|
|
i = 0;
|
|
return false;
|
|
}
|
|
out = rows[i++];
|
|
return true;
|
|
};
|
|
DryRunReport dry = Enforcer::DryRun(policy, hold, scan);
|
|
CHECK(dry.scanned == 3 && dry.kept == 2 && dry.would_delete == 1 && dry.held == 0,
|
|
"89 kept, 91 deleted, 93 in grace");
|
|
CHECK(dry.deletions.size() == 1 && dry.deletions[0].pk == "b", "deletion names pk b");
|
|
|
|
hold.Add(Hold::RowKey("t1", "users", "b"), "litigation");
|
|
DryRunReport dry2 = Enforcer::DryRun(policy, hold, scan);
|
|
CHECK(dry2.held == 1 && dry2.would_delete == 0, "hold blocks deletion");
|
|
|
|
hold.Remove(Hold::RowKey("t1", "users", "b"));
|
|
std::vector<std::string> deleted;
|
|
ApplyResult applied =
|
|
Enforcer::Apply(policy, hold, dry, [&](const ScannedRow& r) { deleted.push_back(r.pk); });
|
|
CHECK(applied.deleted == 1 && deleted[0] == "b", "apply deletes pinned rows");
|
|
|
|
hold.Add(Hold::RowKey("t1", "users", "b"), "late hold");
|
|
ApplyResult held =
|
|
Enforcer::Apply(policy, hold, dry, [&](const ScannedRow&) { deleted.push_back("x"); });
|
|
CHECK(held.deleted == 0 && held.skipped_hold == 1, "late hold skips apply");
|
|
|
|
Policy newer(8, {{"users", TableRule{90, 0}}});
|
|
ApplyResult stale =
|
|
Enforcer::Apply(newer, Hold{}, dry, [&](const ScannedRow&) { deleted.push_back("x"); });
|
|
CHECK(stale.deleted == 0 && stale.skipped_policy == 1, "version change skips apply");
|
|
std::cout << "PASS retention_hold\n";
|
|
return 0;
|
|
}
|