fix: make command constraint replay restart-safe
This commit is contained in:
@@ -16,6 +16,6 @@ alter table device_management_command_receipts
|
||||
'edge.ensure',
|
||||
'route.ensure',
|
||||
'enrollment_intent.ensure'
|
||||
));
|
||||
)) not valid;
|
||||
|
||||
commit;
|
||||
|
||||
@@ -20,6 +20,6 @@ alter table device_management_command_receipts
|
||||
'device.transfer',
|
||||
'discovery.reject',
|
||||
'discovery.expire'
|
||||
));
|
||||
)) not valid;
|
||||
|
||||
commit;
|
||||
|
||||
@@ -22,6 +22,6 @@ alter table device_management_command_receipts
|
||||
'discovery.expire',
|
||||
'device_credential_binding.upsert',
|
||||
'device_credential_binding.revoke'
|
||||
));
|
||||
)) not valid;
|
||||
|
||||
commit;
|
||||
|
||||
@@ -26,6 +26,6 @@ alter table device_management_command_receipts
|
||||
'device_binding.revoke',
|
||||
'device_configuration_revision.create',
|
||||
'device_configuration_desired.set'
|
||||
));
|
||||
)) not valid;
|
||||
|
||||
commit;
|
||||
|
||||
@@ -2,6 +2,36 @@ import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import test from "node:test";
|
||||
|
||||
const replayedIntermediateConstraintMigrations = Object.freeze([
|
||||
"005_device_registry_commands.sql",
|
||||
"007_device_lifecycle_commands.sql",
|
||||
"009_device_sensitive_reference_commands.sql",
|
||||
"011_device_control_resource_commands.sql",
|
||||
]);
|
||||
const finalCommandKindMigration = "014_device_registry_profile_commands.sql";
|
||||
const finalCommandKinds = Object.freeze([
|
||||
"owner_scope.ensure",
|
||||
"project.ensure",
|
||||
"collection.ensure",
|
||||
"project_grant.upsert",
|
||||
"adapter_package.ensure",
|
||||
"adapter_version.register",
|
||||
"model_profile.register",
|
||||
"edge.ensure",
|
||||
"route.ensure",
|
||||
"enrollment_intent.ensure",
|
||||
"device.claim",
|
||||
"device.update",
|
||||
"device.transfer",
|
||||
"discovery.reject",
|
||||
"discovery.expire",
|
||||
"device_credential_binding.upsert",
|
||||
"device_credential_binding.revoke",
|
||||
"device_binding.ensure",
|
||||
"device_binding.revoke",
|
||||
"device_configuration_revision.create",
|
||||
"device_configuration_desired.set",
|
||||
]);
|
||||
const migrationUrl = new URL(
|
||||
"../migrations/003_device_management_commands.sql",
|
||||
import.meta.url,
|
||||
@@ -37,3 +67,33 @@ test("repository applies management migration after project access", async () =>
|
||||
assert.notEqual(managementIndex, -1);
|
||||
assert.ok(projectAccessIndex < managementIndex);
|
||||
});
|
||||
|
||||
test("replayed intermediate command constraints do not revalidate historical receipts", async () => {
|
||||
for (const migrationFile of replayedIntermediateConstraintMigrations) {
|
||||
const sql = await readFile(
|
||||
new URL(`../migrations/${migrationFile}`, import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
assert.match(
|
||||
sql,
|
||||
/add constraint device_management_command_receipts_command_kind_check[\s\S]+not valid;/,
|
||||
`${migrationFile} must not reject receipts introduced by a later migration`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("final replayed command constraint validates every current command kind", async () => {
|
||||
const sql = await readFile(
|
||||
new URL(`../migrations/${finalCommandKindMigration}`, import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
assert.doesNotMatch(sql, /not valid;/);
|
||||
for (const commandKind of finalCommandKinds) {
|
||||
assert.ok(
|
||||
sql.includes(`'${commandKind}'`),
|
||||
`${finalCommandKindMigration} must validate ${commandKind}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user