Migrating from v1
Migrating from v1 to v2 of the c15t backend.
Canary Feature
This feature is available in canary releases and may have breaking changes. Use with caution in production. Report issues on GitHub
There has been several major changes to the c15t backend since v1. For the most part, the migration should be straightforward.
Notable Changes
@c15t/backend/v2
now uses FumaDB to integrate with a variety of databases.@c15t/backend/v2
stores date & time as EPOCH milliseconds instead of ISO strings.@c15t/backend/v2
has a slightly different instance interface.@c15t/backend/v2
does not support custom prefixes or table names.
Info
As your consent backend is less production-critical, it could be worth statrting with a new database and doing a data migration. This ensures your databases schema 100% matches the new FumaDB schema.
Migratiing your database
npx @c15t/cli migrate
If you encounter any issues, and your schema has not been altered e.g. custom prefixes or table names. You can run the following SQL add the table FumaDB expects.
CREATE TABLE private_c15t_settings (
key character varying(255) NOT NULL,
value text NOT NULL,
PRIMARY KEY (key)
);
INSERT INTO private_c15t_settings VALUES
('name-variants', '{"subject":{"convex":"subject","drizzle":"subject","prisma":"subject","mongodb":"subject","sql":"subject"},"subject.id":{"convex":"id","drizzle":"id","prisma":"id","mongodb":"_id","sql":"id"},"subject.isIdentified":{"convex":"isIdentified","drizzle":"isIdentified","prisma":"isIdentified","mongodb":"isIdentified","sql":"isIdentified"},"subject.externalId":{"convex":"externalId","drizzle":"externalId","prisma":"externalId","mongodb":"externalId","sql":"externalId"},"subject.identityProvider":{"convex":"identityProvider","drizzle":"identityProvider","prisma":"identityProvider","mongodb":"identityProvider","sql":"identityProvider"},"subject.lastIpAddress":{"convex":"lastIpAddress","drizzle":"lastIpAddress","prisma":"lastIpAddress","mongodb":"lastIpAddress","sql":"lastIpAddress"},"subject.createdAt":{"convex":"createdAt","drizzle":"createdAt","prisma":"createdAt","mongodb":"createdAt","sql":"createdAt"},"subject.updatedAt":{"convex":"updatedAt","drizzle":"updatedAt","prisma":"updatedAt","mongodb":"updatedAt","sql":"updatedAt"},"domain":{"convex":"domain","drizzle":"domain","prisma":"domain","mongodb":"domain","sql":"domain"},"domain.id":{"convex":"id","drizzle":"id","prisma":"id","mongodb":"_id","sql":"id"},"domain.name":{"convex":"name","drizzle":"name","prisma":"name","mongodb":"name","sql":"name"},"domain.description":{"convex":"description","drizzle":"description","prisma":"description","mongodb":"description","sql":"description"},"domain.allowedOrigins":{"convex":"allowedOrigins","drizzle":"allowedOrigins","prisma":"allowedOrigins","mongodb":"allowedOrigins","sql":"allowedOrigins"},"domain.isVerified":{"convex":"isVerified","drizzle":"isVerified","prisma":"isVerified","mongodb":"isVerified","sql":"isVerified"},"domain.isActive":{"convex":"isActive","drizzle":"isActive","prisma":"isActive","mongodb":"isActive","sql":"isActive"},"domain.createdAt":{"convex":"createdAt","drizzle":"createdAt","prisma":"createdAt","mongodb":"createdAt","sql":"createdAt"},"domain.updatedAt":{"convex":"updatedAt","drizzle":"updatedAt","prisma":"updatedAt","mongodb":"updatedAt","sql":"updatedAt"},"consentPolicy":{"convex":"consentPolicy","drizzle":"consentPolicy","prisma":"consentPolicy","mongodb":"consentPolicy","sql":"consentPolicy"},"consentPolicy.id":{"convex":"id","drizzle":"id","prisma":"id","mongodb":"_id","sql":"id"},"consentPolicy.version":{"convex":"version","drizzle":"version","prisma":"version","mongodb":"version","sql":"version"},"consentPolicy.type":{"convex":"type","drizzle":"type","prisma":"type","mongodb":"type","sql":"type"},"consentPolicy.name":{"convex":"name","drizzle":"name","prisma":"name","mongodb":"name","sql":"name"},"consentPolicy.effectiveDate":{"convex":"effectiveDate","drizzle":"effectiveDate","prisma":"effectiveDate","mongodb":"effectiveDate","sql":"effectiveDate"},"consentPolicy.expirationDate":{"convex":"expirationDate","drizzle":"expirationDate","prisma":"expirationDate","mongodb":"expirationDate","sql":"expirationDate"},"consentPolicy.content":{"convex":"content","drizzle":"content","prisma":"content","mongodb":"content","sql":"content"},"consentPolicy.contentHash":{"convex":"contentHash","drizzle":"contentHash","prisma":"contentHash","mongodb":"contentHash","sql":"contentHash"},"consentPolicy.isActive":{"convex":"isActive","drizzle":"isActive","prisma":"isActive","mongodb":"isActive","sql":"isActive"},"consentPolicy.createdAt":{"convex":"createdAt","drizzle":"createdAt","prisma":"createdAt","mongodb":"createdAt","sql":"createdAt"},"consentPurpose":{"convex":"consentPurpose","drizzle":"consentPurpose","prisma":"consentPurpose","mongodb":"consentPurpose","sql":"consentPurpose"},"consentPurpose.id":{"convex":"id","drizzle":"id","prisma":"id","mongodb":"_id","sql":"id"},"consentPurpose.code":{"convex":"code","drizzle":"code","prisma":"code","mongodb":"code","sql":"code"},"consentPurpose.name":{"convex":"name","drizzle":"name","prisma":"name","mongodb":"name","sql":"name"},"consentPurpose.description":{"convex":"description","drizzle":"description","prisma":"description","mongodb":"description","sql":"description"},"consentPurpose.isEssential":{"convex":"isEssential","drizzle":"isEssential","prisma":"isEssential","mongodb":"isEssential","sql":"isEssential"},"consentPurpose.dataCategory":{"convex":"dataCategory","drizzle":"dataCategory","prisma":"dataCategory","mongodb":"dataCategory","sql":"dataCategory"},"consentPurpose.legalBasis":{"convex":"legalBasis","drizzle":"legalBasis","prisma":"legalBasis","mongodb":"legalBasis","sql":"legalBasis"},"consentPurpose.isActive":{"convex":"isActive","drizzle":"isActive","prisma":"isActive","mongodb":"isActive","sql":"isActive"},"consentPurpose.createdAt":{"convex":"createdAt","drizzle":"createdAt","prisma":"createdAt","mongodb":"createdAt","sql":"createdAt"},"consentPurpose.updatedAt":{"convex":"updatedAt","drizzle":"updatedAt","prisma":"updatedAt","mongodb":"updatedAt","sql":"updatedAt"},"consent":{"convex":"consent","drizzle":"consent","prisma":"consent","mongodb":"consent","sql":"consent"},"consent.id":{"convex":"id","drizzle":"id","prisma":"id","mongodb":"_id","sql":"id"},"consent.subjectId":{"convex":"subjectId","drizzle":"subjectId","prisma":"subjectId","mongodb":"subjectId","sql":"subjectId"},"consent.domainId":{"convex":"domainId","drizzle":"domainId","prisma":"domainId","mongodb":"domainId","sql":"domainId"},"consent.policyId":{"convex":"policyId","drizzle":"policyId","prisma":"policyId","mongodb":"policyId","sql":"policyId"},"consent.purposeIds":{"convex":"purposeIds","drizzle":"purposeIds","prisma":"purposeIds","mongodb":"purposeIds","sql":"purposeIds"},"consent.metadata":{"convex":"metadata","drizzle":"metadata","prisma":"metadata","mongodb":"metadata","sql":"metadata"},"consent.ipAddress":{"convex":"ipAddress","drizzle":"ipAddress","prisma":"ipAddress","mongodb":"ipAddress","sql":"ipAddress"},"consent.userAgent":{"convex":"userAgent","drizzle":"userAgent","prisma":"userAgent","mongodb":"userAgent","sql":"userAgent"},"consent.status":{"convex":"status","drizzle":"status","prisma":"status","mongodb":"status","sql":"status"},"consent.withdrawalReason":{"convex":"withdrawalReason","drizzle":"withdrawalReason","prisma":"withdrawalReason","mongodb":"withdrawalReason","sql":"withdrawalReason"},"consent.givenAt":{"convex":"givenAt","drizzle":"givenAt","prisma":"givenAt","mongodb":"givenAt","sql":"givenAt"},"consent.validUntil":{"convex":"validUntil","drizzle":"validUntil","prisma":"validUntil","mongodb":"validUntil","sql":"validUntil"},"consent.isActive":{"convex":"isActive","drizzle":"isActive","prisma":"isActive","mongodb":"isActive","sql":"isActive"},"auditLog":{"convex":"auditLog","drizzle":"auditLog","prisma":"auditLog","mongodb":"auditLog","sql":"auditLog"},"auditLog.id":{"convex":"id","drizzle":"id","prisma":"id","mongodb":"_id","sql":"id"},"auditLog.entityType":{"convex":"entityType","drizzle":"entityType","prisma":"entityType","mongodb":"entityType","sql":"entityType"},"auditLog.entityId":{"convex":"entityId","drizzle":"entityId","prisma":"entityId","mongodb":"entityId","sql":"entityId"},"auditLog.actionType":{"convex":"actionType","drizzle":"actionType","prisma":"actionType","mongodb":"actionType","sql":"actionType"},"auditLog.subjectId":{"convex":"subjectId","drizzle":"subjectId","prisma":"subjectId","mongodb":"subjectId","sql":"subjectId"},"auditLog.ipAddress":{"convex":"ipAddress","drizzle":"ipAddress","prisma":"ipAddress","mongodb":"ipAddress","sql":"ipAddress"},"auditLog.userAgent":{"convex":"userAgent","drizzle":"userAgent","prisma":"userAgent","mongodb":"userAgent","sql":"userAgent"},"auditLog.changes":{"convex":"changes","drizzle":"changes","prisma":"changes","mongodb":"changes","sql":"changes"},"auditLog.metadata":{"convex":"metadata","drizzle":"metadata","prisma":"metadata","mongodb":"metadata","sql":"metadata"},"auditLog.createdAt":{"convex":"createdAt","drizzle":"createdAt","prisma":"createdAt","mongodb":"createdAt","sql":"createdAt"},"auditLog.eventTimezone":{"convex":"eventTimezone","drizzle":"eventTimezone","prisma":"eventTimezone","mongodb":"eventTimezone","sql":"eventTimezone"},"consentRecord":{"convex":"consentRecord","drizzle":"consentRecord","prisma":"consentRecord","mongodb":"consentRecord","sql":"consentRecord"},"consentRecord.id":{"convex":"id","drizzle":"id","prisma":"id","mongodb":"_id","sql":"id"},"consentRecord.subjectId":{"convex":"subjectId","drizzle":"subjectId","prisma":"subjectId","mongodb":"subjectId","sql":"subjectId"},"consentRecord.consentId":{"convex":"consentId","drizzle":"consentId","prisma":"consentId","mongodb":"consentId","sql":"consentId"},"consentRecord.actionType":{"convex":"actionType","drizzle":"actionType","prisma":"actionType","mongodb":"actionType","sql":"actionType"},"consentRecord.details":{"convex":"details","drizzle":"details","prisma":"details","mongodb":"details","sql":"details"},"consentRecord.createdAt":{"convex":"createdAt","drizzle":"createdAt","prisma":"createdAt","mongodb":"createdAt","sql":"createdAt"}}'),
('version', '1.0.0');
Converting timestamps to EPOCH milliseconds
If you want to update existing timestamps to EPOCH milliseconds, you can run the following SQL. It is best to test this beforehand on a backup to ensure it works as expected.
UPDATE consent
SET
givenAt = CAST(strftime('%s', givenAt) AS INTEGER) * 1000 + CAST(substr(givenAt, 21, 3) AS INTEGER)
WHERE
typeof(givenAt) = 'text'; -- Ensures only timestamps are updated (not EPOCH)