Skip to main content
Compliance export primitives for the Glide agent activity log. The package covers four concerns that every compliant export pipeline shares: validating the requested range against the OSS plan §M4 quota, splitting multi-year requests into calendar-month shards (one DB row per shard), building the signed JSON envelope that ships to the reviewer, and keeping S3 signed URLs from expiring between the time a job enqueues and the time the operator’s UI polls for it. A fifth concern — retention lifecycle — is handled by three concrete S3 storage adapters that share a RetentionStorage interface. The retention-sweep cron picks a storage class per row based on its age tier without coupling to the concrete S3 client. The package is DB-agnostic and S3-client-agnostic. Operators wire their own @aws-sdk/client-s3 instance, storage bucket, and DB driver.

Install

npmjs.com/package/@glideco/compliance-export

Why not bundle the S3 client?

Taking @aws-sdk/client-s3 as a hard dependency would pin the major version and add ~2 MB to every install even for operators who archive to GCS or Cloudflare R2. The S3SendableClient and S3CommandFactory interfaces accept any object whose send() method returns the expected shape — the AWS SDK satisfies them out of the box; a GCS presigned-URL shim satisfies them with a thin adapter. The same logic applies to the DB: export envelope rows live in compliance_exports however the operator manages that table, and the package makes no assumption about the ORM or driver.

Range validation and monthly sharding

The OSS plan §M4 caps a single export at one year. validateRange enforces this; splitIntoMonthlyShards produces one UTC calendar-month shard per month in a longer range, each safe to pass as a single-shot export:
The 10-exports-per-tenant-per-day quota is enforced at the tRPC router layer, not here. validateRange only checks the temporal span.

Building a JSON envelope

buildEnvelope assembles the signed JSON shape that ships in compliance.exportJson (sync path) or inside the async PDF body. The envelope carries the entity ID, display name, export range, and one row per activity-log entry. Per-row fields include the on-chain tx hash (if any), risk verdict, policy version, and redactedFieldsBitmap — the UI renders [REDACTED] for fields whose bit is set:
Both ComplianceExportRowSchema and ComplianceExportEnvelopeSchema are exported for callers that want to validate an envelope they received rather than build one.

Refreshing S3 signed URLs

Signed URLs expire. When the operator’s admin UI polls a long-running export job, the URL from the initial PutObject may already be stale. refreshSignedUrl handles the cache-and-refresh pattern: it re-signs only when the cached URL is absent or will expire within a configurable threshold (default: 5 minutes):

Retention-tier storage adapters

Activity log rows age through four tiers: hot (0–7d, Postgres), warm (7–90d, Postgres), cold (90–365d, S3), and regulatory (1–7y, S3 Deep Archive). The three concrete adapters all implement RetentionStorage so the sweep cron can swap storage class without changing the calling code:

Quotas summary

Reading list