@absolutejs/compliance
v0.1.0
Published
Framework-agnostic compliance substrate for the AbsoluteJS PaaS. Declarative data classification + residency + retention policies; orchestrators for retention sweeps, Subject Access Requests, right-to-erasure, and evidence bundles. Composes onto @absolute
Maintainers
Readme
@absolutejs/compliance
Framework-agnostic compliance substrate for the AbsoluteJS PaaS.
@absolutejs/compliance gives a control plane five composable
primitives. None of them know about a specific framework — SOC2,
HIPAA, ISO 27001, and GDPR all map onto the same shape.
Primitives
1. createCompliancePolicy({ classifications, tenantOverrides? })
Declarative shape. Each classification gets a stable id,
retention window, optional residency region, optional
erasureExempt flag, and an open flags bag.
const policy = createCompliancePolicy({
classifications: {
pii: { id: 'pii', retentionMs: 730 * DAY, residency: 'eu' },
'audit-log': {
id: 'audit-log',
retentionMs: Infinity,
erasureExempt: true, // SOX / many regulators require 7+ years
flags: { immutable: true },
},
operational: { id: 'operational', retentionMs: 90 * DAY },
},
tenantOverrides: {
'gdpr-strict-tenant': { pii: { retentionMs: 90 * DAY } },
},
});2. createResidencyGuard(policy)
Pure check. The runtime, sync, queue, and blob layers call
guard.check({ classification, region, tenant? }) before letting
data move. Mismatches throw ResidencyViolation.
guard.check({ classification: 'pii', region: 'us-east' });
// throws ResidencyViolation if policy says 'eu'
// non-throwing variant
const v = guard.inspect({ classification: 'pii', region: 'eu', tenant: 'acme' });
if (v !== null) return new Response(v.message, { status: 451 });3. runRetention({ policy, scanners, deleters, audit?, ... })
Orchestrator. Each scanner streams expired records for a
classification; each deleter removes them (batched). Per-scanner
failures are isolated. Optional audit broker logs a
'compliance.retention.swept' event per class. dryRun: true
counts without deleting.
const report = await runRetention({
policy,
audit: broker,
scanners: [
{ classification: 'audit-log', scan: auditTable.scan },
{ classification: 'pii', scan: userTable.scan },
],
deleters: {
'audit-log': (rows) => auditTable.delete(rows.map(r => r.id)),
'pii': (rows) => userTable.delete(rows.map(r => r.id)),
},
});
// report = { byClassification: { pii: { scanned, deleted, durationMs }, ... }, errors }4. runSubjectAccess({ subject, collectors }) + runErasure({ subject, erasers, ... })
Compose a "find / forget everything about user X" pipeline across packages. Each package provides a collector / eraser pair. The substrate runs them and returns a structured bundle.
runErasure automatically routes to eraser.anonymize for
erasureExempt classifications (typical: anonymize audit-log
subject references rather than delete the log itself). Records the
erasure to audit if a broker is provided.
const bundle = await runSubjectAccess({
subject: { tenant: 'acme', subjectId: 'u-1' },
collectors: [
{ name: 'profile', classification: 'pii', collect: userTable.findBySubject },
{ name: 'audit', classification: 'audit-log', collect: auditTable.findBySubject },
{ name: 'sync-packs', classification: 'sync-packs', collect: syncPacks.findBySubject },
],
});
await runErasure({
policy, audit: broker,
subject: { tenant: 'acme', subjectId: 'u-1' },
erasers: [
{ name: 'profile', classification: 'pii', erase: userTable.deleteBySubject },
{ name: 'audit', classification: 'audit-log', anonymize: auditTable.anonymizeSubject },
],
});5. collectEvidence({ policy, period, sources })
Bundles per-source JSON evidence into a single structure an
external auditor can read. Each source returns arbitrary JSON-
serializable evidence for the period; the bundler doesn't
interpret the shape. Ships with auditEvidenceSource(broker)
for the typical "all audit events in the period" case.
const bundle = await collectEvidence({
policy,
period: { start: lastQuarter, end: now },
sources: [
auditEvidenceSource(broker, { kindPrefix: 'compliance.' }),
{ name: 'access-log', collect: () => accessLog.dump(period) },
{ name: 'config-snapshot',collect: () => config.snapshot() },
],
});
// Write `bundle` to disk → hand to your SOC2 / ISO / HIPAA auditor.Tenant overrides
A per-tenant override wins over the class default. GDPR-strict tenants riding a default-US-East platform get their own residency, retention, and erasure-exempt behavior without forking the policy.
License
BSL-1.1 with named carveout against hosted compliance / GRC SaaS
(Vanta, Drata, Secureframe, OneTrust, TrustCloud, Sprinto,
Tugboat Logic). See LICENSE. Change date: 2030-05-31 →
Apache 2.0.
