myc

Self-custodial remote signer for Radroots apps
git clone https://radroots.dev/git/myc.git
Log | Files | Refs | README | LICENSE

state_catalog.rs (145232B)


      1 //! Immutable Myc schema and migration catalog identity.
      2 
      3 use core::fmt;
      4 use std::error::Error;
      5 
      6 use radroots_service_sqlite::{
      7     MigrationCatalog, MigrationChecksum, MigrationDescriptor, SchemaCatalog, SchemaDigest,
      8     SchemaObject, SchemaObjectKind, SchemaVersionCatalog,
      9 };
     10 
     11 /// The shared create-new baseline written before service migrations run.
     12 pub const MYC_STATE_BASE_SCHEMA_VERSION: u32 = 1;
     13 
     14 /// The newest governed Myc state schema understood by this binary.
     15 pub const MYC_STATE_SCHEMA_VERSION: u32 = 12;
     16 
     17 /// The shared metadata and migration-ledger objects present at schema v1.
     18 pub const MYC_STATE_SCHEMA_VERSION_1_OBJECT_COUNT: u32 = 6;
     19 
     20 /// The shared objects plus the three immutable Myc metadata objects at schema v2.
     21 pub const MYC_STATE_SCHEMA_VERSION_2_OBJECT_COUNT: u32 = 9;
     22 
     23 /// The shared objects plus Myc metadata and request-admission objects at schema v3.
     24 pub const MYC_STATE_SCHEMA_VERSION_3_OBJECT_COUNT: u32 = 13;
     25 
     26 /// The shared objects plus Myc metadata, request, and connection objects at schema v4.
     27 pub const MYC_STATE_SCHEMA_VERSION_4_OBJECT_COUNT: u32 = 25;
     28 
     29 /// The shared objects plus all Myc metadata, request, connection, and governance objects at v5.
     30 pub const MYC_STATE_SCHEMA_VERSION_5_OBJECT_COUNT: u32 = 34;
     31 
     32 /// The shared objects plus Myc metadata, request, connection, governance, and delivery objects.
     33 pub const MYC_STATE_SCHEMA_VERSION_6_OBJECT_COUNT: u32 = 43;
     34 
     35 /// The shared objects plus Myc discovery desired/current state and exact documents.
     36 pub const MYC_STATE_SCHEMA_VERSION_7_OBJECT_COUNT: u32 = 53;
     37 
     38 /// The shared objects plus immutable NIP-46 operation completion evidence.
     39 pub const MYC_STATE_SCHEMA_VERSION_8_OBJECT_COUNT: u32 = 56;
     40 
     41 /// The shared objects plus immutable exact NIP-46 response authority.
     42 pub const MYC_STATE_SCHEMA_VERSION_9_OBJECT_COUNT: u32 = 59;
     43 
     44 /// The shared objects plus the append-only configuration-binding history.
     45 pub const MYC_STATE_SCHEMA_VERSION_10_OBJECT_COUNT: u32 = 63;
     46 
     47 /// The shared objects plus the bounded admin-operation journal.
     48 pub const MYC_STATE_SCHEMA_VERSION_11_OBJECT_COUNT: u32 = 65;
     49 
     50 /// The shared objects plus immutable pending-approval response authority.
     51 pub const MYC_STATE_SCHEMA_VERSION_12_OBJECT_COUNT: u32 = 70;
     52 
     53 /// SHA-256 identity of the exact schema-v1 object snapshot.
     54 pub const MYC_STATE_SCHEMA_VERSION_1_SHA256: [u8; 32] = [
     55     0x94, 0xdc, 0x66, 0xfb, 0xca, 0x60, 0x16, 0x79, 0x61, 0x5c, 0x05, 0x52, 0x29, 0xdc, 0x0d, 0xb6,
     56     0x11, 0x9f, 0x5b, 0xd9, 0x2b, 0x04, 0x39, 0x0c, 0x67, 0xf6, 0x98, 0xa0, 0x36, 0xfa, 0x78, 0xae,
     57 ];
     58 
     59 /// SHA-256 identity of the schema-v2 object snapshot.
     60 pub const MYC_STATE_SCHEMA_VERSION_2_SHA256: [u8; 32] = [
     61     0x94, 0x73, 0x9b, 0x5a, 0x34, 0xca, 0x8e, 0xd1, 0x30, 0xb9, 0x46, 0xd0, 0x92, 0x73, 0x1b, 0x59,
     62     0xbf, 0x15, 0x48, 0xfe, 0x54, 0x1d, 0x9a, 0x92, 0x69, 0xa3, 0x3d, 0x0a, 0xed, 0x1e, 0xa0, 0x9e,
     63 ];
     64 
     65 /// SHA-256 identity of the ordered Myc migration catalog.
     66 pub const MYC_MIGRATION_CATALOG_SHA256: [u8; 32] = [
     67     0xb1, 0xd6, 0x45, 0x82, 0x45, 0xe6, 0xdf, 0xc4, 0x66, 0x1a, 0xa6, 0x14, 0x6b, 0x8c, 0xe8, 0xab,
     68     0x55, 0xf7, 0xc2, 0x9b, 0xf3, 0x60, 0x99, 0xd2, 0x61, 0xc0, 0x7f, 0x5f, 0x51, 0x67, 0x56, 0x1d,
     69 ];
     70 
     71 /// SHA-256 identity of the schema catalog bound to the migration catalog.
     72 pub const MYC_STATE_SCHEMA_CATALOG_SHA256: [u8; 32] = [
     73     0xb5, 0x27, 0x21, 0xd8, 0x5c, 0x1e, 0xb8, 0xcd, 0xdc, 0x28, 0x25, 0x6c, 0x21, 0x17, 0x9a, 0x10,
     74     0xd5, 0xf3, 0x2b, 0xcb, 0x33, 0xe9, 0xd2, 0xa6, 0xbb, 0x8f, 0xe4, 0x9e, 0xcb, 0xc4, 0x9a, 0x68,
     75 ];
     76 
     77 /// SHA-256 identity of the schema-v2 migration content.
     78 pub const MYC_STATE_SCHEMA_VERSION_2_MIGRATION_SHA256: [u8; 32] = [
     79     0xc5, 0xeb, 0x97, 0x8b, 0xda, 0x1b, 0xc7, 0x0c, 0x70, 0xbd, 0x9b, 0xd4, 0x4d, 0x8c, 0xba, 0x70,
     80     0xcb, 0x28, 0x57, 0xd2, 0x6a, 0x9d, 0xce, 0x74, 0x96, 0x1f, 0x4b, 0x78, 0x1e, 0x71, 0x00, 0x37,
     81 ];
     82 
     83 /// SHA-256 identity of the schema-v3 migration content.
     84 pub const MYC_STATE_SCHEMA_VERSION_3_MIGRATION_SHA256: [u8; 32] = [
     85     0x75, 0x31, 0x65, 0x13, 0x6b, 0x3d, 0xac, 0xe0, 0x09, 0x1d, 0x78, 0x2f, 0x33, 0xf6, 0xb1, 0x0c,
     86     0xa1, 0xa2, 0x82, 0x33, 0x14, 0x15, 0x8d, 0x80, 0xa4, 0x77, 0x5e, 0x0a, 0xf6, 0x28, 0xed, 0xf9,
     87 ];
     88 
     89 /// SHA-256 identity of the schema-v3 object snapshot.
     90 pub const MYC_STATE_SCHEMA_VERSION_3_SHA256: [u8; 32] = [
     91     0x57, 0x2f, 0xe6, 0xa4, 0xd3, 0x6c, 0x04, 0x76, 0xec, 0x40, 0x53, 0x6f, 0x48, 0x02, 0x8e, 0x15,
     92     0x58, 0x48, 0x8f, 0xb8, 0xab, 0xeb, 0xa0, 0xa3, 0x4b, 0xa6, 0x9b, 0x4b, 0x70, 0x80, 0xba, 0x08,
     93 ];
     94 
     95 /// SHA-256 identity of the schema-v4 migration content.
     96 pub const MYC_STATE_SCHEMA_VERSION_4_MIGRATION_SHA256: [u8; 32] = [
     97     0x93, 0x9c, 0x0e, 0xd0, 0x7c, 0xd1, 0x5c, 0xc0, 0xc7, 0x94, 0xbf, 0x6c, 0x2a, 0xf7, 0x19, 0x22,
     98     0x61, 0x40, 0x93, 0x05, 0xc2, 0x87, 0x6f, 0x3b, 0xe3, 0x63, 0xe8, 0xe4, 0xfe, 0x4a, 0x1a, 0xbb,
     99 ];
    100 
    101 /// SHA-256 identity of the schema-v4 object snapshot.
    102 pub const MYC_STATE_SCHEMA_VERSION_4_SHA256: [u8; 32] = [
    103     0x47, 0x98, 0x63, 0xd3, 0x7d, 0x91, 0xe6, 0xc2, 0x69, 0xfa, 0x35, 0x73, 0xdb, 0x6c, 0x2e, 0x76,
    104     0x7c, 0xdd, 0x3b, 0x24, 0xa9, 0x3a, 0xb4, 0x82, 0xd7, 0x74, 0xbc, 0xec, 0x02, 0x18, 0xc1, 0x74,
    105 ];
    106 
    107 /// SHA-256 identity of the schema-v5 migration content.
    108 pub const MYC_STATE_SCHEMA_VERSION_5_MIGRATION_SHA256: [u8; 32] = [
    109     0x0e, 0x00, 0x4f, 0xcb, 0x5d, 0x0b, 0xc7, 0xc9, 0x51, 0xb1, 0x6f, 0x43, 0x34, 0x53, 0x3d, 0x10,
    110     0xef, 0xcb, 0x18, 0xa8, 0x26, 0xf6, 0x24, 0xde, 0x09, 0x22, 0xd8, 0x6d, 0xc8, 0x50, 0x4b, 0x33,
    111 ];
    112 
    113 /// SHA-256 identity of the schema-v5 object snapshot.
    114 pub const MYC_STATE_SCHEMA_VERSION_5_SHA256: [u8; 32] = [
    115     0xfe, 0x89, 0xd4, 0xaf, 0x7d, 0xe4, 0xed, 0xed, 0x78, 0xa3, 0xf0, 0x62, 0xdc, 0x9d, 0x30, 0x0f,
    116     0x06, 0xcf, 0x0f, 0x4c, 0xfc, 0xa5, 0xfa, 0x5c, 0xff, 0xc9, 0x3a, 0xf1, 0x14, 0x6f, 0x21, 0xc5,
    117 ];
    118 
    119 /// SHA-256 identity of the schema-v6 delivery-state migration.
    120 pub const MYC_STATE_SCHEMA_VERSION_6_MIGRATION_SHA256: [u8; 32] = [
    121     0x46, 0x49, 0xb9, 0xaf, 0xd0, 0x3f, 0xc0, 0x7f, 0x89, 0xfe, 0x18, 0x4f, 0x02, 0x79, 0x25, 0x67,
    122     0x5a, 0x02, 0x65, 0x95, 0x1e, 0xa7, 0xcf, 0x75, 0xe0, 0x6a, 0x43, 0x12, 0xc5, 0x5a, 0x82, 0xbd,
    123 ];
    124 
    125 /// SHA-256 identity of the schema-v6 object snapshot.
    126 pub const MYC_STATE_SCHEMA_VERSION_6_SHA256: [u8; 32] = [
    127     0x55, 0x72, 0x73, 0x30, 0x6e, 0x68, 0xe9, 0x30, 0x6d, 0xc1, 0xd7, 0xc7, 0x00, 0x9e, 0x1c, 0xb7,
    128     0xc9, 0xd1, 0x5b, 0x8d, 0x52, 0xe0, 0x7d, 0xb7, 0xd0, 0xbd, 0x51, 0xe8, 0x3f, 0x05, 0x44, 0x92,
    129 ];
    130 
    131 /// SHA-256 identity of the schema-v7 discovery-state migration.
    132 pub const MYC_STATE_SCHEMA_VERSION_7_MIGRATION_SHA256: [u8; 32] = [
    133     0x60, 0x97, 0xc4, 0x07, 0x76, 0xa5, 0x7d, 0xd4, 0xbd, 0xdc, 0x04, 0xe6, 0x52, 0x98, 0x72, 0x17,
    134     0xd6, 0xf5, 0x99, 0x1f, 0x2d, 0x5e, 0x94, 0xd3, 0x22, 0xd1, 0x20, 0x86, 0x19, 0x25, 0x4e, 0x6c,
    135 ];
    136 
    137 /// SHA-256 identity of the schema-v7 object snapshot.
    138 pub const MYC_STATE_SCHEMA_VERSION_7_SHA256: [u8; 32] = [
    139     0x3b, 0x35, 0x28, 0x91, 0x1a, 0x29, 0x34, 0x99, 0xd9, 0x72, 0x1d, 0xa7, 0x1b, 0x6a, 0xd0, 0x7a,
    140     0x5e, 0x72, 0x3e, 0x97, 0xb6, 0xeb, 0xf5, 0xb4, 0x0a, 0x19, 0xb9, 0x05, 0x89, 0x58, 0xbf, 0x79,
    141 ];
    142 
    143 /// SHA-256 identity of the schema-v8 operation-completion migration.
    144 pub const MYC_STATE_SCHEMA_VERSION_8_MIGRATION_SHA256: [u8; 32] = [
    145     0xb8, 0x1f, 0x98, 0x0c, 0x91, 0xac, 0xd9, 0x8b, 0x91, 0xec, 0xd5, 0xcb, 0x24, 0x8e, 0x40, 0x27,
    146     0xc9, 0xf4, 0x7c, 0x1d, 0xc8, 0xd0, 0x13, 0x4a, 0x61, 0xaf, 0x5c, 0x38, 0x23, 0x83, 0x15, 0xbc,
    147 ];
    148 
    149 /// SHA-256 identity of the schema-v8 object snapshot.
    150 pub const MYC_STATE_SCHEMA_VERSION_8_SHA256: [u8; 32] = [
    151     0x50, 0x15, 0x8c, 0xb0, 0x93, 0xed, 0x70, 0xb3, 0xd5, 0x78, 0x37, 0x62, 0xb1, 0x8d, 0x21, 0xb7,
    152     0x80, 0x96, 0x65, 0xc8, 0x9f, 0xde, 0x92, 0x5d, 0x87, 0x23, 0x65, 0x90, 0x9d, 0x28, 0xf0, 0x6e,
    153 ];
    154 
    155 /// SHA-256 identity of the schema-v9 atomic response migration.
    156 pub const MYC_STATE_SCHEMA_VERSION_9_MIGRATION_SHA256: [u8; 32] = [
    157     0xfd, 0xb0, 0x39, 0xd4, 0x72, 0xcd, 0x62, 0xe7, 0xda, 0x46, 0xc4, 0x0a, 0x97, 0x86, 0xc3, 0xa9,
    158     0xa7, 0xec, 0x55, 0xf2, 0xae, 0x7d, 0xb6, 0x89, 0xd0, 0xf8, 0x55, 0xfb, 0xbf, 0x8a, 0x95, 0x66,
    159 ];
    160 
    161 /// SHA-256 identity of the schema-v9 object snapshot.
    162 pub const MYC_STATE_SCHEMA_VERSION_9_SHA256: [u8; 32] = [
    163     0xee, 0xe7, 0x6f, 0x4f, 0xf0, 0xbd, 0x2d, 0xc2, 0xc0, 0x61, 0xae, 0x38, 0x4e, 0x00, 0xde, 0x16,
    164     0xc5, 0xf5, 0xef, 0xc4, 0xb6, 0xed, 0xd0, 0xac, 0x7f, 0x73, 0xca, 0xd8, 0x3a, 0x99, 0x1f, 0xf7,
    165 ];
    166 
    167 /// SHA-256 identity of the schema-v10 configuration-binding migration.
    168 pub const MYC_STATE_SCHEMA_VERSION_10_MIGRATION_SHA256: [u8; 32] = [
    169     0x28, 0x42, 0x3e, 0xbb, 0x59, 0xf4, 0xb2, 0x62, 0x23, 0x30, 0x7b, 0x74, 0xa7, 0xe1, 0x29, 0x05,
    170     0xca, 0x48, 0x18, 0xc0, 0x1a, 0x65, 0x52, 0x03, 0xee, 0x8d, 0x63, 0xc9, 0x11, 0xf4, 0x44, 0x89,
    171 ];
    172 
    173 /// SHA-256 identity of the schema-v10 object snapshot.
    174 pub const MYC_STATE_SCHEMA_VERSION_10_SHA256: [u8; 32] = [
    175     0xb7, 0x7e, 0xd2, 0x3a, 0xfa, 0x39, 0xff, 0x45, 0xdd, 0xa2, 0x50, 0xfa, 0xa1, 0xeb, 0xfc, 0x05,
    176     0x87, 0xc3, 0x44, 0x62, 0x65, 0x8f, 0xc4, 0x9f, 0xb7, 0xb2, 0xfb, 0xc8, 0x90, 0x9b, 0xa3, 0x03,
    177 ];
    178 
    179 /// SHA-256 identity of the schema-v11 admin-operation journal migration.
    180 pub const MYC_STATE_SCHEMA_VERSION_11_MIGRATION_SHA256: [u8; 32] = [
    181     0x16, 0x38, 0x53, 0x68, 0xaa, 0x4e, 0xe4, 0x0e, 0xa7, 0x00, 0x2a, 0x0a, 0xb4, 0x26, 0x45, 0xbc,
    182     0x68, 0xb5, 0x46, 0xa4, 0xba, 0x6a, 0xfd, 0xfe, 0xde, 0x56, 0x5f, 0xe0, 0x26, 0x57, 0x6c, 0x96,
    183 ];
    184 
    185 /// SHA-256 identity of the schema-v12 pending-approval response migration.
    186 pub const MYC_STATE_SCHEMA_VERSION_12_MIGRATION_SHA256: [u8; 32] = [
    187     0x38, 0x8e, 0xe5, 0x1d, 0xe5, 0x99, 0xf3, 0x7b, 0x7b, 0xb1, 0x95, 0x6c, 0xeb, 0xd5, 0x18, 0x46,
    188     0x1f, 0x3e, 0xb1, 0x93, 0x53, 0x5f, 0xfe, 0x6b, 0xb9, 0xea, 0xc2, 0xd8, 0x2b, 0xbe, 0x3e, 0x37,
    189 ];
    190 
    191 /// SHA-256 identity of the schema-v12 object snapshot.
    192 pub const MYC_STATE_SCHEMA_VERSION_12_SHA256: [u8; 32] = [
    193     0xd8, 0x93, 0xa2, 0x3b, 0xa6, 0x8e, 0x46, 0x34, 0x89, 0xad, 0x7e, 0xf1, 0xe6, 0xa8, 0x0e, 0xa4,
    194     0xe8, 0x80, 0x89, 0x38, 0x1c, 0x73, 0xde, 0xcc, 0x32, 0x43, 0xa4, 0xce, 0x6f, 0x64, 0xda, 0x8f,
    195 ];
    196 
    197 /// SHA-256 identity of the schema-v11 object snapshot.
    198 pub const MYC_STATE_SCHEMA_VERSION_11_SHA256: [u8; 32] = [
    199     0x0d, 0xe7, 0xfe, 0x17, 0x6e, 0xa7, 0xda, 0x60, 0x30, 0x42, 0x4a, 0xdd, 0xc2, 0x9b, 0x9a, 0x91,
    200     0x36, 0x3e, 0x88, 0xb0, 0x4d, 0xc7, 0x8d, 0xda, 0xb4, 0x80, 0xfd, 0x0f, 0x0a, 0xf9, 0x4e, 0x5a,
    201 ];
    202 
    203 /// SHA-256 identity of the Myc metadata table definition.
    204 const MYC_STATE_METADATA_TABLE_SHA256: [u8; 32] = [
    205     0x16, 0x17, 0x46, 0xa2, 0x26, 0x42, 0x46, 0x2f, 0x2b, 0xdb, 0x08, 0x5b, 0xae, 0xde, 0xb2, 0x3b,
    206     0xb2, 0x83, 0xee, 0xbe, 0x8b, 0xcc, 0x95, 0x72, 0x38, 0xad, 0xaa, 0x30, 0x78, 0xc0, 0x29, 0x1a,
    207 ];
    208 
    209 /// SHA-256 identity of the Myc metadata update guard.
    210 const MYC_STATE_METADATA_NO_UPDATE_SHA256: [u8; 32] = [
    211     0xf0, 0xe3, 0x30, 0xf2, 0x19, 0x63, 0xd4, 0x94, 0xf8, 0x02, 0xf3, 0x55, 0x78, 0x4b, 0x45, 0x1c,
    212     0xde, 0x2b, 0xd2, 0xc8, 0x0d, 0x90, 0x22, 0x33, 0x0e, 0x61, 0x03, 0x97, 0xd4, 0x3c, 0xbe, 0x08,
    213 ];
    214 
    215 /// SHA-256 identity of the Myc metadata delete guard.
    216 const MYC_STATE_METADATA_NO_DELETE_SHA256: [u8; 32] = [
    217     0x05, 0x32, 0x87, 0x93, 0x6d, 0xbb, 0xae, 0x52, 0x0b, 0xff, 0x25, 0xfe, 0x87, 0xd5, 0xd2, 0xd1,
    218     0xa3, 0xcc, 0xf2, 0x81, 0xc3, 0x5b, 0x14, 0xa0, 0x24, 0xa7, 0x74, 0xa5, 0x67, 0x50, 0x3d, 0x4c,
    219 ];
    220 
    221 const NIP46_REQUESTS_TABLE_SHA256: [u8; 32] = [
    222     0x7a, 0x62, 0x77, 0xaa, 0xa9, 0x71, 0x62, 0x2c, 0x1c, 0x7e, 0x0c, 0x0f, 0xab, 0x62, 0xe7, 0xfc,
    223     0xfa, 0xea, 0x1b, 0x1d, 0x6f, 0x20, 0xda, 0x14, 0x7a, 0x93, 0xc7, 0x80, 0x6d, 0xd4, 0xaa, 0x54,
    224 ];
    225 const NIP46_REQUEST_DEDUP_TABLE_SHA256: [u8; 32] = [
    226     0x1d, 0xe1, 0x60, 0xcb, 0x35, 0xd1, 0x84, 0x66, 0x60, 0xda, 0xfc, 0xa4, 0xae, 0x26, 0x51, 0x12,
    227     0xd1, 0x4a, 0xa9, 0x19, 0x7e, 0xf3, 0x7f, 0x2a, 0x5a, 0xd7, 0xdf, 0x3d, 0xfe, 0x36, 0xd7, 0x65,
    228 ];
    229 const NIP46_REQUESTS_NO_UPDATE_SHA256: [u8; 32] = [
    230     0x26, 0xfb, 0x6f, 0x52, 0x78, 0x7e, 0x07, 0x8a, 0x4a, 0xb9, 0x2f, 0xa1, 0x19, 0xf4, 0x65, 0x42,
    231     0x18, 0xea, 0x3d, 0x61, 0xad, 0x58, 0xb2, 0x01, 0x3a, 0x99, 0x0e, 0xbc, 0xc9, 0xd7, 0x6b, 0x35,
    232 ];
    233 const NIP46_REQUEST_DEDUP_GUARD_UPDATE_SHA256: [u8; 32] = [
    234     0x47, 0x57, 0x86, 0x7c, 0x88, 0xe8, 0xec, 0x05, 0x0c, 0xa5, 0x3d, 0x64, 0x79, 0xae, 0x22, 0xb4,
    235     0x9a, 0x11, 0xa4, 0xff, 0x39, 0x32, 0xd9, 0xa3, 0x88, 0x80, 0xd3, 0x1d, 0x7e, 0x7a, 0x94, 0x6c,
    236 ];
    237 
    238 macro_rules! myc_state_metadata_table_sql {
    239     () => {
    240         r#"CREATE TABLE myc_state_metadata (
    241     singleton INTEGER NOT NULL PRIMARY KEY CHECK (singleton = 1),
    242     normalized_config_sha256 BLOB NOT NULL CHECK (length(normalized_config_sha256) = 32),
    243     transport_public_key TEXT NOT NULL
    244         CHECK (length(CAST(transport_public_key AS BLOB)) = 64)
    245         CHECK (transport_public_key NOT GLOB '*[^0-9a-f]*'),
    246     user_public_key TEXT NOT NULL
    247         CHECK (length(CAST(user_public_key AS BLOB)) = 64)
    248         CHECK (user_public_key NOT GLOB '*[^0-9a-f]*'),
    249     discovery_public_key TEXT
    250         CHECK (discovery_public_key IS NULL OR (
    251             length(CAST(discovery_public_key AS BLOB)) = 64
    252             AND discovery_public_key NOT GLOB '*[^0-9a-f]*'
    253         )),
    254     config_contract_version INTEGER NOT NULL
    255         CHECK (config_contract_version BETWEEN 1 AND 4294967295),
    256     state_contract_version INTEGER NOT NULL
    257         CHECK (state_contract_version BETWEEN 1 AND 4294967295),
    258     operator_contract_version INTEGER NOT NULL
    259         CHECK (operator_contract_version BETWEEN 1 AND 4294967295),
    260     status_contract_version INTEGER NOT NULL
    261         CHECK (status_contract_version BETWEEN 1 AND 4294967295)
    262 ) STRICT"#
    263     };
    264 }
    265 
    266 macro_rules! myc_state_metadata_no_update_sql {
    267     () => {
    268         r#"CREATE TRIGGER myc_state_metadata_no_update
    269 BEFORE UPDATE ON myc_state_metadata
    270 BEGIN
    271     SELECT RAISE(ABORT, 'Myc state metadata is immutable');
    272 END"#
    273     };
    274 }
    275 
    276 macro_rules! myc_state_metadata_no_delete_sql {
    277     () => {
    278         r#"CREATE TRIGGER myc_state_metadata_no_delete
    279 BEFORE DELETE ON myc_state_metadata
    280 BEGIN
    281     SELECT RAISE(ABORT, 'Myc state metadata is immutable');
    282 END"#
    283     };
    284 }
    285 
    286 const CREATE_MYC_STATE_METADATA_TABLE_SQL: &str = myc_state_metadata_table_sql!();
    287 const CREATE_MYC_STATE_METADATA_NO_UPDATE_SQL: &str = myc_state_metadata_no_update_sql!();
    288 const CREATE_MYC_STATE_METADATA_NO_DELETE_SQL: &str = myc_state_metadata_no_delete_sql!();
    289 
    290 const CREATE_MYC_STATE_METADATA_MIGRATION_SQL: &str = concat!(
    291     myc_state_metadata_table_sql!(),
    292     ";\n",
    293     myc_state_metadata_no_update_sql!(),
    294     ";\n",
    295     myc_state_metadata_no_delete_sql!(),
    296 );
    297 
    298 macro_rules! nip46_requests_table_sql {
    299     () => {
    300         r#"CREATE TABLE nip46_requests (
    301     operation_id BLOB NOT NULL PRIMARY KEY CHECK (length(operation_id) = 32),
    302     correlation_id BLOB NOT NULL UNIQUE CHECK (length(correlation_id) = 32),
    303     operation_nonce BLOB NOT NULL CHECK (length(operation_nonce) = 32),
    304     request_identity_sha256 BLOB NOT NULL UNIQUE CHECK (length(request_identity_sha256) = 32),
    305     client_public_key TEXT NOT NULL
    306         CHECK (length(CAST(client_public_key AS BLOB)) = 64)
    307         CHECK (client_public_key NOT GLOB '*[^0-9a-f]*'),
    308     request_id TEXT NOT NULL
    309         CHECK (length(CAST(request_id AS BLOB)) BETWEEN 1 AND 128),
    310     first_event_id BLOB NOT NULL CHECK (length(first_event_id) = 32),
    311     method TEXT NOT NULL CHECK (method IN (
    312         'connect',
    313         'get_public_key',
    314         'get_session_capability',
    315         'sign_event',
    316         'nip04_encrypt',
    317         'nip04_decrypt',
    318         'nip44_encrypt',
    319         'nip44_decrypt',
    320         'ping',
    321         'switch_relays',
    322         'logout'
    323     )),
    324     request_sha256 BLOB NOT NULL CHECK (length(request_sha256) = 32),
    325     received_at_unix_ms INTEGER NOT NULL
    326         CHECK (received_at_unix_ms BETWEEN 1 AND 9223372036854775807)
    327 ) STRICT"#
    328     };
    329 }
    330 
    331 macro_rules! nip46_request_dedup_table_sql {
    332     () => {
    333         r#"CREATE TABLE nip46_request_dedup (
    334     dedup_kind TEXT NOT NULL CHECK (dedup_kind IN ('request', 'event')),
    335     identity_sha256 BLOB NOT NULL CHECK (length(identity_sha256) = 32),
    336     request_sha256 BLOB NOT NULL CHECK (length(request_sha256) = 32),
    337     operation_id BLOB NOT NULL CHECK (length(operation_id) = 32)
    338         REFERENCES nip46_requests(operation_id),
    339     replay_count INTEGER NOT NULL CHECK (replay_count BETWEEN 0 AND 9223372036854775807),
    340     conflict_count INTEGER NOT NULL CHECK (conflict_count BETWEEN 0 AND 9223372036854775807),
    341     first_seen_at_unix_ms INTEGER NOT NULL
    342         CHECK (first_seen_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    343     last_seen_at_unix_ms INTEGER NOT NULL
    344         CHECK (last_seen_at_unix_ms BETWEEN first_seen_at_unix_ms AND 9223372036854775807),
    345     PRIMARY KEY (dedup_kind, identity_sha256)
    346 ) STRICT"#
    347     };
    348 }
    349 
    350 macro_rules! nip46_requests_no_update_sql {
    351     () => {
    352         r#"CREATE TRIGGER nip46_requests_no_update
    353 BEFORE UPDATE ON nip46_requests
    354 BEGIN
    355     SELECT RAISE(ABORT, 'NIP-46 request identity is immutable');
    356 END"#
    357     };
    358 }
    359 
    360 macro_rules! nip46_request_dedup_guard_update_sql {
    361     () => {
    362         r#"CREATE TRIGGER nip46_request_dedup_guard_update
    363 BEFORE UPDATE ON nip46_request_dedup
    364 WHEN NEW.dedup_kind != OLD.dedup_kind
    365     OR NEW.identity_sha256 != OLD.identity_sha256
    366     OR NEW.request_sha256 != OLD.request_sha256
    367     OR NEW.operation_id != OLD.operation_id
    368     OR NEW.first_seen_at_unix_ms != OLD.first_seen_at_unix_ms
    369     OR NEW.last_seen_at_unix_ms < OLD.last_seen_at_unix_ms
    370     OR NOT (
    371         (
    372             OLD.replay_count < 9223372036854775807
    373             AND NEW.replay_count = OLD.replay_count + 1
    374             AND NEW.conflict_count = OLD.conflict_count
    375         ) OR (
    376             OLD.conflict_count < 9223372036854775807
    377             AND NEW.conflict_count = OLD.conflict_count + 1
    378             AND NEW.replay_count = OLD.replay_count
    379         )
    380     )
    381 BEGIN
    382     SELECT RAISE(ABORT, 'NIP-46 request evidence is append-only');
    383 END"#
    384     };
    385 }
    386 
    387 const CREATE_NIP46_REQUESTS_TABLE_SQL: &str = nip46_requests_table_sql!();
    388 const CREATE_NIP46_REQUEST_DEDUP_TABLE_SQL: &str = nip46_request_dedup_table_sql!();
    389 const CREATE_NIP46_REQUESTS_NO_UPDATE_SQL: &str = nip46_requests_no_update_sql!();
    390 const CREATE_NIP46_REQUEST_DEDUP_GUARD_UPDATE_SQL: &str = nip46_request_dedup_guard_update_sql!();
    391 
    392 const CREATE_NIP46_REQUEST_ADMISSION_MIGRATION_SQL: &str = concat!(
    393     "DROP TRIGGER myc_state_metadata_no_update;\n",
    394     "UPDATE myc_state_metadata SET state_contract_version = CASE ",
    395     "WHEN state_contract_version = 2 THEN 3 ELSE 0 END WHERE singleton = 1;\n",
    396     myc_state_metadata_no_update_sql!(),
    397     ";\n",
    398     nip46_requests_table_sql!(),
    399     ";\n",
    400     nip46_request_dedup_table_sql!(),
    401     ";\n",
    402     nip46_requests_no_update_sql!(),
    403     ";\n",
    404     nip46_request_dedup_guard_update_sql!(),
    405 );
    406 
    407 macro_rules! connections_table_sql {
    408     () => {
    409         r#"CREATE TABLE connections (
    410     connection_id BLOB NOT NULL PRIMARY KEY CHECK (length(connection_id) = 32),
    411     connection_nonce BLOB NOT NULL CHECK (length(connection_nonce) = 32),
    412     client_public_key TEXT NOT NULL
    413         CHECK (length(CAST(client_public_key AS BLOB)) = 64)
    414         CHECK (client_public_key NOT GLOB '*[^0-9a-f]*'),
    415     requested_permissions_sha256 BLOB NOT NULL
    416         CHECK (length(requested_permissions_sha256) = 32),
    417     policy_generation INTEGER NOT NULL
    418         CHECK (policy_generation BETWEEN 1 AND 9223372036854775807),
    419     status TEXT NOT NULL CHECK (status IN ('pending', 'active', 'denied', 'expired')),
    420     created_at_unix_ms INTEGER NOT NULL
    421         CHECK (created_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    422     updated_at_unix_ms INTEGER NOT NULL
    423         CHECK (updated_at_unix_ms BETWEEN created_at_unix_ms AND 9223372036854775807),
    424     authorized_until_unix_ms INTEGER
    425         CHECK (authorized_until_unix_ms IS NULL OR
    426             authorized_until_unix_ms BETWEEN created_at_unix_ms + 1 AND 9223372036854775807),
    427     CHECK ((status = 'active') OR authorized_until_unix_ms IS NULL)
    428 ) STRICT"#
    429     };
    430 }
    431 
    432 macro_rules! connection_permissions_table_sql {
    433     () => {
    434         r#"CREATE TABLE connection_permissions (
    435     connection_id BLOB NOT NULL CHECK (length(connection_id) = 32)
    436         REFERENCES connections(connection_id),
    437     permission_scope TEXT NOT NULL CHECK (permission_scope IN ('requested', 'granted')),
    438     permission_code TEXT NOT NULL
    439         CHECK (length(CAST(permission_code AS BLOB)) BETWEEN 1 AND 64),
    440     PRIMARY KEY (connection_id, permission_scope, permission_code)
    441 ) STRICT"#
    442     };
    443 }
    444 
    445 macro_rules! nip46_request_decisions_table_sql {
    446     () => {
    447         r#"CREATE TABLE nip46_request_decisions (
    448     operation_id BLOB NOT NULL PRIMARY KEY CHECK (length(operation_id) = 32)
    449         REFERENCES nip46_requests(operation_id),
    450     connection_id BLOB CHECK (connection_id IS NULL OR length(connection_id) = 32)
    451         REFERENCES connections(connection_id),
    452     decision TEXT NOT NULL
    453         CHECK (decision IN ('pending_approval', 'challenged', 'allowed', 'denied')),
    454     reason_code TEXT NOT NULL CHECK (reason_code IN (
    455         'explicit_approval_required',
    456         'trusted_client',
    457         'policy_denied',
    458         'operator_approved',
    459         'operator_denied',
    460         'authorization_challenge_required',
    461         'authorization_challenge_authorized',
    462         'authorization_challenge_expired'
    463     )),
    464     policy_generation INTEGER NOT NULL
    465         CHECK (policy_generation BETWEEN 1 AND 9223372036854775807),
    466     requested_permissions_sha256 BLOB NOT NULL
    467         CHECK (length(requested_permissions_sha256) = 32),
    468     challenge_id BLOB UNIQUE CHECK (challenge_id IS NULL OR length(challenge_id) = 32)
    469         REFERENCES connection_auth_challenges(challenge_id),
    470     decided_at_unix_ms INTEGER NOT NULL
    471         CHECK (decided_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    472     CHECK (
    473         (decision = 'denied' AND reason_code = 'policy_denied'
    474             AND connection_id IS NULL AND challenge_id IS NULL)
    475         OR (decision = 'pending_approval' AND reason_code = 'explicit_approval_required'
    476             AND connection_id IS NOT NULL AND challenge_id IS NULL)
    477         OR (decision = 'allowed' AND reason_code IN ('trusted_client', 'operator_approved')
    478             AND connection_id IS NOT NULL AND challenge_id IS NULL)
    479         OR (decision = 'denied' AND reason_code = 'operator_denied'
    480             AND connection_id IS NOT NULL AND challenge_id IS NULL)
    481         OR (decision = 'challenged' AND reason_code = 'authorization_challenge_required'
    482             AND connection_id IS NOT NULL AND challenge_id IS NOT NULL)
    483         OR (decision = 'allowed' AND reason_code = 'authorization_challenge_authorized'
    484             AND connection_id IS NOT NULL AND challenge_id IS NOT NULL)
    485         OR (decision = 'denied' AND reason_code = 'authorization_challenge_expired'
    486             AND connection_id IS NOT NULL AND challenge_id IS NOT NULL)
    487     )
    488 ) STRICT"#
    489     };
    490 }
    491 
    492 macro_rules! connection_auth_challenges_table_sql {
    493     () => {
    494         r#"CREATE TABLE connection_auth_challenges (
    495     challenge_id BLOB NOT NULL PRIMARY KEY CHECK (length(challenge_id) = 32),
    496     challenge_nonce BLOB NOT NULL CHECK (length(challenge_nonce) = 32),
    497     connection_id BLOB NOT NULL CHECK (length(connection_id) = 32)
    498         REFERENCES connections(connection_id),
    499     operation_id BLOB NOT NULL UNIQUE CHECK (length(operation_id) = 32)
    500         REFERENCES nip46_requests(operation_id),
    501     policy_generation INTEGER NOT NULL
    502         CHECK (policy_generation BETWEEN 1 AND 9223372036854775807),
    503     challenge_url TEXT NOT NULL
    504         CHECK (length(CAST(challenge_url AS BLOB)) BETWEEN 1 AND 2048),
    505     state TEXT NOT NULL CHECK (state IN ('pending', 'authorized', 'expired')),
    506     issued_at_unix_ms INTEGER NOT NULL
    507         CHECK (issued_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    508     expires_at_unix_ms INTEGER NOT NULL
    509         CHECK (expires_at_unix_ms BETWEEN issued_at_unix_ms + 1 AND 9223372036854775807),
    510     resolved_at_unix_ms INTEGER
    511         CHECK (resolved_at_unix_ms IS NULL OR
    512             resolved_at_unix_ms BETWEEN issued_at_unix_ms AND 9223372036854775807),
    513     CHECK ((state = 'pending' AND resolved_at_unix_ms IS NULL)
    514         OR (state IN ('authorized', 'expired') AND resolved_at_unix_ms IS NOT NULL))
    515 ) STRICT"#
    516     };
    517 }
    518 
    519 macro_rules! connections_guard_update_sql {
    520     () => {
    521         r#"CREATE TRIGGER connections_guard_update
    522 BEFORE UPDATE ON connections
    523 WHEN NEW.connection_id != OLD.connection_id
    524     OR NEW.connection_nonce != OLD.connection_nonce
    525     OR NEW.client_public_key != OLD.client_public_key
    526     OR NEW.requested_permissions_sha256 != OLD.requested_permissions_sha256
    527     OR NEW.policy_generation != OLD.policy_generation
    528     OR NEW.created_at_unix_ms != OLD.created_at_unix_ms
    529     OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms
    530     OR NOT (
    531         (OLD.status = 'pending' AND NEW.status = 'active'
    532             AND (NEW.authorized_until_unix_ms IS NULL
    533                 OR NEW.authorized_until_unix_ms > NEW.updated_at_unix_ms))
    534         OR (OLD.status = 'pending' AND NEW.status = 'denied'
    535             AND NEW.authorized_until_unix_ms IS NULL)
    536         OR (OLD.status = 'active' AND NEW.status = 'expired'
    537             AND NEW.authorized_until_unix_ms IS NULL)
    538     )
    539 BEGIN
    540     SELECT RAISE(ABORT, 'connection transition is invalid');
    541 END"#
    542     };
    543 }
    544 
    545 macro_rules! connections_no_delete_sql {
    546     () => {
    547         r#"CREATE TRIGGER connections_no_delete
    548 BEFORE DELETE ON connections
    549 BEGIN
    550     SELECT RAISE(ABORT, 'connection evidence is retained');
    551 END"#
    552     };
    553 }
    554 
    555 macro_rules! connection_permissions_no_update_sql {
    556     () => {
    557         r#"CREATE TRIGGER connection_permissions_no_update
    558 BEFORE UPDATE ON connection_permissions
    559 BEGIN
    560     SELECT RAISE(ABORT, 'connection permission evidence is immutable');
    561 END"#
    562     };
    563 }
    564 
    565 macro_rules! connection_permissions_no_delete_sql {
    566     () => {
    567         r#"CREATE TRIGGER connection_permissions_no_delete
    568 BEFORE DELETE ON connection_permissions
    569 BEGIN
    570     SELECT RAISE(ABORT, 'connection permission evidence is retained');
    571 END"#
    572     };
    573 }
    574 
    575 macro_rules! nip46_request_decisions_guard_update_sql {
    576     () => {
    577         r#"CREATE TRIGGER nip46_request_decisions_guard_update
    578 BEFORE UPDATE ON nip46_request_decisions
    579 WHEN NEW.operation_id != OLD.operation_id
    580     OR NEW.connection_id IS NOT OLD.connection_id
    581     OR NEW.policy_generation != OLD.policy_generation
    582     OR NEW.requested_permissions_sha256 != OLD.requested_permissions_sha256
    583     OR NEW.challenge_id IS NOT OLD.challenge_id
    584     OR NEW.decided_at_unix_ms < OLD.decided_at_unix_ms
    585     OR NOT (
    586         (OLD.decision = 'pending_approval' AND NEW.decision = 'allowed'
    587             AND NEW.reason_code = 'operator_approved')
    588         OR (OLD.decision = 'pending_approval' AND NEW.decision = 'denied'
    589             AND NEW.reason_code = 'operator_denied')
    590         OR (OLD.decision = 'challenged' AND NEW.decision = 'allowed'
    591             AND NEW.reason_code = 'authorization_challenge_authorized')
    592         OR (OLD.decision = 'challenged' AND NEW.decision = 'denied'
    593             AND NEW.reason_code = 'authorization_challenge_expired')
    594     )
    595 BEGIN
    596     SELECT RAISE(ABORT, 'request decision transition is invalid');
    597 END"#
    598     };
    599 }
    600 
    601 macro_rules! nip46_request_decisions_no_delete_sql {
    602     () => {
    603         r#"CREATE TRIGGER nip46_request_decisions_no_delete
    604 BEFORE DELETE ON nip46_request_decisions
    605 BEGIN
    606     SELECT RAISE(ABORT, 'request decision evidence is retained');
    607 END"#
    608     };
    609 }
    610 
    611 macro_rules! connection_auth_challenges_guard_update_sql {
    612     () => {
    613         r#"CREATE TRIGGER connection_auth_challenges_guard_update
    614 BEFORE UPDATE ON connection_auth_challenges
    615 WHEN NEW.challenge_id != OLD.challenge_id
    616     OR NEW.challenge_nonce != OLD.challenge_nonce
    617     OR NEW.connection_id != OLD.connection_id
    618     OR NEW.operation_id != OLD.operation_id
    619     OR NEW.policy_generation != OLD.policy_generation
    620     OR NEW.challenge_url != OLD.challenge_url
    621     OR NEW.issued_at_unix_ms != OLD.issued_at_unix_ms
    622     OR NEW.expires_at_unix_ms != OLD.expires_at_unix_ms
    623     OR NOT (OLD.state = 'pending'
    624         AND NEW.state IN ('authorized', 'expired')
    625         AND NEW.resolved_at_unix_ms IS NOT NULL
    626         AND NEW.resolved_at_unix_ms >= OLD.issued_at_unix_ms)
    627 BEGIN
    628     SELECT RAISE(ABORT, 'authorization challenge transition is invalid');
    629 END"#
    630     };
    631 }
    632 
    633 macro_rules! connection_auth_challenges_no_delete_sql {
    634     () => {
    635         r#"CREATE TRIGGER connection_auth_challenges_no_delete
    636 BEFORE DELETE ON connection_auth_challenges
    637 BEGIN
    638     SELECT RAISE(ABORT, 'authorization challenge evidence is retained');
    639 END"#
    640     };
    641 }
    642 
    643 const CREATE_CONNECTIONS_TABLE_SQL: &str = connections_table_sql!();
    644 const CREATE_CONNECTION_PERMISSIONS_TABLE_SQL: &str = connection_permissions_table_sql!();
    645 const CREATE_NIP46_REQUEST_DECISIONS_TABLE_SQL: &str = nip46_request_decisions_table_sql!();
    646 const CREATE_CONNECTION_AUTH_CHALLENGES_TABLE_SQL: &str = connection_auth_challenges_table_sql!();
    647 const CREATE_CONNECTIONS_GUARD_UPDATE_SQL: &str = connections_guard_update_sql!();
    648 const CREATE_CONNECTIONS_NO_DELETE_SQL: &str = connections_no_delete_sql!();
    649 const CREATE_CONNECTION_PERMISSIONS_NO_UPDATE_SQL: &str = connection_permissions_no_update_sql!();
    650 const CREATE_CONNECTION_PERMISSIONS_NO_DELETE_SQL: &str = connection_permissions_no_delete_sql!();
    651 const CREATE_NIP46_REQUEST_DECISIONS_GUARD_UPDATE_SQL: &str =
    652     nip46_request_decisions_guard_update_sql!();
    653 const CREATE_NIP46_REQUEST_DECISIONS_NO_DELETE_SQL: &str = nip46_request_decisions_no_delete_sql!();
    654 const CREATE_CONNECTION_AUTH_CHALLENGES_GUARD_UPDATE_SQL: &str =
    655     connection_auth_challenges_guard_update_sql!();
    656 const CREATE_CONNECTION_AUTH_CHALLENGES_NO_DELETE_SQL: &str =
    657     connection_auth_challenges_no_delete_sql!();
    658 
    659 const CREATE_CONNECTION_STATE_MIGRATION_SQL: &str = concat!(
    660     "DROP TRIGGER myc_state_metadata_no_update;\n",
    661     "UPDATE myc_state_metadata SET state_contract_version = CASE ",
    662     "WHEN state_contract_version = 3 THEN 4 ELSE 0 END WHERE singleton = 1;\n",
    663     myc_state_metadata_no_update_sql!(),
    664     ";\n",
    665     connections_table_sql!(),
    666     ";\n",
    667     connection_permissions_table_sql!(),
    668     ";\n",
    669     nip46_request_decisions_table_sql!(),
    670     ";\n",
    671     connection_auth_challenges_table_sql!(),
    672     ";\n",
    673     connections_guard_update_sql!(),
    674     ";\n",
    675     connections_no_delete_sql!(),
    676     ";\n",
    677     connection_permissions_no_update_sql!(),
    678     ";\n",
    679     connection_permissions_no_delete_sql!(),
    680     ";\n",
    681     nip46_request_decisions_guard_update_sql!(),
    682     ";\n",
    683     nip46_request_decisions_no_delete_sql!(),
    684     ";\n",
    685     connection_auth_challenges_guard_update_sql!(),
    686     ";\n",
    687     connection_auth_challenges_no_delete_sql!(),
    688 );
    689 
    690 macro_rules! myc_audit_state_table_sql {
    691     () => {
    692         r#"CREATE TABLE myc_audit_state (
    693     singleton INTEGER NOT NULL PRIMARY KEY CHECK (singleton = 1),
    694     next_sequence INTEGER NOT NULL CHECK (next_sequence BETWEEN 0 AND 9223372036854775807)
    695 ) STRICT"#
    696     };
    697 }
    698 
    699 macro_rules! operation_audit_table_sql {
    700     () => {
    701         r#"CREATE TABLE operation_audit (
    702     audit_sequence INTEGER NOT NULL PRIMARY KEY
    703         CHECK (audit_sequence BETWEEN 1 AND 9223372036854775807),
    704     audit_id BLOB NOT NULL UNIQUE CHECK (length(audit_id) = 32),
    705     correlation_id BLOB NOT NULL CHECK (length(correlation_id) = 32),
    706     audit_kind TEXT NOT NULL CHECK (audit_kind IN (
    707         'connection_admission',
    708         'connection_operator_decision',
    709         'connection_expiry',
    710         'challenge_creation',
    711         'challenge_authorization',
    712         'governance_compaction'
    713     )),
    714     outcome TEXT NOT NULL CHECK (outcome IN ('succeeded', 'rejected', 'failed')),
    715     reason_code TEXT NOT NULL CHECK (reason_code IN (
    716         'trusted',
    717         'approval_required',
    718         'policy_denied',
    719         'operator_approved',
    720         'operator_denied',
    721         'connection_expired',
    722         'challenge_required',
    723         'challenge_authorized',
    724         'challenge_expired',
    725         'rate_limited',
    726         'compacted'
    727     )),
    728     occurred_at_unix_ms INTEGER NOT NULL
    729         CHECK (occurred_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    730     UNIQUE (correlation_id, audit_kind)
    731 ) STRICT"#
    732     };
    733 }
    734 
    735 macro_rules! nip46_request_audit_table_sql {
    736     () => {
    737         r#"CREATE TABLE nip46_request_audit (
    738     operation_id BLOB NOT NULL CHECK (length(operation_id) = 32)
    739         REFERENCES nip46_requests(operation_id),
    740     audit_kind TEXT NOT NULL CHECK (audit_kind IN (
    741         'connection_admission', 'challenge_creation', 'challenge_authorization'
    742     )),
    743     audit_sequence INTEGER NOT NULL UNIQUE
    744         CHECK (audit_sequence BETWEEN 1 AND 9223372036854775807)
    745         REFERENCES operation_audit(audit_sequence),
    746     PRIMARY KEY (operation_id, audit_kind)
    747 ) STRICT"#
    748     };
    749 }
    750 
    751 macro_rules! connection_rate_windows_table_sql {
    752     () => {
    753         r#"CREATE TABLE connection_rate_windows (
    754     rate_kind TEXT NOT NULL CHECK (rate_kind IN (
    755         'connection_admission', 'challenge_creation', 'challenge_authorization'
    756     )),
    757     subject_scope TEXT NOT NULL CHECK (subject_scope IN ('global', 'relay', 'connection')),
    758     subject_sha256 BLOB NOT NULL CHECK (length(subject_sha256) = 32),
    759     window_started_at_unix_ms INTEGER NOT NULL
    760         CHECK (window_started_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    761     window_ends_at_unix_ms INTEGER NOT NULL
    762         CHECK (window_ends_at_unix_ms BETWEEN window_started_at_unix_ms AND 9223372036854775807),
    763     accepted_count INTEGER NOT NULL CHECK (accepted_count BETWEEN 0 AND 10000),
    764     rejected_count INTEGER NOT NULL CHECK (rejected_count BETWEEN 0 AND 9223372036854775807),
    765     lifetime_accepted_count INTEGER NOT NULL
    766         CHECK (lifetime_accepted_count BETWEEN accepted_count AND 9223372036854775807),
    767     lifetime_rejected_count INTEGER NOT NULL
    768         CHECK (lifetime_rejected_count BETWEEN rejected_count AND 9223372036854775807),
    769     last_observed_at_unix_ms INTEGER NOT NULL
    770         CHECK (last_observed_at_unix_ms BETWEEN window_started_at_unix_ms AND 9223372036854775807),
    771     retention_expires_at_unix_ms INTEGER NOT NULL
    772         CHECK (retention_expires_at_unix_ms BETWEEN last_observed_at_unix_ms AND 9223372036854775807),
    773     CHECK (
    774         (rate_kind = 'connection_admission' AND subject_scope IN ('global', 'relay'))
    775         OR (rate_kind IN ('challenge_creation', 'challenge_authorization')
    776             AND subject_scope = 'connection')
    777     ),
    778     PRIMARY KEY (rate_kind, subject_scope, subject_sha256)
    779 ) STRICT"#
    780     };
    781 }
    782 
    783 macro_rules! myc_audit_state_guard_update_sql {
    784     () => {
    785         r#"CREATE TRIGGER myc_audit_state_guard_update
    786 BEFORE UPDATE ON myc_audit_state
    787 WHEN NEW.singleton != OLD.singleton
    788     OR OLD.next_sequence = 9223372036854775807
    789     OR NEW.next_sequence != OLD.next_sequence + 1
    790 BEGIN
    791     SELECT RAISE(ABORT, 'audit sequence transition is invalid');
    792 END"#
    793     };
    794 }
    795 
    796 macro_rules! myc_audit_state_no_delete_sql {
    797     () => {
    798         r#"CREATE TRIGGER myc_audit_state_no_delete
    799 BEFORE DELETE ON myc_audit_state
    800 BEGIN
    801     SELECT RAISE(ABORT, 'audit sequence authority is retained');
    802 END"#
    803     };
    804 }
    805 
    806 macro_rules! operation_audit_no_update_sql {
    807     () => {
    808         r#"CREATE TRIGGER operation_audit_no_update
    809 BEFORE UPDATE ON operation_audit
    810 BEGIN
    811     SELECT RAISE(ABORT, 'operation audit is immutable');
    812 END"#
    813     };
    814 }
    815 
    816 macro_rules! nip46_request_audit_no_update_sql {
    817     () => {
    818         r#"CREATE TRIGGER nip46_request_audit_no_update
    819 BEFORE UPDATE ON nip46_request_audit
    820 BEGIN
    821     SELECT RAISE(ABORT, 'request audit binding is immutable');
    822 END"#
    823     };
    824 }
    825 
    826 macro_rules! connection_rate_windows_guard_update_sql {
    827     () => {
    828         r#"CREATE TRIGGER connection_rate_windows_guard_update
    829 BEFORE UPDATE ON connection_rate_windows
    830 WHEN NEW.rate_kind != OLD.rate_kind
    831     OR NEW.subject_scope != OLD.subject_scope
    832     OR NEW.subject_sha256 != OLD.subject_sha256
    833     OR NEW.window_started_at_unix_ms < OLD.window_started_at_unix_ms
    834     OR NEW.window_ends_at_unix_ms < NEW.window_started_at_unix_ms
    835     OR NEW.lifetime_accepted_count < OLD.lifetime_accepted_count
    836     OR NEW.lifetime_rejected_count < OLD.lifetime_rejected_count
    837     OR NEW.last_observed_at_unix_ms < OLD.last_observed_at_unix_ms
    838     OR NEW.retention_expires_at_unix_ms < NEW.last_observed_at_unix_ms
    839     OR NOT (
    840         (NEW.window_started_at_unix_ms = OLD.window_started_at_unix_ms
    841             AND NEW.window_ends_at_unix_ms = OLD.window_ends_at_unix_ms
    842             AND (
    843                 (NEW.accepted_count = OLD.accepted_count + 1
    844                     AND NEW.rejected_count = OLD.rejected_count
    845                     AND NEW.lifetime_accepted_count = OLD.lifetime_accepted_count + 1
    846                     AND NEW.lifetime_rejected_count = OLD.lifetime_rejected_count)
    847                 OR (NEW.accepted_count = OLD.accepted_count
    848                     AND NEW.rejected_count = OLD.rejected_count + 1
    849                     AND NEW.lifetime_accepted_count = OLD.lifetime_accepted_count
    850                     AND NEW.lifetime_rejected_count = OLD.lifetime_rejected_count + 1)
    851             ))
    852         OR (NEW.window_started_at_unix_ms > OLD.window_ends_at_unix_ms
    853             AND NEW.window_ends_at_unix_ms > NEW.window_started_at_unix_ms
    854             AND ((NEW.accepted_count = 1 AND NEW.rejected_count = 0)
    855                 OR (NEW.accepted_count = 0 AND NEW.rejected_count = 1))
    856             AND NEW.lifetime_accepted_count = OLD.lifetime_accepted_count + NEW.accepted_count
    857             AND NEW.lifetime_rejected_count = OLD.lifetime_rejected_count + NEW.rejected_count)
    858     )
    859 BEGIN
    860     SELECT RAISE(ABORT, 'rate-window transition is invalid');
    861 END"#
    862     };
    863 }
    864 
    865 const CREATE_MYC_AUDIT_STATE_TABLE_SQL: &str = myc_audit_state_table_sql!();
    866 const CREATE_OPERATION_AUDIT_TABLE_SQL: &str = operation_audit_table_sql!();
    867 const CREATE_NIP46_REQUEST_AUDIT_TABLE_SQL: &str = nip46_request_audit_table_sql!();
    868 const CREATE_CONNECTION_RATE_WINDOWS_TABLE_SQL: &str = connection_rate_windows_table_sql!();
    869 const CREATE_MYC_AUDIT_STATE_GUARD_UPDATE_SQL: &str = myc_audit_state_guard_update_sql!();
    870 const CREATE_MYC_AUDIT_STATE_NO_DELETE_SQL: &str = myc_audit_state_no_delete_sql!();
    871 const CREATE_OPERATION_AUDIT_NO_UPDATE_SQL: &str = operation_audit_no_update_sql!();
    872 const CREATE_NIP46_REQUEST_AUDIT_NO_UPDATE_SQL: &str = nip46_request_audit_no_update_sql!();
    873 const CREATE_CONNECTION_RATE_WINDOWS_GUARD_UPDATE_SQL: &str =
    874     connection_rate_windows_guard_update_sql!();
    875 
    876 const CREATE_GOVERNANCE_STATE_MIGRATION_SQL: &str = concat!(
    877     "DROP TRIGGER myc_state_metadata_no_update;\n",
    878     "UPDATE myc_state_metadata SET state_contract_version = CASE ",
    879     "WHEN state_contract_version = 4 THEN 5 ELSE 0 END WHERE singleton = 1;\n",
    880     myc_state_metadata_no_update_sql!(),
    881     ";\n",
    882     myc_audit_state_table_sql!(),
    883     ";\n",
    884     "INSERT INTO myc_audit_state (singleton, next_sequence) VALUES (1, 0);\n",
    885     operation_audit_table_sql!(),
    886     ";\n",
    887     nip46_request_audit_table_sql!(),
    888     ";\n",
    889     connection_rate_windows_table_sql!(),
    890     ";\n",
    891     myc_audit_state_guard_update_sql!(),
    892     ";\n",
    893     myc_audit_state_no_delete_sql!(),
    894     ";\n",
    895     operation_audit_no_update_sql!(),
    896     ";\n",
    897     nip46_request_audit_no_update_sql!(),
    898     ";\n",
    899     connection_rate_windows_guard_update_sql!(),
    900 );
    901 
    902 macro_rules! publication_outbox_table_sql {
    903     () => {
    904         r#"CREATE TABLE publication_outbox (
    905     job_id BLOB NOT NULL PRIMARY KEY CHECK (length(job_id) = 32),
    906     signer_operation_id BLOB NOT NULL UNIQUE CHECK (length(signer_operation_id) = 32)
    907         REFERENCES nip46_requests(operation_id),
    908     artifact_sha256 BLOB NOT NULL CHECK (length(artifact_sha256) = 32),
    909     policy_mode TEXT NOT NULL CHECK (policy_mode IN (
    910         'at_least_one_required', 'all_required', 'required_quorum'
    911     )),
    912     required_acknowledgements INTEGER NOT NULL
    913         CHECK (required_acknowledgements BETWEEN 1 AND 32),
    914     max_attempts INTEGER NOT NULL CHECK (max_attempts BETWEEN 1 AND 32),
    915     initial_backoff_ms INTEGER NOT NULL CHECK (initial_backoff_ms BETWEEN 1 AND 30000),
    916     maximum_backoff_ms INTEGER NOT NULL CHECK (maximum_backoff_ms BETWEEN initial_backoff_ms AND 300000),
    917     attempt_deadline_ms INTEGER NOT NULL CHECK (attempt_deadline_ms BETWEEN 1 AND 30000),
    918     status TEXT NOT NULL CHECK (status IN ('pending', 'active', 'delivered', 'failed', 'unknown')),
    919     created_at_unix_ms INTEGER NOT NULL
    920         CHECK (created_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    921     updated_at_unix_ms INTEGER NOT NULL
    922         CHECK (updated_at_unix_ms BETWEEN created_at_unix_ms AND 9223372036854775807),
    923     finalized_at_unix_ms INTEGER
    924         CHECK (finalized_at_unix_ms IS NULL OR
    925             finalized_at_unix_ms BETWEEN created_at_unix_ms AND 9223372036854775807),
    926     CHECK ((status IN ('pending', 'active') AND finalized_at_unix_ms IS NULL)
    927         OR (status IN ('delivered', 'failed', 'unknown') AND finalized_at_unix_ms IS NOT NULL))
    928 ) STRICT"#
    929     };
    930 }
    931 
    932 macro_rules! publication_targets_table_sql {
    933     () => {
    934         r#"CREATE TABLE publication_targets (
    935     job_id BLOB NOT NULL CHECK (length(job_id) = 32)
    936         REFERENCES publication_outbox(job_id),
    937     target_index INTEGER NOT NULL CHECK (target_index BETWEEN 0 AND 31),
    938     relay_id TEXT NOT NULL CHECK (length(CAST(relay_id AS BLOB)) BETWEEN 1 AND 64),
    939     required INTEGER NOT NULL CHECK (required IN (0, 1)),
    940     attempt_count INTEGER NOT NULL CHECK (attempt_count BETWEEN 0 AND 32),
    941     status TEXT NOT NULL CHECK (status IN (
    942         'pending', 'leased', 'submitted', 'delivered', 'retryable', 'unknown', 'exhausted'
    943     )),
    944     active_attempt_id BLOB CHECK (active_attempt_id IS NULL OR length(active_attempt_id) = 32),
    945     next_attempt_at_unix_ms INTEGER
    946         CHECK (next_attempt_at_unix_ms IS NULL OR
    947             next_attempt_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    948     updated_at_unix_ms INTEGER NOT NULL
    949         CHECK (updated_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    950     CHECK ((status IN ('leased', 'submitted') AND active_attempt_id IS NOT NULL
    951             AND next_attempt_at_unix_ms IS NULL)
    952         OR (status = 'retryable' AND active_attempt_id IS NULL
    953             AND next_attempt_at_unix_ms IS NOT NULL)
    954         OR (status = 'unknown' AND active_attempt_id IS NULL)
    955         OR (status IN ('pending', 'delivered', 'exhausted') AND active_attempt_id IS NULL
    956             AND next_attempt_at_unix_ms IS NULL)),
    957     PRIMARY KEY (job_id, target_index),
    958     UNIQUE (job_id, relay_id)
    959 ) STRICT"#
    960     };
    961 }
    962 
    963 macro_rules! publication_attempts_table_sql {
    964     () => {
    965         r#"CREATE TABLE publication_attempts (
    966     attempt_id BLOB NOT NULL PRIMARY KEY CHECK (length(attempt_id) = 32),
    967     job_id BLOB NOT NULL CHECK (length(job_id) = 32),
    968     target_index INTEGER NOT NULL CHECK (target_index BETWEEN 0 AND 31),
    969     attempt_number INTEGER NOT NULL CHECK (attempt_number BETWEEN 1 AND 32),
    970     attempt_nonce BLOB NOT NULL CHECK (length(attempt_nonce) = 32),
    971     status TEXT NOT NULL CHECK (status IN ('leased', 'submitted', 'delivered', 'failed', 'unknown')),
    972     leased_at_unix_ms INTEGER NOT NULL
    973         CHECK (leased_at_unix_ms BETWEEN 1 AND 9223372036854775807),
    974     lease_expires_at_unix_ms INTEGER NOT NULL
    975         CHECK (lease_expires_at_unix_ms BETWEEN leased_at_unix_ms + 1 AND 9223372036854775807),
    976     submitted_at_unix_ms INTEGER
    977         CHECK (submitted_at_unix_ms IS NULL OR
    978             submitted_at_unix_ms BETWEEN leased_at_unix_ms AND lease_expires_at_unix_ms),
    979     resolved_at_unix_ms INTEGER
    980         CHECK (resolved_at_unix_ms IS NULL OR
    981             resolved_at_unix_ms BETWEEN leased_at_unix_ms AND 9223372036854775807),
    982     reason_code TEXT CHECK (reason_code IS NULL OR reason_code IN (
    983         'accepted', 'relay_rejected', 'transport_failed',
    984         'lease_expired_before_submit', 'acknowledgement_lost'
    985     )),
    986     CHECK ((status = 'leased' AND submitted_at_unix_ms IS NULL
    987             AND resolved_at_unix_ms IS NULL AND reason_code IS NULL)
    988         OR (status = 'submitted' AND submitted_at_unix_ms IS NOT NULL
    989             AND resolved_at_unix_ms IS NULL AND reason_code IS NULL)
    990         OR (status = 'delivered' AND submitted_at_unix_ms IS NOT NULL
    991             AND resolved_at_unix_ms IS NOT NULL AND reason_code = 'accepted')
    992         OR (status = 'failed' AND resolved_at_unix_ms IS NOT NULL
    993             AND reason_code IN ('relay_rejected', 'transport_failed', 'lease_expired_before_submit'))
    994         OR (status = 'unknown' AND submitted_at_unix_ms IS NOT NULL
    995             AND resolved_at_unix_ms IS NOT NULL AND reason_code = 'acknowledgement_lost')),
    996     FOREIGN KEY (job_id, target_index)
    997         REFERENCES publication_targets(job_id, target_index),
    998     UNIQUE (job_id, target_index, attempt_number),
    999     UNIQUE (job_id, target_index, attempt_nonce)
   1000 ) STRICT"#
   1001     };
   1002 }
   1003 
   1004 macro_rules! publication_outbox_guard_update_sql {
   1005     () => {
   1006         r#"CREATE TRIGGER publication_outbox_guard_update
   1007 BEFORE UPDATE ON publication_outbox
   1008 WHEN NEW.job_id != OLD.job_id
   1009     OR NEW.signer_operation_id != OLD.signer_operation_id
   1010     OR NEW.artifact_sha256 != OLD.artifact_sha256
   1011     OR NEW.policy_mode != OLD.policy_mode
   1012     OR NEW.required_acknowledgements != OLD.required_acknowledgements
   1013     OR NEW.max_attempts != OLD.max_attempts
   1014     OR NEW.initial_backoff_ms != OLD.initial_backoff_ms
   1015     OR NEW.maximum_backoff_ms != OLD.maximum_backoff_ms
   1016     OR NEW.attempt_deadline_ms != OLD.attempt_deadline_ms
   1017     OR NEW.created_at_unix_ms != OLD.created_at_unix_ms
   1018     OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms
   1019     OR NOT ((OLD.status = 'pending' AND NEW.status = 'active'
   1020             AND NEW.finalized_at_unix_ms IS NULL)
   1021         OR (OLD.status IN ('pending', 'active') AND NEW.status IN ('delivered', 'failed', 'unknown')
   1022             AND NEW.finalized_at_unix_ms IS NOT NULL))
   1023 BEGIN
   1024     SELECT RAISE(ABORT, 'publication job transition is invalid');
   1025 END"#
   1026     };
   1027 }
   1028 
   1029 macro_rules! publication_targets_guard_update_sql {
   1030     () => {
   1031         r#"CREATE TRIGGER publication_targets_guard_update
   1032 BEFORE UPDATE ON publication_targets
   1033 WHEN NEW.job_id != OLD.job_id
   1034     OR NEW.target_index != OLD.target_index
   1035     OR NEW.relay_id != OLD.relay_id
   1036     OR NEW.required != OLD.required
   1037     OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms
   1038     OR NOT ((OLD.status IN ('pending', 'retryable', 'unknown') AND NEW.status = 'leased'
   1039             AND NEW.attempt_count = OLD.attempt_count + 1
   1040             AND NEW.active_attempt_id IS NOT NULL AND NEW.next_attempt_at_unix_ms IS NULL)
   1041         OR (OLD.status = 'leased' AND NEW.status = 'submitted'
   1042             AND NEW.attempt_count = OLD.attempt_count
   1043             AND NEW.active_attempt_id = OLD.active_attempt_id
   1044             AND NEW.next_attempt_at_unix_ms IS NULL)
   1045         OR (OLD.status IN ('leased', 'submitted')
   1046             AND NEW.status IN ('delivered', 'retryable', 'unknown', 'exhausted')
   1047             AND NEW.attempt_count = OLD.attempt_count
   1048             AND NEW.active_attempt_id IS NULL
   1049             AND ((NEW.status = 'retryable'
   1050                     AND NEW.next_attempt_at_unix_ms IS NOT NULL)
   1051                 OR NEW.status = 'unknown'
   1052                 OR (NEW.status IN ('delivered', 'exhausted')
   1053                     AND NEW.next_attempt_at_unix_ms IS NULL))))
   1054 BEGIN
   1055     SELECT RAISE(ABORT, 'publication target transition is invalid');
   1056 END"#
   1057     };
   1058 }
   1059 
   1060 macro_rules! publication_attempts_guard_update_sql {
   1061     () => {
   1062         r#"CREATE TRIGGER publication_attempts_guard_update
   1063 BEFORE UPDATE ON publication_attempts
   1064 WHEN NEW.attempt_id != OLD.attempt_id
   1065     OR NEW.job_id != OLD.job_id
   1066     OR NEW.target_index != OLD.target_index
   1067     OR NEW.attempt_number != OLD.attempt_number
   1068     OR NEW.attempt_nonce != OLD.attempt_nonce
   1069     OR NEW.leased_at_unix_ms != OLD.leased_at_unix_ms
   1070     OR NEW.lease_expires_at_unix_ms != OLD.lease_expires_at_unix_ms
   1071     OR NOT ((OLD.status = 'leased' AND NEW.status = 'submitted'
   1072             AND NEW.submitted_at_unix_ms IS NOT NULL
   1073             AND NEW.resolved_at_unix_ms IS NULL AND NEW.reason_code IS NULL)
   1074         OR (OLD.status = 'leased' AND NEW.status = 'failed'
   1075             AND NEW.submitted_at_unix_ms IS NULL
   1076             AND NEW.resolved_at_unix_ms IS NOT NULL
   1077             AND NEW.reason_code IN ('transport_failed', 'lease_expired_before_submit'))
   1078         OR (OLD.status = 'submitted' AND NEW.status IN ('delivered', 'failed', 'unknown')
   1079             AND NEW.submitted_at_unix_ms = OLD.submitted_at_unix_ms
   1080             AND NEW.resolved_at_unix_ms IS NOT NULL
   1081             AND ((NEW.status = 'delivered' AND NEW.reason_code = 'accepted')
   1082                 OR (NEW.status = 'failed'
   1083                     AND NEW.reason_code IN ('relay_rejected', 'transport_failed'))
   1084                 OR (NEW.status = 'unknown'
   1085                     AND NEW.reason_code = 'acknowledgement_lost'))))
   1086 BEGIN
   1087     SELECT RAISE(ABORT, 'publication attempt transition is invalid');
   1088 END"#
   1089     };
   1090 }
   1091 
   1092 macro_rules! publication_outbox_no_delete_sql {
   1093     () => {
   1094         r#"CREATE TRIGGER publication_outbox_no_delete
   1095 BEFORE DELETE ON publication_outbox
   1096 BEGIN
   1097     SELECT RAISE(ABORT, 'publication jobs are immutable');
   1098 END"#
   1099     };
   1100 }
   1101 
   1102 macro_rules! publication_targets_no_delete_sql {
   1103     () => {
   1104         r#"CREATE TRIGGER publication_targets_no_delete
   1105 BEFORE DELETE ON publication_targets
   1106 BEGIN
   1107     SELECT RAISE(ABORT, 'publication targets are immutable');
   1108 END"#
   1109     };
   1110 }
   1111 
   1112 macro_rules! publication_attempts_no_delete_sql {
   1113     () => {
   1114         r#"CREATE TRIGGER publication_attempts_no_delete
   1115 BEFORE DELETE ON publication_attempts
   1116 BEGIN
   1117     SELECT RAISE(ABORT, 'publication attempts are immutable');
   1118 END"#
   1119     };
   1120 }
   1121 
   1122 const CREATE_PUBLICATION_OUTBOX_TABLE_SQL: &str = publication_outbox_table_sql!();
   1123 const CREATE_PUBLICATION_TARGETS_TABLE_SQL: &str = publication_targets_table_sql!();
   1124 const CREATE_PUBLICATION_ATTEMPTS_TABLE_SQL: &str = publication_attempts_table_sql!();
   1125 const CREATE_PUBLICATION_OUTBOX_GUARD_UPDATE_SQL: &str = publication_outbox_guard_update_sql!();
   1126 const CREATE_PUBLICATION_TARGETS_GUARD_UPDATE_SQL: &str = publication_targets_guard_update_sql!();
   1127 const CREATE_PUBLICATION_ATTEMPTS_GUARD_UPDATE_SQL: &str = publication_attempts_guard_update_sql!();
   1128 const CREATE_PUBLICATION_OUTBOX_NO_DELETE_SQL: &str = publication_outbox_no_delete_sql!();
   1129 const CREATE_PUBLICATION_TARGETS_NO_DELETE_SQL: &str = publication_targets_no_delete_sql!();
   1130 const CREATE_PUBLICATION_ATTEMPTS_NO_DELETE_SQL: &str = publication_attempts_no_delete_sql!();
   1131 
   1132 const CREATE_DELIVERY_STATE_MIGRATION_SQL: &str = concat!(
   1133     "DROP TRIGGER myc_state_metadata_no_update;\n",
   1134     "UPDATE myc_state_metadata SET state_contract_version = CASE ",
   1135     "WHEN state_contract_version = 5 THEN 6 ELSE 0 END WHERE singleton = 1;\n",
   1136     myc_state_metadata_no_update_sql!(),
   1137     ";\n",
   1138     publication_outbox_table_sql!(),
   1139     ";\n",
   1140     publication_targets_table_sql!(),
   1141     ";\n",
   1142     publication_attempts_table_sql!(),
   1143     ";\n",
   1144     publication_outbox_guard_update_sql!(),
   1145     ";\n",
   1146     publication_targets_guard_update_sql!(),
   1147     ";\n",
   1148     publication_attempts_guard_update_sql!(),
   1149     ";\n",
   1150     publication_outbox_no_delete_sql!(),
   1151     ";\n",
   1152     publication_targets_no_delete_sql!(),
   1153     ";\n",
   1154     publication_attempts_no_delete_sql!(),
   1155 );
   1156 
   1157 macro_rules! delivery_jobs_table_sql {
   1158     () => {
   1159         r#"CREATE TABLE delivery_jobs (
   1160     job_id BLOB NOT NULL PRIMARY KEY CHECK (length(job_id) = 32),
   1161     source_kind TEXT NOT NULL CHECK (source_kind IN ('signer_response', 'discovery_handler')),
   1162     source_id BLOB NOT NULL CHECK (length(source_id) = 32),
   1163     artifact_sha256 BLOB NOT NULL CHECK (length(artifact_sha256) = 32),
   1164     policy_mode TEXT NOT NULL CHECK (policy_mode IN (
   1165         'at_least_one_required', 'all_required', 'required_quorum'
   1166     )),
   1167     required_acknowledgements INTEGER NOT NULL
   1168         CHECK (required_acknowledgements BETWEEN 1 AND 32),
   1169     max_attempts INTEGER NOT NULL CHECK (max_attempts BETWEEN 1 AND 32),
   1170     initial_backoff_ms INTEGER NOT NULL CHECK (initial_backoff_ms BETWEEN 1 AND 30000),
   1171     maximum_backoff_ms INTEGER NOT NULL CHECK (maximum_backoff_ms BETWEEN initial_backoff_ms AND 300000),
   1172     attempt_deadline_ms INTEGER NOT NULL CHECK (attempt_deadline_ms BETWEEN 1 AND 30000),
   1173     status TEXT NOT NULL CHECK (status IN ('pending', 'active', 'delivered', 'failed', 'unknown')),
   1174     created_at_unix_ms INTEGER NOT NULL
   1175         CHECK (created_at_unix_ms BETWEEN 1 AND 9223372036854775807),
   1176     updated_at_unix_ms INTEGER NOT NULL
   1177         CHECK (updated_at_unix_ms BETWEEN created_at_unix_ms AND 9223372036854775807),
   1178     finalized_at_unix_ms INTEGER
   1179         CHECK (finalized_at_unix_ms IS NULL OR
   1180             finalized_at_unix_ms BETWEEN created_at_unix_ms AND 9223372036854775807),
   1181     UNIQUE (source_kind, source_id),
   1182     CHECK ((status IN ('pending', 'active') AND finalized_at_unix_ms IS NULL)
   1183         OR (status IN ('delivered', 'failed', 'unknown') AND finalized_at_unix_ms IS NOT NULL))
   1184 ) STRICT"#
   1185     };
   1186 }
   1187 
   1188 macro_rules! delivery_targets_table_sql {
   1189     () => {
   1190         r#"CREATE TABLE delivery_targets (
   1191     job_id BLOB NOT NULL CHECK (length(job_id) = 32)
   1192         REFERENCES delivery_jobs(job_id),
   1193     target_index INTEGER NOT NULL CHECK (target_index BETWEEN 0 AND 31),
   1194     relay_id TEXT NOT NULL CHECK (length(CAST(relay_id AS BLOB)) BETWEEN 1 AND 64),
   1195     required INTEGER NOT NULL CHECK (required IN (0, 1)),
   1196     attempt_count INTEGER NOT NULL CHECK (attempt_count BETWEEN 0 AND 32),
   1197     status TEXT NOT NULL CHECK (status IN (
   1198         'pending', 'leased', 'submitted', 'delivered', 'retryable', 'unknown', 'exhausted'
   1199     )),
   1200     active_attempt_id BLOB CHECK (active_attempt_id IS NULL OR length(active_attempt_id) = 32),
   1201     next_attempt_at_unix_ms INTEGER
   1202         CHECK (next_attempt_at_unix_ms IS NULL OR
   1203             next_attempt_at_unix_ms BETWEEN 1 AND 9223372036854775807),
   1204     updated_at_unix_ms INTEGER NOT NULL
   1205         CHECK (updated_at_unix_ms BETWEEN 1 AND 9223372036854775807),
   1206     CHECK ((status IN ('leased', 'submitted') AND active_attempt_id IS NOT NULL
   1207             AND next_attempt_at_unix_ms IS NULL)
   1208         OR (status = 'retryable' AND active_attempt_id IS NULL
   1209             AND next_attempt_at_unix_ms IS NOT NULL)
   1210         OR (status = 'unknown' AND active_attempt_id IS NULL)
   1211         OR (status IN ('pending', 'delivered', 'exhausted') AND active_attempt_id IS NULL
   1212             AND next_attempt_at_unix_ms IS NULL)),
   1213     PRIMARY KEY (job_id, target_index),
   1214     UNIQUE (job_id, relay_id)
   1215 ) STRICT"#
   1216     };
   1217 }
   1218 
   1219 macro_rules! delivery_attempts_table_sql {
   1220     () => {
   1221         r#"CREATE TABLE delivery_attempts (
   1222     attempt_id BLOB NOT NULL PRIMARY KEY CHECK (length(attempt_id) = 32),
   1223     job_id BLOB NOT NULL CHECK (length(job_id) = 32),
   1224     target_index INTEGER NOT NULL CHECK (target_index BETWEEN 0 AND 31),
   1225     attempt_number INTEGER NOT NULL CHECK (attempt_number BETWEEN 1 AND 32),
   1226     attempt_nonce BLOB NOT NULL CHECK (length(attempt_nonce) = 32),
   1227     status TEXT NOT NULL CHECK (status IN ('leased', 'submitted', 'delivered', 'failed', 'unknown')),
   1228     leased_at_unix_ms INTEGER NOT NULL
   1229         CHECK (leased_at_unix_ms BETWEEN 1 AND 9223372036854775807),
   1230     lease_expires_at_unix_ms INTEGER NOT NULL
   1231         CHECK (lease_expires_at_unix_ms BETWEEN leased_at_unix_ms + 1 AND 9223372036854775807),
   1232     submitted_at_unix_ms INTEGER
   1233         CHECK (submitted_at_unix_ms IS NULL OR
   1234             submitted_at_unix_ms BETWEEN leased_at_unix_ms AND lease_expires_at_unix_ms),
   1235     resolved_at_unix_ms INTEGER
   1236         CHECK (resolved_at_unix_ms IS NULL OR
   1237             resolved_at_unix_ms BETWEEN leased_at_unix_ms AND 9223372036854775807),
   1238     reason_code TEXT CHECK (reason_code IS NULL OR reason_code IN (
   1239         'accepted', 'relay_rejected', 'transport_failed',
   1240         'lease_expired_before_submit', 'acknowledgement_lost'
   1241     )),
   1242     CHECK ((status = 'leased' AND submitted_at_unix_ms IS NULL
   1243             AND resolved_at_unix_ms IS NULL AND reason_code IS NULL)
   1244         OR (status = 'submitted' AND submitted_at_unix_ms IS NOT NULL
   1245             AND resolved_at_unix_ms IS NULL AND reason_code IS NULL)
   1246         OR (status = 'delivered' AND submitted_at_unix_ms IS NOT NULL
   1247             AND resolved_at_unix_ms IS NOT NULL AND reason_code = 'accepted')
   1248         OR (status = 'failed' AND resolved_at_unix_ms IS NOT NULL
   1249             AND reason_code IN ('relay_rejected', 'transport_failed', 'lease_expired_before_submit'))
   1250         OR (status = 'unknown' AND submitted_at_unix_ms IS NOT NULL
   1251             AND resolved_at_unix_ms IS NOT NULL AND reason_code = 'acknowledgement_lost')),
   1252     FOREIGN KEY (job_id, target_index)
   1253         REFERENCES delivery_targets(job_id, target_index),
   1254     UNIQUE (job_id, target_index, attempt_number),
   1255     UNIQUE (job_id, target_index, attempt_nonce)
   1256 ) STRICT"#
   1257     };
   1258 }
   1259 
   1260 macro_rules! delivery_jobs_guard_update_sql {
   1261     () => {
   1262         r#"CREATE TRIGGER delivery_jobs_guard_update
   1263 BEFORE UPDATE ON delivery_jobs
   1264 WHEN NEW.job_id != OLD.job_id
   1265     OR NEW.source_kind != OLD.source_kind
   1266     OR NEW.source_id != OLD.source_id
   1267     OR NEW.artifact_sha256 != OLD.artifact_sha256
   1268     OR NEW.policy_mode != OLD.policy_mode
   1269     OR NEW.required_acknowledgements != OLD.required_acknowledgements
   1270     OR NEW.max_attempts != OLD.max_attempts
   1271     OR NEW.initial_backoff_ms != OLD.initial_backoff_ms
   1272     OR NEW.maximum_backoff_ms != OLD.maximum_backoff_ms
   1273     OR NEW.attempt_deadline_ms != OLD.attempt_deadline_ms
   1274     OR NEW.created_at_unix_ms != OLD.created_at_unix_ms
   1275     OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms
   1276     OR NOT ((OLD.status = 'pending' AND NEW.status = 'active'
   1277             AND NEW.finalized_at_unix_ms IS NULL)
   1278         OR (OLD.status IN ('pending', 'active') AND NEW.status IN ('delivered', 'failed', 'unknown')
   1279             AND NEW.finalized_at_unix_ms IS NOT NULL))
   1280 BEGIN
   1281     SELECT RAISE(ABORT, 'publication job transition is invalid');
   1282 END"#
   1283     };
   1284 }
   1285 
   1286 macro_rules! delivery_jobs_guard_insert_sql {
   1287     () => {
   1288         r#"CREATE TRIGGER delivery_jobs_guard_insert
   1289 BEFORE INSERT ON delivery_jobs
   1290 WHEN (NEW.source_kind = 'signer_response'
   1291         AND NOT EXISTS (
   1292             SELECT 1 FROM nip46_requests WHERE operation_id = NEW.source_id
   1293         ))
   1294     OR (NEW.source_kind = 'discovery_handler'
   1295         AND NOT EXISTS (
   1296             SELECT 1 FROM discovery_desired_state WHERE generation_id = NEW.source_id
   1297         ))
   1298 BEGIN
   1299     SELECT RAISE(ABORT, 'delivery job source is unknown');
   1300 END"#
   1301     };
   1302 }
   1303 
   1304 macro_rules! delivery_targets_guard_update_sql {
   1305     () => {
   1306         r#"CREATE TRIGGER delivery_targets_guard_update
   1307 BEFORE UPDATE ON delivery_targets
   1308 WHEN NEW.job_id != OLD.job_id
   1309     OR NEW.target_index != OLD.target_index
   1310     OR NEW.relay_id != OLD.relay_id
   1311     OR NEW.required != OLD.required
   1312     OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms
   1313     OR NOT ((OLD.status IN ('pending', 'retryable', 'unknown') AND NEW.status = 'leased'
   1314             AND NEW.attempt_count = OLD.attempt_count + 1
   1315             AND NEW.active_attempt_id IS NOT NULL AND NEW.next_attempt_at_unix_ms IS NULL)
   1316         OR (OLD.status = 'leased' AND NEW.status = 'submitted'
   1317             AND NEW.attempt_count = OLD.attempt_count
   1318             AND NEW.active_attempt_id = OLD.active_attempt_id
   1319             AND NEW.next_attempt_at_unix_ms IS NULL)
   1320         OR (OLD.status IN ('leased', 'submitted')
   1321             AND NEW.status IN ('delivered', 'retryable', 'unknown', 'exhausted')
   1322             AND NEW.attempt_count = OLD.attempt_count
   1323             AND NEW.active_attempt_id IS NULL
   1324             AND ((NEW.status = 'retryable'
   1325                     AND NEW.next_attempt_at_unix_ms IS NOT NULL)
   1326                 OR NEW.status = 'unknown'
   1327                 OR (NEW.status IN ('delivered', 'exhausted')
   1328                     AND NEW.next_attempt_at_unix_ms IS NULL))))
   1329 BEGIN
   1330     SELECT RAISE(ABORT, 'publication target transition is invalid');
   1331 END"#
   1332     };
   1333 }
   1334 
   1335 macro_rules! delivery_attempts_guard_update_sql {
   1336     () => {
   1337         r#"CREATE TRIGGER delivery_attempts_guard_update
   1338 BEFORE UPDATE ON delivery_attempts
   1339 WHEN NEW.attempt_id != OLD.attempt_id
   1340     OR NEW.job_id != OLD.job_id
   1341     OR NEW.target_index != OLD.target_index
   1342     OR NEW.attempt_number != OLD.attempt_number
   1343     OR NEW.attempt_nonce != OLD.attempt_nonce
   1344     OR NEW.leased_at_unix_ms != OLD.leased_at_unix_ms
   1345     OR NEW.lease_expires_at_unix_ms != OLD.lease_expires_at_unix_ms
   1346     OR NOT ((OLD.status = 'leased' AND NEW.status = 'submitted'
   1347             AND NEW.submitted_at_unix_ms IS NOT NULL
   1348             AND NEW.resolved_at_unix_ms IS NULL AND NEW.reason_code IS NULL)
   1349         OR (OLD.status = 'leased' AND NEW.status = 'failed'
   1350             AND NEW.submitted_at_unix_ms IS NULL
   1351             AND NEW.resolved_at_unix_ms IS NOT NULL
   1352             AND NEW.reason_code IN ('transport_failed', 'lease_expired_before_submit'))
   1353         OR (OLD.status = 'submitted' AND NEW.status IN ('delivered', 'failed', 'unknown')
   1354             AND NEW.submitted_at_unix_ms = OLD.submitted_at_unix_ms
   1355             AND NEW.resolved_at_unix_ms IS NOT NULL
   1356             AND ((NEW.status = 'delivered' AND NEW.reason_code = 'accepted')
   1357                 OR (NEW.status = 'failed'
   1358                     AND NEW.reason_code IN ('relay_rejected', 'transport_failed'))
   1359                 OR (NEW.status = 'unknown'
   1360                     AND NEW.reason_code = 'acknowledgement_lost'))))
   1361 BEGIN
   1362     SELECT RAISE(ABORT, 'publication attempt transition is invalid');
   1363 END"#
   1364     };
   1365 }
   1366 
   1367 macro_rules! discovery_desired_state_table_sql {
   1368     () => {
   1369         r#"CREATE TABLE discovery_desired_state (
   1370     generation_id BLOB NOT NULL PRIMARY KEY CHECK (length(generation_id) = 32),
   1371     normalized_config_sha256 BLOB NOT NULL CHECK (length(normalized_config_sha256) = 32),
   1372     desired_sha256 BLOB NOT NULL UNIQUE CHECK (length(desired_sha256) = 32),
   1373     created_at_unix_ms INTEGER NOT NULL
   1374         CHECK (created_at_unix_ms BETWEEN 1 AND 9223372036854775807)
   1375 ) STRICT"#
   1376     };
   1377 }
   1378 
   1379 macro_rules! discovery_documents_table_sql {
   1380     () => {
   1381         r#"CREATE TABLE discovery_documents (
   1382     generation_id BLOB NOT NULL PRIMARY KEY CHECK (length(generation_id) = 32)
   1383         REFERENCES discovery_desired_state(generation_id),
   1384     event_id BLOB NOT NULL UNIQUE CHECK (length(event_id) = 32),
   1385     event_sha256 BLOB NOT NULL UNIQUE CHECK (length(event_sha256) = 32),
   1386     event_bytes BLOB NOT NULL CHECK (length(event_bytes) BETWEEN 1 AND 524288),
   1387     nip05_projection_sha256 BLOB NOT NULL CHECK (length(nip05_projection_sha256) = 32),
   1388     nip05_projection_bytes BLOB NOT NULL
   1389         CHECK (length(nip05_projection_bytes) BETWEEN 1 AND 524288)
   1390 ) STRICT"#
   1391     };
   1392 }
   1393 
   1394 macro_rules! discovery_publication_state_table_sql {
   1395     () => {
   1396         r#"CREATE TABLE discovery_publication_state (
   1397     singleton INTEGER NOT NULL PRIMARY KEY CHECK (singleton = 1),
   1398     desired_generation_id BLOB NOT NULL UNIQUE CHECK (length(desired_generation_id) = 32)
   1399         REFERENCES discovery_desired_state(generation_id),
   1400     desired_job_id BLOB NOT NULL UNIQUE CHECK (length(desired_job_id) = 32)
   1401         REFERENCES delivery_jobs(job_id),
   1402     current_generation_id BLOB UNIQUE
   1403         CHECK (current_generation_id IS NULL OR length(current_generation_id) = 32)
   1404         REFERENCES discovery_desired_state(generation_id),
   1405     current_job_id BLOB UNIQUE
   1406         CHECK (current_job_id IS NULL OR length(current_job_id) = 32)
   1407         REFERENCES delivery_jobs(job_id),
   1408     updated_at_unix_ms INTEGER NOT NULL
   1409         CHECK (updated_at_unix_ms BETWEEN 1 AND 9223372036854775807),
   1410     CHECK ((current_generation_id IS NULL AND current_job_id IS NULL)
   1411         OR (current_generation_id IS NOT NULL AND current_job_id IS NOT NULL))
   1412 ) STRICT"#
   1413     };
   1414 }
   1415 
   1416 macro_rules! immutable_no_update_sql {
   1417     ($trigger:literal, $table:literal, $message:literal) => {
   1418         concat!(
   1419             "CREATE TRIGGER ",
   1420             $trigger,
   1421             " BEFORE UPDATE ON ",
   1422             $table,
   1423             " BEGIN SELECT RAISE(ABORT, '",
   1424             $message,
   1425             "'); END"
   1426         )
   1427     };
   1428 }
   1429 
   1430 macro_rules! immutable_no_delete_sql {
   1431     ($trigger:literal, $table:literal, $message:literal) => {
   1432         concat!(
   1433             "CREATE TRIGGER ",
   1434             $trigger,
   1435             " BEFORE DELETE ON ",
   1436             $table,
   1437             " BEGIN SELECT RAISE(ABORT, '",
   1438             $message,
   1439             "'); END"
   1440         )
   1441     };
   1442 }
   1443 
   1444 macro_rules! discovery_publication_state_guard_update_sql {
   1445     () => {
   1446         r#"CREATE TRIGGER discovery_publication_state_guard_update
   1447 BEFORE UPDATE ON discovery_publication_state
   1448 WHEN NEW.singleton != OLD.singleton
   1449     OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms
   1450     OR NOT (
   1451         (NEW.desired_generation_id != OLD.desired_generation_id
   1452             AND NEW.desired_job_id != OLD.desired_job_id
   1453             AND NEW.current_generation_id IS OLD.current_generation_id
   1454             AND NEW.current_job_id IS OLD.current_job_id)
   1455         OR (NEW.desired_generation_id = OLD.desired_generation_id
   1456             AND NEW.desired_job_id = OLD.desired_job_id
   1457             AND NEW.current_generation_id = OLD.desired_generation_id
   1458             AND NEW.current_job_id = OLD.desired_job_id)
   1459     )
   1460 BEGIN
   1461     SELECT RAISE(ABORT, 'discovery publication transition is invalid');
   1462 END"#
   1463     };
   1464 }
   1465 
   1466 const CREATE_DELIVERY_JOBS_TABLE_SQL: &str = delivery_jobs_table_sql!();
   1467 const CREATE_DELIVERY_TARGETS_TABLE_SQL: &str = delivery_targets_table_sql!();
   1468 const CREATE_DELIVERY_ATTEMPTS_TABLE_SQL: &str = delivery_attempts_table_sql!();
   1469 const CREATE_DELIVERY_JOBS_GUARD_INSERT_SQL: &str = delivery_jobs_guard_insert_sql!();
   1470 const CREATE_DELIVERY_JOBS_GUARD_UPDATE_SQL: &str = delivery_jobs_guard_update_sql!();
   1471 const CREATE_DELIVERY_TARGETS_GUARD_UPDATE_SQL: &str = delivery_targets_guard_update_sql!();
   1472 const CREATE_DELIVERY_ATTEMPTS_GUARD_UPDATE_SQL: &str = delivery_attempts_guard_update_sql!();
   1473 const CREATE_DELIVERY_JOBS_NO_DELETE_SQL: &str = immutable_no_delete_sql!(
   1474     "delivery_jobs_no_delete",
   1475     "delivery_jobs",
   1476     "publication jobs are immutable"
   1477 );
   1478 const CREATE_DELIVERY_TARGETS_NO_DELETE_SQL: &str = immutable_no_delete_sql!(
   1479     "delivery_targets_no_delete",
   1480     "delivery_targets",
   1481     "publication targets are immutable"
   1482 );
   1483 const CREATE_DELIVERY_ATTEMPTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!(
   1484     "delivery_attempts_no_delete",
   1485     "delivery_attempts",
   1486     "publication attempts are immutable"
   1487 );
   1488 const CREATE_DISCOVERY_DESIRED_STATE_TABLE_SQL: &str = discovery_desired_state_table_sql!();
   1489 const CREATE_DISCOVERY_DOCUMENTS_TABLE_SQL: &str = discovery_documents_table_sql!();
   1490 const CREATE_DISCOVERY_PUBLICATION_STATE_TABLE_SQL: &str = discovery_publication_state_table_sql!();
   1491 const CREATE_DISCOVERY_DESIRED_STATE_NO_UPDATE_SQL: &str = immutable_no_update_sql!(
   1492     "discovery_desired_state_no_update",
   1493     "discovery_desired_state",
   1494     "discovery desired state is immutable"
   1495 );
   1496 const CREATE_DISCOVERY_DESIRED_STATE_NO_DELETE_SQL: &str = immutable_no_delete_sql!(
   1497     "discovery_desired_state_no_delete",
   1498     "discovery_desired_state",
   1499     "discovery desired state is immutable"
   1500 );
   1501 const CREATE_DISCOVERY_DOCUMENTS_NO_UPDATE_SQL: &str = immutable_no_update_sql!(
   1502     "discovery_documents_no_update",
   1503     "discovery_documents",
   1504     "discovery documents are immutable"
   1505 );
   1506 const CREATE_DISCOVERY_DOCUMENTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!(
   1507     "discovery_documents_no_delete",
   1508     "discovery_documents",
   1509     "discovery documents are immutable"
   1510 );
   1511 const CREATE_DISCOVERY_PUBLICATION_STATE_GUARD_UPDATE_SQL: &str =
   1512     discovery_publication_state_guard_update_sql!();
   1513 const CREATE_DISCOVERY_PUBLICATION_STATE_NO_DELETE_SQL: &str = immutable_no_delete_sql!(
   1514     "discovery_publication_state_no_delete",
   1515     "discovery_publication_state",
   1516     "discovery publication state is retained"
   1517 );
   1518 
   1519 const CREATE_DISCOVERY_STATE_MIGRATION_SQL: &str = concat!(
   1520     "DROP TRIGGER myc_state_metadata_no_update;\n",
   1521     "UPDATE myc_state_metadata SET state_contract_version = CASE ",
   1522     "WHEN state_contract_version = 6 THEN 7 ELSE 0 END WHERE singleton = 1;\n",
   1523     myc_state_metadata_no_update_sql!(),
   1524     ";\n",
   1525     "DROP TRIGGER publication_attempts_no_delete;\n",
   1526     "DROP TRIGGER publication_targets_no_delete;\n",
   1527     "DROP TRIGGER publication_outbox_no_delete;\n",
   1528     "DROP TRIGGER publication_attempts_guard_update;\n",
   1529     "DROP TRIGGER publication_targets_guard_update;\n",
   1530     "DROP TRIGGER publication_outbox_guard_update;\n",
   1531     delivery_jobs_table_sql!(),
   1532     ";\n",
   1533     delivery_targets_table_sql!(),
   1534     ";\n",
   1535     delivery_attempts_table_sql!(),
   1536     ";\n",
   1537     "INSERT INTO delivery_jobs (job_id, source_kind, source_id, artifact_sha256, ",
   1538     "policy_mode, required_acknowledgements, max_attempts, initial_backoff_ms, ",
   1539     "maximum_backoff_ms, attempt_deadline_ms, status, created_at_unix_ms, ",
   1540     "updated_at_unix_ms, finalized_at_unix_ms) SELECT job_id, 'signer_response', ",
   1541     "signer_operation_id, artifact_sha256, policy_mode, required_acknowledgements, ",
   1542     "max_attempts, initial_backoff_ms, maximum_backoff_ms, attempt_deadline_ms, status, ",
   1543     "created_at_unix_ms, updated_at_unix_ms, finalized_at_unix_ms FROM publication_outbox;\n",
   1544     "INSERT INTO delivery_targets SELECT * FROM publication_targets;\n",
   1545     "INSERT INTO delivery_attempts SELECT * FROM publication_attempts;\n",
   1546     "DROP TABLE publication_attempts;\n",
   1547     "DROP TABLE publication_targets;\n",
   1548     "DROP TABLE publication_outbox;\n",
   1549     delivery_jobs_guard_update_sql!(),
   1550     ";\n",
   1551     delivery_targets_guard_update_sql!(),
   1552     ";\n",
   1553     delivery_attempts_guard_update_sql!(),
   1554     ";\n",
   1555     immutable_no_delete_sql!(
   1556         "delivery_jobs_no_delete",
   1557         "delivery_jobs",
   1558         "publication jobs are immutable"
   1559     ),
   1560     ";\n",
   1561     immutable_no_delete_sql!(
   1562         "delivery_targets_no_delete",
   1563         "delivery_targets",
   1564         "publication targets are immutable"
   1565     ),
   1566     ";\n",
   1567     immutable_no_delete_sql!(
   1568         "delivery_attempts_no_delete",
   1569         "delivery_attempts",
   1570         "publication attempts are immutable"
   1571     ),
   1572     ";\n",
   1573     discovery_desired_state_table_sql!(),
   1574     ";\n",
   1575     discovery_documents_table_sql!(),
   1576     ";\n",
   1577     discovery_publication_state_table_sql!(),
   1578     ";\n",
   1579     delivery_jobs_guard_insert_sql!(),
   1580     ";\n",
   1581     immutable_no_update_sql!(
   1582         "discovery_desired_state_no_update",
   1583         "discovery_desired_state",
   1584         "discovery desired state is immutable"
   1585     ),
   1586     ";\n",
   1587     immutable_no_delete_sql!(
   1588         "discovery_desired_state_no_delete",
   1589         "discovery_desired_state",
   1590         "discovery desired state is immutable"
   1591     ),
   1592     ";\n",
   1593     immutable_no_update_sql!(
   1594         "discovery_documents_no_update",
   1595         "discovery_documents",
   1596         "discovery documents are immutable"
   1597     ),
   1598     ";\n",
   1599     immutable_no_delete_sql!(
   1600         "discovery_documents_no_delete",
   1601         "discovery_documents",
   1602         "discovery documents are immutable"
   1603     ),
   1604     ";\n",
   1605     discovery_publication_state_guard_update_sql!(),
   1606     ";\n",
   1607     immutable_no_delete_sql!(
   1608         "discovery_publication_state_no_delete",
   1609         "discovery_publication_state",
   1610         "discovery publication state is retained"
   1611     ),
   1612 );
   1613 
   1614 macro_rules! nip46_operation_commits_table_sql {
   1615     () => {
   1616         r#"CREATE TABLE nip46_operation_commits (
   1617     operation_id BLOB NOT NULL PRIMARY KEY CHECK (length(operation_id) = 32)
   1618         REFERENCES nip46_requests(operation_id),
   1619     correlation_id BLOB NOT NULL UNIQUE CHECK (length(correlation_id) = 32),
   1620     method TEXT NOT NULL CHECK (method IN (
   1621         'connect', 'get_public_key', 'get_session_capability', 'sign_event',
   1622         'nip04_encrypt', 'nip04_decrypt', 'nip44_encrypt', 'nip44_decrypt',
   1623         'ping', 'switch_relays', 'logout'
   1624     )),
   1625     connection_id BLOB CHECK (connection_id IS NULL OR length(connection_id) = 32)
   1626         REFERENCES connections(connection_id),
   1627     session_effect TEXT NOT NULL CHECK (session_effect IN (
   1628         'none', 'connection_admitted', 'connection_revoked'
   1629     )),
   1630     provider_operation_id BLOB UNIQUE
   1631         CHECK (provider_operation_id IS NULL OR length(provider_operation_id) = 32),
   1632     provider_artifact_kind TEXT NOT NULL CHECK (provider_artifact_kind IN (
   1633         'none', 'signed_event'
   1634     )),
   1635     provider_artifact_sha256 BLOB
   1636         CHECK (provider_artifact_sha256 IS NULL OR length(provider_artifact_sha256) = 32),
   1637     provider_artifact BLOB
   1638         CHECK (provider_artifact IS NULL OR length(provider_artifact) BETWEEN 1 AND 1048576),
   1639     outcome TEXT NOT NULL CHECK (outcome = 'succeeded'),
   1640     reason_code TEXT NOT NULL CHECK (reason_code IN (
   1641         'completed', 'connection_admitted', 'connection_denied', 'session_revoked'
   1642     )),
   1643     completed_at_unix_ms INTEGER NOT NULL
   1644         CHECK (completed_at_unix_ms BETWEEN 1 AND 9223372036854775807),
   1645     CHECK (
   1646         (method = 'connect' AND session_effect = 'connection_admitted'
   1647             AND connection_id IS NOT NULL AND reason_code = 'connection_admitted')
   1648         OR (method = 'connect' AND session_effect = 'none'
   1649             AND connection_id IS NULL AND reason_code = 'connection_denied')
   1650         OR (method = 'logout' AND session_effect = 'connection_revoked'
   1651             AND connection_id IS NOT NULL AND reason_code = 'session_revoked')
   1652         OR (method NOT IN ('connect', 'logout') AND session_effect = 'none'
   1653             AND connection_id IS NOT NULL AND reason_code = 'completed')
   1654     ),
   1655     CHECK (
   1656         (method IN ('sign_event', 'nip04_encrypt', 'nip04_decrypt',
   1657                 'nip44_encrypt', 'nip44_decrypt') AND provider_operation_id IS NOT NULL)
   1658         OR (method NOT IN ('sign_event', 'nip04_encrypt', 'nip04_decrypt',
   1659                 'nip44_encrypt', 'nip44_decrypt') AND provider_operation_id IS NULL)
   1660     ),
   1661     CHECK (
   1662         (method = 'sign_event' AND provider_artifact_kind = 'signed_event'
   1663             AND provider_artifact_sha256 IS NOT NULL AND provider_artifact IS NOT NULL)
   1664         OR (method != 'sign_event' AND provider_artifact_kind = 'none'
   1665             AND provider_artifact_sha256 IS NULL AND provider_artifact IS NULL)
   1666     )
   1667 ) STRICT"#
   1668     };
   1669 }
   1670 
   1671 macro_rules! nip46_operation_commits_no_update_sql {
   1672     () => {
   1673         r#"CREATE TRIGGER nip46_operation_commits_no_update
   1674 BEFORE UPDATE ON nip46_operation_commits
   1675 BEGIN
   1676     SELECT RAISE(ABORT, 'NIP-46 operation completion is immutable');
   1677 END"#
   1678     };
   1679 }
   1680 
   1681 macro_rules! nip46_operation_commits_no_delete_sql {
   1682     () => {
   1683         r#"CREATE TRIGGER nip46_operation_commits_no_delete
   1684 BEFORE DELETE ON nip46_operation_commits
   1685 BEGIN
   1686     SELECT RAISE(ABORT, 'NIP-46 operation completion is retained');
   1687 END"#
   1688     };
   1689 }
   1690 
   1691 const CREATE_NIP46_OPERATION_COMMITS_TABLE_SQL: &str = nip46_operation_commits_table_sql!();
   1692 const CREATE_NIP46_OPERATION_COMMITS_NO_UPDATE_SQL: &str = nip46_operation_commits_no_update_sql!();
   1693 const CREATE_NIP46_OPERATION_COMMITS_NO_DELETE_SQL: &str = nip46_operation_commits_no_delete_sql!();
   1694 
   1695 const CREATE_NIP46_OPERATION_COMPLETION_MIGRATION_SQL: &str = concat!(
   1696     "DROP TRIGGER myc_state_metadata_no_update;\n",
   1697     "UPDATE myc_state_metadata SET state_contract_version = CASE ",
   1698     "WHEN state_contract_version = 7 THEN 8 ELSE 0 END WHERE singleton = 1;\n",
   1699     myc_state_metadata_no_update_sql!(),
   1700     ";\n",
   1701     nip46_operation_commits_table_sql!(),
   1702     ";\n",
   1703     nip46_operation_commits_no_update_sql!(),
   1704     ";\n",
   1705     nip46_operation_commits_no_delete_sql!(),
   1706 );
   1707 
   1708 macro_rules! nip46_signed_responses_table_sql {
   1709     () => {
   1710         r#"CREATE TABLE nip46_signed_responses (
   1711     operation_id BLOB NOT NULL PRIMARY KEY CHECK (length(operation_id) = 32)
   1712         REFERENCES nip46_operation_commits(operation_id),
   1713     response_provider_operation_id BLOB NOT NULL UNIQUE
   1714         CHECK (length(response_provider_operation_id) = 32),
   1715     response_event_id BLOB NOT NULL UNIQUE CHECK (length(response_event_id) = 32),
   1716     response_sha256 BLOB NOT NULL CHECK (length(response_sha256) = 32),
   1717     response_bytes BLOB NOT NULL
   1718         CHECK (length(response_bytes) BETWEEN 1 AND 1048576),
   1719     authored_at_unix_s INTEGER NOT NULL
   1720         CHECK (authored_at_unix_s BETWEEN 1 AND 9223372036854775807),
   1721     committed_at_unix_ms INTEGER NOT NULL
   1722         CHECK (committed_at_unix_ms BETWEEN 1 AND 9223372036854775807)
   1723 ) STRICT"#
   1724     };
   1725 }
   1726 
   1727 macro_rules! nip46_signed_responses_no_update_sql {
   1728     () => {
   1729         r#"CREATE TRIGGER nip46_signed_responses_no_update
   1730 BEFORE UPDATE ON nip46_signed_responses
   1731 BEGIN
   1732     SELECT RAISE(ABORT, 'NIP-46 signed response is immutable');
   1733 END"#
   1734     };
   1735 }
   1736 
   1737 macro_rules! nip46_signed_responses_no_delete_sql {
   1738     () => {
   1739         r#"CREATE TRIGGER nip46_signed_responses_no_delete
   1740 BEFORE DELETE ON nip46_signed_responses
   1741 BEGIN
   1742     SELECT RAISE(ABORT, 'NIP-46 signed response is retained');
   1743 END"#
   1744     };
   1745 }
   1746 
   1747 const CREATE_NIP46_SIGNED_RESPONSES_TABLE_SQL: &str = nip46_signed_responses_table_sql!();
   1748 const CREATE_NIP46_SIGNED_RESPONSES_NO_UPDATE_SQL: &str = nip46_signed_responses_no_update_sql!();
   1749 const CREATE_NIP46_SIGNED_RESPONSES_NO_DELETE_SQL: &str = nip46_signed_responses_no_delete_sql!();
   1750 
   1751 const CREATE_NIP46_ATOMIC_RESPONSE_MIGRATION_SQL: &str = concat!(
   1752     "DROP TRIGGER myc_state_metadata_no_update;\n",
   1753     "UPDATE myc_state_metadata SET state_contract_version = CASE ",
   1754     "WHEN state_contract_version = 8 THEN 9 ELSE 0 END WHERE singleton = 1;\n",
   1755     myc_state_metadata_no_update_sql!(),
   1756     ";\n",
   1757     nip46_signed_responses_table_sql!(),
   1758     ";\n",
   1759     nip46_signed_responses_no_update_sql!(),
   1760     ";\n",
   1761     nip46_signed_responses_no_delete_sql!(),
   1762 );
   1763 
   1764 macro_rules! nip46_pending_responses_table_sql {
   1765     () => {
   1766         r#"CREATE TABLE nip46_pending_responses (
   1767     operation_id BLOB NOT NULL PRIMARY KEY CHECK (length(operation_id) = 32)
   1768         REFERENCES nip46_requests(operation_id),
   1769     connection_id BLOB NOT NULL CHECK (length(connection_id) = 32)
   1770         REFERENCES connections(connection_id),
   1771     response_kind TEXT NOT NULL CHECK (response_kind = 'pending_approval'),
   1772     response_provider_operation_id BLOB NOT NULL UNIQUE
   1773         CHECK (length(response_provider_operation_id) = 32),
   1774     response_event_id BLOB NOT NULL UNIQUE CHECK (length(response_event_id) = 32),
   1775     response_sha256 BLOB NOT NULL CHECK (length(response_sha256) = 32),
   1776     response_bytes BLOB NOT NULL
   1777         CHECK (length(response_bytes) BETWEEN 1 AND 1048576),
   1778     authored_at_unix_s INTEGER NOT NULL
   1779         CHECK (authored_at_unix_s BETWEEN 1 AND 9223372036854775807),
   1780     committed_at_unix_ms INTEGER NOT NULL
   1781         CHECK (committed_at_unix_ms BETWEEN 1 AND 9223372036854775807)
   1782 ) STRICT"#
   1783     };
   1784 }
   1785 
   1786 macro_rules! nip46_pending_responses_guard_insert_sql {
   1787     () => {
   1788         r#"CREATE TRIGGER nip46_pending_responses_guard_insert
   1789 BEFORE INSERT ON nip46_pending_responses
   1790 WHEN NOT EXISTS (
   1791         SELECT 1
   1792         FROM nip46_request_decisions AS decision
   1793         JOIN connections AS connection
   1794             ON connection.connection_id = decision.connection_id
   1795         JOIN nip46_requests AS request
   1796             ON request.operation_id = decision.operation_id
   1797         WHERE decision.operation_id = NEW.operation_id
   1798             AND decision.connection_id = NEW.connection_id
   1799             AND decision.decision = 'pending_approval'
   1800             AND decision.reason_code = 'explicit_approval_required'
   1801             AND connection.status = 'pending'
   1802             AND connection.client_public_key = request.client_public_key
   1803             AND connection.policy_generation = decision.policy_generation
   1804             AND connection.requested_permissions_sha256 = decision.requested_permissions_sha256
   1805             AND request.method = 'connect'
   1806     )
   1807     OR EXISTS (
   1808         SELECT 1 FROM nip46_signed_responses
   1809         WHERE operation_id = NEW.operation_id
   1810             OR response_provider_operation_id = NEW.response_provider_operation_id
   1811             OR response_event_id = NEW.response_event_id
   1812     )
   1813 BEGIN
   1814     SELECT RAISE(ABORT, 'pending NIP-46 response binding is invalid');
   1815 END"#
   1816     };
   1817 }
   1818 
   1819 macro_rules! nip46_signed_responses_guard_pending_insert_sql {
   1820     () => {
   1821         r#"CREATE TRIGGER nip46_signed_responses_guard_pending_insert
   1822 BEFORE INSERT ON nip46_signed_responses
   1823 WHEN EXISTS (
   1824     SELECT 1 FROM nip46_pending_responses
   1825     WHERE operation_id = NEW.operation_id
   1826         OR response_provider_operation_id = NEW.response_provider_operation_id
   1827         OR response_event_id = NEW.response_event_id
   1828 )
   1829 BEGIN
   1830     SELECT RAISE(ABORT, 'terminal NIP-46 response conflicts with pending authority');
   1831 END"#
   1832     };
   1833 }
   1834 
   1835 macro_rules! nip46_pending_responses_no_update_sql {
   1836     () => {
   1837         r#"CREATE TRIGGER nip46_pending_responses_no_update
   1838 BEFORE UPDATE ON nip46_pending_responses
   1839 BEGIN
   1840     SELECT RAISE(ABORT, 'pending NIP-46 response is immutable');
   1841 END"#
   1842     };
   1843 }
   1844 
   1845 macro_rules! nip46_pending_responses_no_delete_sql {
   1846     () => {
   1847         r#"CREATE TRIGGER nip46_pending_responses_no_delete
   1848 BEFORE DELETE ON nip46_pending_responses
   1849 BEGIN
   1850     SELECT RAISE(ABORT, 'pending NIP-46 response is retained');
   1851 END"#
   1852     };
   1853 }
   1854 
   1855 const CREATE_NIP46_PENDING_RESPONSES_TABLE_SQL: &str = nip46_pending_responses_table_sql!();
   1856 const CREATE_NIP46_PENDING_RESPONSES_GUARD_INSERT_SQL: &str =
   1857     nip46_pending_responses_guard_insert_sql!();
   1858 const CREATE_NIP46_SIGNED_RESPONSES_GUARD_PENDING_INSERT_SQL: &str =
   1859     nip46_signed_responses_guard_pending_insert_sql!();
   1860 const CREATE_NIP46_PENDING_RESPONSES_NO_UPDATE_SQL: &str = nip46_pending_responses_no_update_sql!();
   1861 const CREATE_NIP46_PENDING_RESPONSES_NO_DELETE_SQL: &str = nip46_pending_responses_no_delete_sql!();
   1862 
   1863 const CREATE_NIP46_PENDING_RESPONSE_MIGRATION_SQL: &str = concat!(
   1864     nip46_pending_responses_table_sql!(),
   1865     ";\n",
   1866     nip46_pending_responses_guard_insert_sql!(),
   1867     ";\n",
   1868     nip46_signed_responses_guard_pending_insert_sql!(),
   1869     ";\n",
   1870     nip46_pending_responses_no_update_sql!(),
   1871     ";\n",
   1872     nip46_pending_responses_no_delete_sql!(),
   1873     ";",
   1874 );
   1875 
   1876 macro_rules! myc_config_bindings_table_sql {
   1877     () => {
   1878         r#"CREATE TABLE myc_config_bindings (
   1879     generation INTEGER NOT NULL PRIMARY KEY CHECK (generation BETWEEN 1 AND 1024),
   1880     normalized_config_sha256 BLOB NOT NULL CHECK (length(normalized_config_sha256) = 32),
   1881     transport_public_key TEXT NOT NULL
   1882         CHECK (length(CAST(transport_public_key AS BLOB)) = 64)
   1883         CHECK (transport_public_key NOT GLOB '*[^0-9a-f]*'),
   1884     user_public_key TEXT NOT NULL
   1885         CHECK (length(CAST(user_public_key AS BLOB)) = 64)
   1886         CHECK (user_public_key NOT GLOB '*[^0-9a-f]*'),
   1887     discovery_public_key TEXT
   1888         CHECK (discovery_public_key IS NULL OR
   1889             (length(CAST(discovery_public_key AS BLOB)) = 64
   1890                 AND discovery_public_key NOT GLOB '*[^0-9a-f]*')),
   1891     config_contract_version INTEGER NOT NULL
   1892         CHECK (config_contract_version BETWEEN 1 AND 4294967295),
   1893     state_contract_version INTEGER NOT NULL
   1894         CHECK (state_contract_version BETWEEN 1 AND 4294967295),
   1895     operator_contract_version INTEGER NOT NULL
   1896         CHECK (operator_contract_version BETWEEN 1 AND 4294967295),
   1897     status_contract_version INTEGER NOT NULL
   1898         CHECK (status_contract_version BETWEEN 1 AND 4294967295),
   1899     applied_at_unix_s INTEGER NOT NULL
   1900         CHECK (applied_at_unix_s BETWEEN 0 AND 9223372036854775807),
   1901     service_version TEXT NOT NULL
   1902         CHECK (length(CAST(service_version AS BLOB)) BETWEEN 1 AND 128),
   1903     service_commit TEXT NOT NULL
   1904         CHECK (length(CAST(service_commit AS BLOB)) = 40),
   1905     lib_revision TEXT NOT NULL
   1906         CHECK (length(CAST(lib_revision AS BLOB)) = 40),
   1907     rust_version TEXT NOT NULL
   1908         CHECK (length(CAST(rust_version AS BLOB)) BETWEEN 1 AND 128),
   1909     target TEXT NOT NULL CHECK (length(CAST(target AS BLOB)) BETWEEN 1 AND 128),
   1910     feature_profile TEXT NOT NULL
   1911         CHECK (length(CAST(feature_profile AS BLOB)) BETWEEN 1 AND 128),
   1912     provider_contract_version INTEGER NOT NULL
   1913         CHECK (provider_contract_version BETWEEN 1 AND 4294967295)
   1914 ) STRICT"#
   1915     };
   1916 }
   1917 
   1918 macro_rules! myc_config_bindings_guard_insert_sql {
   1919     () => {
   1920         r#"CREATE TRIGGER myc_config_bindings_guard_insert
   1921 BEFORE INSERT ON myc_config_bindings
   1922 WHEN NEW.generation != COALESCE(
   1923         (SELECT MAX(generation) + 1 FROM myc_config_bindings), 1
   1924     )
   1925     OR (SELECT COUNT(*) FROM myc_config_bindings) >= 1024
   1926     OR NEW.applied_at_unix_s < COALESCE(
   1927         (SELECT MAX(applied_at_unix_s) FROM myc_config_bindings), 0
   1928     )
   1929 BEGIN
   1930     SELECT RAISE(ABORT, 'configuration binding sequence is invalid');
   1931 END"#
   1932     };
   1933 }
   1934 
   1935 macro_rules! myc_config_bindings_no_update_sql {
   1936     () => {
   1937         r#"CREATE TRIGGER myc_config_bindings_no_update
   1938 BEFORE UPDATE ON myc_config_bindings
   1939 BEGIN
   1940     SELECT RAISE(ABORT, 'configuration binding history is immutable');
   1941 END"#
   1942     };
   1943 }
   1944 
   1945 macro_rules! myc_config_bindings_no_delete_sql {
   1946     () => {
   1947         r#"CREATE TRIGGER myc_config_bindings_no_delete
   1948 BEFORE DELETE ON myc_config_bindings
   1949 BEGIN
   1950     SELECT RAISE(ABORT, 'configuration binding history is retained');
   1951 END"#
   1952     };
   1953 }
   1954 
   1955 const CREATE_MYC_CONFIG_BINDINGS_TABLE_SQL: &str = myc_config_bindings_table_sql!();
   1956 const CREATE_MYC_CONFIG_BINDINGS_GUARD_INSERT_SQL: &str = myc_config_bindings_guard_insert_sql!();
   1957 const CREATE_MYC_CONFIG_BINDINGS_NO_UPDATE_SQL: &str = myc_config_bindings_no_update_sql!();
   1958 const CREATE_MYC_CONFIG_BINDINGS_NO_DELETE_SQL: &str = myc_config_bindings_no_delete_sql!();
   1959 
   1960 const CREATE_MYC_CONFIG_BINDINGS_MIGRATION_SQL: &str = concat!(
   1961     myc_config_bindings_table_sql!(),
   1962     ";\n",
   1963     myc_config_bindings_guard_insert_sql!(),
   1964     ";\n",
   1965     myc_config_bindings_no_update_sql!(),
   1966     ";\n",
   1967     myc_config_bindings_no_delete_sql!(),
   1968     ";",
   1969 );
   1970 
   1971 macro_rules! myc_admin_operations_table_sql {
   1972     () => {
   1973         r#"CREATE TABLE myc_admin_operations (
   1974     operation_id TEXT NOT NULL PRIMARY KEY
   1975         CHECK (length(CAST(operation_id AS BLOB)) BETWEEN 1 AND 128)
   1976         CHECK (substr(operation_id, 1, 1) GLOB '[A-Za-z0-9]')
   1977         CHECK (operation_id NOT GLOB '*[^A-Za-z0-9._:-]*'),
   1978     route TEXT NOT NULL CHECK (length(CAST(route AS BLOB)) BETWEEN 1 AND 128),
   1979     request_sha256 BLOB NOT NULL CHECK (length(request_sha256) = 32),
   1980     state TEXT NOT NULL CHECK (state IN ('prepared', 'completed')),
   1981     response_model BLOB CHECK (response_model IS NULL OR
   1982         length(response_model) BETWEEN 1 AND 8192),
   1983     response_sha256 BLOB CHECK (response_sha256 IS NULL OR
   1984         length(response_sha256) = 32),
   1985     prepared_at_unix_ms INTEGER NOT NULL
   1986         CHECK (prepared_at_unix_ms BETWEEN 0 AND 9223372036854775807),
   1987     completed_at_unix_ms INTEGER
   1988         CHECK (completed_at_unix_ms IS NULL OR
   1989             completed_at_unix_ms BETWEEN prepared_at_unix_ms AND 9223372036854775807),
   1990     expires_at_unix_ms INTEGER
   1991         CHECK (expires_at_unix_ms IS NULL OR
   1992             expires_at_unix_ms BETWEEN completed_at_unix_ms AND 9223372036854775807),
   1993     CHECK ((state = 'prepared' AND response_model IS NULL
   1994             AND response_sha256 IS NULL AND completed_at_unix_ms IS NULL
   1995             AND expires_at_unix_ms IS NULL)
   1996         OR (state = 'completed' AND response_model IS NOT NULL
   1997             AND response_sha256 IS NOT NULL AND completed_at_unix_ms IS NOT NULL
   1998             AND expires_at_unix_ms IS NOT NULL))
   1999 ) STRICT"#
   2000     };
   2001 }
   2002 
   2003 macro_rules! myc_admin_operations_guard_update_sql {
   2004     () => {
   2005         r#"CREATE TRIGGER myc_admin_operations_guard_update
   2006 BEFORE UPDATE ON myc_admin_operations
   2007 WHEN OLD.state != 'prepared' OR NEW.state != 'completed'
   2008     OR NEW.operation_id != OLD.operation_id OR NEW.route != OLD.route
   2009     OR NEW.request_sha256 != OLD.request_sha256
   2010     OR NEW.prepared_at_unix_ms != OLD.prepared_at_unix_ms
   2011     OR NEW.response_model IS NULL OR NEW.response_sha256 IS NULL
   2012     OR NEW.completed_at_unix_ms IS NULL OR NEW.expires_at_unix_ms IS NULL
   2013 BEGIN
   2014     SELECT RAISE(ABORT, 'admin operation transition is invalid');
   2015 END"#
   2016     };
   2017 }
   2018 
   2019 const CREATE_MYC_ADMIN_OPERATIONS_TABLE_SQL: &str = myc_admin_operations_table_sql!();
   2020 const CREATE_MYC_ADMIN_OPERATIONS_GUARD_UPDATE_SQL: &str = myc_admin_operations_guard_update_sql!();
   2021 const CREATE_MYC_ADMIN_OPERATIONS_MIGRATION_SQL: &str = concat!(
   2022     myc_admin_operations_table_sql!(),
   2023     ";\n",
   2024     myc_admin_operations_guard_update_sql!(),
   2025     ";",
   2026 );
   2027 
   2028 const MYC_ADMIN_OPERATIONS_TABLE_SHA256: [u8; 32] = [
   2029     0x22, 0xd6, 0xbc, 0xb4, 0x15, 0xac, 0x9a, 0xf2, 0x4e, 0x41, 0x61, 0xac, 0x2a, 0x8c, 0xae, 0xfb,
   2030     0xfb, 0x7a, 0xf0, 0xa4, 0xfe, 0xae, 0xe9, 0xe6, 0xdf, 0x36, 0x67, 0x14, 0x24, 0x5b, 0xf3, 0xf1,
   2031 ];
   2032 const MYC_ADMIN_OPERATIONS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2033     0xb9, 0x68, 0x2d, 0x07, 0xca, 0x59, 0x91, 0x3b, 0x66, 0x09, 0xdc, 0x73, 0x61, 0xc5, 0xe0, 0xee,
   2034     0x22, 0x52, 0x4f, 0x51, 0x2c, 0xbc, 0xe2, 0x8a, 0x7a, 0x8f, 0xe0, 0xd5, 0x2c, 0xfd, 0x45, 0xf6,
   2035 ];
   2036 
   2037 const NIP46_PENDING_RESPONSES_TABLE_SHA256: [u8; 32] = [
   2038     0x27, 0x99, 0x17, 0x8b, 0x41, 0xb4, 0x4b, 0xb2, 0x22, 0x2c, 0x54, 0x99, 0xbc, 0xc2, 0x67, 0x37,
   2039     0x47, 0x84, 0xe8, 0xe1, 0xd5, 0xde, 0xa2, 0xe6, 0x93, 0x6e, 0xfa, 0x9f, 0xb0, 0xc8, 0x80, 0x10,
   2040 ];
   2041 const NIP46_PENDING_RESPONSES_GUARD_INSERT_SHA256: [u8; 32] = [
   2042     0x7a, 0x8a, 0x70, 0x91, 0x63, 0x33, 0xf4, 0xb8, 0x39, 0x5e, 0xa9, 0x39, 0x6b, 0xc1, 0xd6, 0x3e,
   2043     0x4b, 0x11, 0xe9, 0x96, 0x70, 0x4d, 0x6f, 0x3b, 0xa0, 0x30, 0xac, 0xbb, 0x19, 0x5a, 0xd6, 0x8c,
   2044 ];
   2045 const NIP46_SIGNED_RESPONSES_GUARD_PENDING_INSERT_SHA256: [u8; 32] = [
   2046     0xd7, 0x30, 0xca, 0xbe, 0xe4, 0x05, 0x1b, 0xfb, 0x5a, 0x7b, 0x34, 0xe5, 0x9c, 0x1f, 0x35, 0x7b,
   2047     0x25, 0x4f, 0xea, 0x50, 0x53, 0x6d, 0xed, 0x67, 0x7e, 0x9e, 0x52, 0x67, 0x4a, 0x6b, 0x15, 0xbe,
   2048 ];
   2049 const NIP46_PENDING_RESPONSES_NO_UPDATE_SHA256: [u8; 32] = [
   2050     0x7a, 0xfa, 0xc0, 0xb6, 0x19, 0x61, 0x2d, 0xf8, 0xfe, 0xab, 0xe0, 0x27, 0xa8, 0x18, 0x82, 0x7b,
   2051     0xa6, 0x5c, 0x84, 0xed, 0x11, 0x1f, 0x2d, 0x7e, 0xf3, 0xee, 0xdd, 0x3b, 0xaa, 0x3c, 0x7d, 0x4e,
   2052 ];
   2053 const NIP46_PENDING_RESPONSES_NO_DELETE_SHA256: [u8; 32] = [
   2054     0xa2, 0x95, 0x91, 0x8a, 0x52, 0x2e, 0xfb, 0xf3, 0xbf, 0x94, 0x73, 0xeb, 0x58, 0x60, 0x67, 0xad,
   2055     0x4d, 0x28, 0x64, 0x2f, 0xbb, 0x02, 0xca, 0xf3, 0xdf, 0x2f, 0x2a, 0x02, 0xfd, 0xe1, 0x5d, 0x1b,
   2056 ];
   2057 
   2058 const MYC_CONFIG_BINDINGS_TABLE_SHA256: [u8; 32] = [
   2059     0xf7, 0x7a, 0x0b, 0xc4, 0x4a, 0xb0, 0xf9, 0x18, 0x09, 0xed, 0x6a, 0xb1, 0xaa, 0x0c, 0x9e, 0xd8,
   2060     0x80, 0x4c, 0xac, 0x8f, 0x12, 0x15, 0xf1, 0x15, 0xd5, 0x7e, 0x1b, 0x42, 0xe4, 0x20, 0xf2, 0x60,
   2061 ];
   2062 const MYC_CONFIG_BINDINGS_GUARD_INSERT_SHA256: [u8; 32] = [
   2063     0x28, 0x4c, 0xc3, 0xa6, 0xe6, 0xb2, 0x42, 0x2c, 0x71, 0x42, 0xb9, 0x43, 0x2f, 0x67, 0x29, 0x20,
   2064     0x4d, 0xa7, 0x03, 0xde, 0x21, 0xec, 0x8e, 0xbc, 0xe1, 0xc4, 0xda, 0x24, 0x60, 0x43, 0x5d, 0xce,
   2065 ];
   2066 const MYC_CONFIG_BINDINGS_NO_UPDATE_SHA256: [u8; 32] = [
   2067     0xba, 0xcc, 0x52, 0x41, 0x3e, 0x4b, 0xc2, 0x68, 0x01, 0xbc, 0xfd, 0xa0, 0x8b, 0xda, 0xdb, 0x1f,
   2068     0x24, 0xd0, 0x6d, 0x86, 0xa1, 0x79, 0x72, 0xd2, 0x93, 0x6b, 0xcf, 0xfb, 0xdd, 0xc7, 0xa0, 0xe5,
   2069 ];
   2070 const MYC_CONFIG_BINDINGS_NO_DELETE_SHA256: [u8; 32] = [
   2071     0xb5, 0x2b, 0x12, 0xde, 0xec, 0xc3, 0x2b, 0xe8, 0x5e, 0x48, 0xa9, 0x91, 0xc1, 0x4b, 0xff, 0xc0,
   2072     0x0d, 0xe9, 0xfc, 0x24, 0x44, 0x62, 0x83, 0xf3, 0x7c, 0x05, 0xa3, 0x52, 0xdf, 0xfa, 0xcf, 0x5c,
   2073 ];
   2074 
   2075 const CONNECTIONS_TABLE_SHA256: [u8; 32] = [
   2076     0x72, 0xd5, 0xd8, 0xba, 0x24, 0x68, 0x9c, 0x93, 0x34, 0xb3, 0x8f, 0xbf, 0x64, 0x21, 0xe1, 0x65,
   2077     0xfd, 0xc3, 0x80, 0x46, 0xf1, 0x3f, 0x56, 0x49, 0x3a, 0xef, 0xd7, 0x42, 0xc4, 0xe6, 0x49, 0x85,
   2078 ];
   2079 const CONNECTION_PERMISSIONS_TABLE_SHA256: [u8; 32] = [
   2080     0xc0, 0x84, 0xe6, 0x03, 0xa3, 0xb8, 0xa3, 0x78, 0xeb, 0x58, 0x00, 0x6f, 0x1c, 0x1c, 0xdd, 0x76,
   2081     0x7f, 0x67, 0xc7, 0xf4, 0xc8, 0x9d, 0x4c, 0x58, 0x02, 0x57, 0x2d, 0xca, 0x1e, 0x7d, 0x83, 0x02,
   2082 ];
   2083 const NIP46_REQUEST_DECISIONS_TABLE_SHA256: [u8; 32] = [
   2084     0xe8, 0x53, 0x1d, 0xed, 0xad, 0x22, 0xfd, 0xfe, 0x96, 0xd4, 0x17, 0x04, 0xea, 0x05, 0x6d, 0xf1,
   2085     0x2f, 0xc2, 0x99, 0xac, 0x1a, 0xbf, 0x73, 0xff, 0xcc, 0x6f, 0x2c, 0x5f, 0xdc, 0x27, 0xd9, 0x80,
   2086 ];
   2087 const CONNECTION_AUTH_CHALLENGES_TABLE_SHA256: [u8; 32] = [
   2088     0x65, 0x09, 0x11, 0x3c, 0x4b, 0xfa, 0x30, 0x16, 0x7e, 0x0b, 0xc8, 0xf6, 0x67, 0xf5, 0x38, 0xc5,
   2089     0x5a, 0xd9, 0x4e, 0x0e, 0xb7, 0x18, 0x22, 0x94, 0x73, 0xea, 0x11, 0x74, 0x9c, 0x8e, 0xa4, 0x37,
   2090 ];
   2091 const CONNECTIONS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2092     0x66, 0x61, 0xb0, 0xc6, 0x78, 0x3a, 0x0d, 0x4a, 0x01, 0xb9, 0x7e, 0x7e, 0xd0, 0x8e, 0x2b, 0x6e,
   2093     0xdb, 0xd5, 0x3a, 0x28, 0x56, 0x11, 0x88, 0x80, 0x16, 0xf3, 0x2e, 0x5a, 0x42, 0xf0, 0xf9, 0xfe,
   2094 ];
   2095 const CONNECTIONS_NO_DELETE_SHA256: [u8; 32] = [
   2096     0xb0, 0xcf, 0x50, 0x22, 0x23, 0x2a, 0xab, 0x23, 0x62, 0x1f, 0xfc, 0x54, 0x8c, 0xc5, 0x88, 0xdb,
   2097     0x8c, 0x6e, 0x4a, 0xe0, 0x91, 0x48, 0x0d, 0xda, 0xc8, 0x79, 0x4b, 0x6c, 0x0c, 0x06, 0x3f, 0xaa,
   2098 ];
   2099 const CONNECTION_PERMISSIONS_NO_UPDATE_SHA256: [u8; 32] = [
   2100     0x5e, 0x11, 0x4c, 0xa4, 0x28, 0x69, 0x0e, 0xa7, 0x64, 0x3d, 0x67, 0xbc, 0x30, 0x0f, 0x3f, 0xf1,
   2101     0xe9, 0x7e, 0xfe, 0x2f, 0x8d, 0xbd, 0x7b, 0x79, 0x47, 0x18, 0x56, 0x3d, 0xb6, 0x64, 0x70, 0x1f,
   2102 ];
   2103 const CONNECTION_PERMISSIONS_NO_DELETE_SHA256: [u8; 32] = [
   2104     0xd0, 0x27, 0x41, 0x8e, 0x03, 0x72, 0x87, 0x09, 0x16, 0x49, 0x1d, 0x83, 0x28, 0x98, 0xb9, 0x47,
   2105     0xe1, 0x1f, 0xf8, 0xe6, 0x57, 0xbd, 0x89, 0x2c, 0x90, 0xa5, 0x5c, 0x30, 0x51, 0xfe, 0x2b, 0xd7,
   2106 ];
   2107 const NIP46_REQUEST_DECISIONS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2108     0x1b, 0xf7, 0xe9, 0xb9, 0x52, 0x64, 0x95, 0x6b, 0x43, 0xf2, 0xc8, 0xdd, 0x73, 0x82, 0xc8, 0xbf,
   2109     0x0a, 0xc3, 0xcc, 0x91, 0xa2, 0x95, 0xd7, 0xe2, 0x25, 0xc1, 0xcb, 0xc2, 0xc3, 0xa8, 0x1b, 0x26,
   2110 ];
   2111 const NIP46_REQUEST_DECISIONS_NO_DELETE_SHA256: [u8; 32] = [
   2112     0xab, 0xd0, 0x76, 0xca, 0xe9, 0x17, 0x53, 0x6d, 0xdc, 0x9d, 0x03, 0x23, 0x1e, 0xc4, 0xdc, 0xc8,
   2113     0xab, 0x8e, 0x7a, 0xc4, 0x23, 0x4e, 0x64, 0x39, 0xaa, 0x58, 0x8b, 0x54, 0x15, 0x7a, 0x2d, 0x34,
   2114 ];
   2115 const CONNECTION_AUTH_CHALLENGES_GUARD_UPDATE_SHA256: [u8; 32] = [
   2116     0xb3, 0x24, 0x1e, 0x29, 0x5b, 0x29, 0x68, 0x9b, 0x73, 0x72, 0x5d, 0xe2, 0xce, 0x7c, 0x8c, 0x2b,
   2117     0x85, 0xd0, 0xd2, 0xe1, 0xd8, 0xd0, 0x24, 0x6d, 0x35, 0x68, 0x23, 0x2b, 0x9e, 0x87, 0xe4, 0xa8,
   2118 ];
   2119 const CONNECTION_AUTH_CHALLENGES_NO_DELETE_SHA256: [u8; 32] = [
   2120     0xf3, 0xf8, 0xd1, 0x48, 0xbc, 0xde, 0x89, 0xd3, 0x34, 0xcd, 0xde, 0x51, 0x4b, 0x83, 0xa2, 0x19,
   2121     0x16, 0xe5, 0xd6, 0x72, 0xb7, 0xc3, 0x1e, 0x59, 0xcb, 0xdf, 0x3a, 0x3c, 0x33, 0x80, 0x21, 0x4f,
   2122 ];
   2123 const MYC_AUDIT_STATE_TABLE_SHA256: [u8; 32] = [
   2124     0xc8, 0x6b, 0x49, 0xf6, 0x55, 0xac, 0x2c, 0xa4, 0xcb, 0x13, 0xed, 0x31, 0xff, 0x9e, 0xce, 0xe3,
   2125     0x2f, 0xd4, 0x2a, 0x3e, 0xb0, 0xf1, 0xc8, 0x52, 0x9d, 0x92, 0xae, 0x5b, 0x48, 0x63, 0x38, 0x3b,
   2126 ];
   2127 const OPERATION_AUDIT_TABLE_SHA256: [u8; 32] = [
   2128     0xc1, 0x8d, 0x0b, 0x72, 0x34, 0xff, 0x8b, 0x21, 0x9f, 0x54, 0x20, 0x7f, 0x6c, 0x0b, 0x64, 0xae,
   2129     0xd6, 0x8d, 0xd6, 0x1b, 0x48, 0xb3, 0x5b, 0xbe, 0x13, 0x2c, 0x0d, 0xb0, 0x9b, 0xea, 0x16, 0x2d,
   2130 ];
   2131 const NIP46_REQUEST_AUDIT_TABLE_SHA256: [u8; 32] = [
   2132     0xe2, 0x42, 0x82, 0x0b, 0xbb, 0xb2, 0x31, 0xa3, 0x8e, 0x9e, 0x7d, 0xf3, 0xf0, 0xe4, 0xd3, 0xc6,
   2133     0x85, 0x93, 0x19, 0xe1, 0x2e, 0x47, 0x84, 0x48, 0x98, 0x8b, 0xc0, 0xdf, 0xdf, 0x96, 0xc6, 0xe3,
   2134 ];
   2135 const CONNECTION_RATE_WINDOWS_TABLE_SHA256: [u8; 32] = [
   2136     0x57, 0x53, 0xdf, 0x7b, 0x74, 0x44, 0x96, 0x9d, 0x88, 0x56, 0xe6, 0x1f, 0x15, 0x36, 0xdc, 0xab,
   2137     0xa0, 0x02, 0x0a, 0x78, 0x77, 0x8e, 0x48, 0xa2, 0x80, 0x97, 0xc6, 0x37, 0xa6, 0x31, 0x17, 0xfc,
   2138 ];
   2139 const MYC_AUDIT_STATE_GUARD_UPDATE_SHA256: [u8; 32] = [
   2140     0xda, 0xba, 0xc9, 0x86, 0x0f, 0x2a, 0xd8, 0xa0, 0x60, 0x75, 0x4b, 0x87, 0x78, 0xc8, 0xd8, 0xce,
   2141     0x78, 0xa3, 0x57, 0x6e, 0xea, 0x08, 0x2b, 0x0c, 0x9c, 0x56, 0x5d, 0xa2, 0xb5, 0x6c, 0x68, 0xad,
   2142 ];
   2143 const MYC_AUDIT_STATE_NO_DELETE_SHA256: [u8; 32] = [
   2144     0x0a, 0x88, 0xa1, 0xbe, 0xe8, 0x23, 0x1f, 0xf0, 0xaf, 0x41, 0x91, 0xd7, 0x38, 0x64, 0x67, 0xb6,
   2145     0xa8, 0xac, 0xda, 0xf0, 0x38, 0x8e, 0xd4, 0xb0, 0xac, 0x2c, 0xb6, 0xf2, 0x0a, 0xa1, 0xf5, 0x5c,
   2146 ];
   2147 const OPERATION_AUDIT_NO_UPDATE_SHA256: [u8; 32] = [
   2148     0xd8, 0xe4, 0x39, 0x63, 0x67, 0x74, 0x97, 0x4c, 0xa7, 0x97, 0x54, 0x6c, 0xed, 0x39, 0x9a, 0x7b,
   2149     0xbc, 0x6c, 0x36, 0xc5, 0xd7, 0x8e, 0xf4, 0x08, 0xbd, 0xfd, 0xb7, 0x9b, 0xd0, 0x36, 0x74, 0x40,
   2150 ];
   2151 const NIP46_REQUEST_AUDIT_NO_UPDATE_SHA256: [u8; 32] = [
   2152     0x8a, 0x4a, 0x99, 0x4c, 0x13, 0x5f, 0x8d, 0x4d, 0x85, 0xd1, 0x25, 0x1d, 0x65, 0x47, 0x4d, 0x23,
   2153     0x37, 0x62, 0xb7, 0x27, 0xb6, 0x7f, 0x31, 0xd4, 0x9c, 0x93, 0xe5, 0xce, 0x18, 0x43, 0xba, 0x81,
   2154 ];
   2155 const CONNECTION_RATE_WINDOWS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2156     0x59, 0x3c, 0xfb, 0xff, 0x20, 0x95, 0x32, 0x4e, 0x61, 0xdc, 0xd6, 0x09, 0xea, 0x7b, 0x1b, 0x1d,
   2157     0xc4, 0xb9, 0xb7, 0x38, 0xcf, 0x80, 0x56, 0x00, 0xa5, 0x3b, 0xb4, 0xcd, 0x02, 0xcd, 0xe1, 0xef,
   2158 ];
   2159 const PUBLICATION_OUTBOX_TABLE_SHA256: [u8; 32] = [
   2160     0x26, 0xbd, 0xa8, 0x77, 0x39, 0x07, 0xdb, 0x05, 0xa8, 0x7c, 0x38, 0x21, 0x9b, 0x58, 0xd7, 0xf8,
   2161     0xc8, 0x01, 0x80, 0xb3, 0x50, 0xae, 0x69, 0x87, 0xd2, 0x13, 0xd1, 0x84, 0xc6, 0x1d, 0x15, 0x0c,
   2162 ];
   2163 const PUBLICATION_TARGETS_TABLE_SHA256: [u8; 32] = [
   2164     0x16, 0xd5, 0xa3, 0x85, 0x71, 0x0d, 0xb1, 0x02, 0xaa, 0x25, 0x02, 0x80, 0xbb, 0xc4, 0x23, 0x44,
   2165     0x20, 0xc1, 0xa2, 0x8a, 0x33, 0xaf, 0xd0, 0xe9, 0x6b, 0x65, 0x7a, 0x79, 0xd7, 0xe3, 0x1b, 0x43,
   2166 ];
   2167 const PUBLICATION_ATTEMPTS_TABLE_SHA256: [u8; 32] = [
   2168     0x25, 0xed, 0xa7, 0xb2, 0xd5, 0x07, 0xc2, 0xe5, 0x29, 0xef, 0x07, 0x31, 0xe6, 0x84, 0x6a, 0x64,
   2169     0xe9, 0xef, 0x11, 0x47, 0x41, 0x0d, 0xc9, 0x79, 0x43, 0x06, 0x8e, 0x78, 0x47, 0xfb, 0x3b, 0x3d,
   2170 ];
   2171 const PUBLICATION_OUTBOX_GUARD_UPDATE_SHA256: [u8; 32] = [
   2172     0x6f, 0xb5, 0x23, 0x36, 0x36, 0x1d, 0xea, 0x76, 0x83, 0x4c, 0x55, 0xe3, 0xdb, 0x90, 0xf1, 0xd1,
   2173     0x84, 0xcb, 0x11, 0x23, 0x17, 0x1f, 0x09, 0xd7, 0xee, 0x9c, 0xdc, 0x70, 0x28, 0xbe, 0x24, 0xc4,
   2174 ];
   2175 const PUBLICATION_TARGETS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2176     0x3e, 0x74, 0xf3, 0x95, 0x67, 0x81, 0x3e, 0x55, 0xfd, 0xc6, 0x73, 0x50, 0xa4, 0xa4, 0x4a, 0xb1,
   2177     0x77, 0xf0, 0x12, 0x8a, 0xe7, 0xd0, 0x07, 0x3d, 0x23, 0x92, 0x89, 0x1c, 0x97, 0x9d, 0x2f, 0x34,
   2178 ];
   2179 const PUBLICATION_ATTEMPTS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2180     0x5f, 0xda, 0xc3, 0xa9, 0x01, 0x48, 0x93, 0xac, 0xb4, 0x33, 0x3f, 0xac, 0x16, 0xe9, 0x63, 0x22,
   2181     0xcb, 0x74, 0xff, 0xe6, 0x2c, 0xbf, 0x89, 0xfc, 0x59, 0x4f, 0x75, 0xc6, 0x39, 0xa0, 0x40, 0xc9,
   2182 ];
   2183 const PUBLICATION_OUTBOX_NO_DELETE_SHA256: [u8; 32] = [
   2184     0xe9, 0x0e, 0x86, 0x86, 0xe8, 0xf0, 0x51, 0xb7, 0x89, 0x97, 0x92, 0x92, 0x8c, 0x6a, 0xd6, 0x64,
   2185     0xb9, 0x79, 0xaa, 0xbf, 0xbe, 0x08, 0x5d, 0xad, 0xc0, 0x69, 0x02, 0xa7, 0x5e, 0x58, 0xa5, 0x28,
   2186 ];
   2187 const PUBLICATION_TARGETS_NO_DELETE_SHA256: [u8; 32] = [
   2188     0x19, 0x0b, 0x6b, 0x34, 0xd0, 0x69, 0x45, 0x24, 0xd8, 0x57, 0x17, 0xf7, 0x27, 0x9e, 0xd9, 0x0c,
   2189     0x5a, 0xc0, 0xc2, 0xa6, 0x63, 0xd6, 0x95, 0x2e, 0x77, 0x55, 0x8f, 0x6f, 0x7c, 0x81, 0xb0, 0x48,
   2190 ];
   2191 const PUBLICATION_ATTEMPTS_NO_DELETE_SHA256: [u8; 32] = [
   2192     0x72, 0x0a, 0x1f, 0x3a, 0x40, 0xfb, 0xf8, 0x63, 0xeb, 0x1f, 0xd4, 0x54, 0x7f, 0xa0, 0xbc, 0x43,
   2193     0x50, 0x65, 0x2b, 0xb2, 0xf0, 0x98, 0x9f, 0xda, 0x1f, 0xc6, 0x49, 0xcf, 0xd8, 0xb5, 0xd4, 0xe5,
   2194 ];
   2195 const DELIVERY_JOBS_TABLE_SHA256: [u8; 32] = [
   2196     0xbb, 0xb1, 0xcf, 0xa2, 0x5e, 0x1e, 0xdd, 0x70, 0x30, 0x61, 0xd8, 0x43, 0xbe, 0x8d, 0x8c, 0x2b,
   2197     0x16, 0x8c, 0x35, 0x6c, 0x9a, 0x9c, 0x0b, 0xe7, 0x88, 0x64, 0x18, 0xde, 0xca, 0xdd, 0x05, 0x01,
   2198 ];
   2199 const DELIVERY_TARGETS_TABLE_SHA256: [u8; 32] = [
   2200     0xce, 0xa5, 0x3a, 0xa4, 0x64, 0x18, 0xb1, 0x8e, 0xaf, 0x61, 0xe0, 0x90, 0xf9, 0x51, 0xe7, 0x76,
   2201     0x79, 0xba, 0x33, 0x97, 0xc5, 0xa9, 0x5b, 0x3c, 0xa7, 0xeb, 0x83, 0x81, 0x4a, 0x8c, 0xaf, 0x69,
   2202 ];
   2203 const DELIVERY_ATTEMPTS_TABLE_SHA256: [u8; 32] = [
   2204     0xae, 0x8c, 0x2a, 0xa4, 0x61, 0xeb, 0xb2, 0x04, 0x69, 0x7b, 0xdc, 0x57, 0xc9, 0x34, 0x9c, 0x1b,
   2205     0x86, 0x4b, 0x0f, 0xcd, 0x7b, 0xba, 0x9a, 0x45, 0xa7, 0x72, 0x2b, 0x49, 0xa0, 0x95, 0x94, 0xb8,
   2206 ];
   2207 const DELIVERY_JOBS_GUARD_INSERT_SHA256: [u8; 32] = [
   2208     0x29, 0x60, 0xe9, 0x9e, 0x32, 0xcd, 0x50, 0x0a, 0xfb, 0xa2, 0x5a, 0xc6, 0xbc, 0x2b, 0xfc, 0xa0,
   2209     0x1a, 0x71, 0x95, 0x68, 0xa6, 0x2c, 0xa7, 0xac, 0x63, 0xd4, 0x79, 0x30, 0xc8, 0x5a, 0x8f, 0x7f,
   2210 ];
   2211 const DELIVERY_JOBS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2212     0xc9, 0x5f, 0x5c, 0xac, 0x67, 0xa5, 0xe8, 0x1e, 0x88, 0xca, 0x5d, 0xf2, 0xc4, 0x8e, 0x71, 0x39,
   2213     0xb6, 0x11, 0xc4, 0x4f, 0xa9, 0x59, 0x09, 0xea, 0xf7, 0x5e, 0x34, 0x61, 0xab, 0x5a, 0x5c, 0xe8,
   2214 ];
   2215 const DELIVERY_TARGETS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2216     0x1b, 0xf7, 0x81, 0xe9, 0x9e, 0xe2, 0xdd, 0x1a, 0xb9, 0xc7, 0xd5, 0xd4, 0x25, 0x96, 0x65, 0x11,
   2217     0x79, 0x50, 0x1f, 0x74, 0xbf, 0x1a, 0x09, 0xdb, 0x99, 0x9c, 0x19, 0x9f, 0x25, 0xff, 0x98, 0x97,
   2218 ];
   2219 const DELIVERY_ATTEMPTS_GUARD_UPDATE_SHA256: [u8; 32] = [
   2220     0x24, 0x5f, 0x0a, 0x53, 0xa0, 0xd5, 0x96, 0xa9, 0x62, 0x82, 0x70, 0xca, 0x9b, 0x89, 0x9e, 0xc2,
   2221     0xd8, 0xe7, 0xf1, 0x45, 0x81, 0x61, 0x6f, 0x61, 0x62, 0x66, 0x98, 0xf5, 0x48, 0x29, 0x76, 0x9c,
   2222 ];
   2223 const DELIVERY_JOBS_NO_DELETE_SHA256: [u8; 32] = [
   2224     0x19, 0x9b, 0x4a, 0xc3, 0x1e, 0x53, 0x87, 0xed, 0x6a, 0xbc, 0x15, 0x69, 0x51, 0x38, 0x0d, 0xf2,
   2225     0x61, 0xf7, 0x3c, 0x97, 0x0c, 0xc3, 0x7b, 0x16, 0xfc, 0x9e, 0xca, 0x47, 0x1a, 0x64, 0x3d, 0xb2,
   2226 ];
   2227 const DELIVERY_TARGETS_NO_DELETE_SHA256: [u8; 32] = [
   2228     0xa6, 0xa1, 0xd0, 0xb7, 0x42, 0xfd, 0x4f, 0xd7, 0x1d, 0x14, 0x0c, 0x64, 0xfd, 0xda, 0x1b, 0x1a,
   2229     0x60, 0xfb, 0xea, 0xc4, 0xea, 0x6e, 0x22, 0xd8, 0x12, 0x79, 0xc3, 0xee, 0xbb, 0xf8, 0xb1, 0x29,
   2230 ];
   2231 const DELIVERY_ATTEMPTS_NO_DELETE_SHA256: [u8; 32] = [
   2232     0x8b, 0x6d, 0x86, 0x04, 0xe3, 0x6b, 0xf6, 0xb9, 0xa2, 0x21, 0x13, 0x39, 0xda, 0xd1, 0xf0, 0x9a,
   2233     0x6a, 0xf3, 0x31, 0xef, 0x46, 0xbc, 0xdd, 0xd1, 0xe0, 0xe3, 0xef, 0x35, 0x07, 0x40, 0x08, 0xf1,
   2234 ];
   2235 const DISCOVERY_DESIRED_STATE_TABLE_SHA256: [u8; 32] = [
   2236     0xad, 0x85, 0x4a, 0x61, 0x50, 0xa4, 0x0f, 0xf9, 0x99, 0xe7, 0x2e, 0xf8, 0xa7, 0x63, 0xa8, 0xc8,
   2237     0xcc, 0x57, 0x9d, 0x37, 0x23, 0xa2, 0x20, 0x67, 0x3c, 0xb1, 0xee, 0xbe, 0x9a, 0xda, 0xec, 0xce,
   2238 ];
   2239 const DISCOVERY_DOCUMENTS_TABLE_SHA256: [u8; 32] = [
   2240     0x0b, 0x44, 0x57, 0x52, 0xbd, 0xdc, 0x28, 0x9c, 0x90, 0x96, 0x42, 0x80, 0x00, 0x8e, 0x00, 0x2a,
   2241     0x96, 0x81, 0x1a, 0x2a, 0x67, 0x96, 0x9c, 0x6c, 0x55, 0x44, 0x1b, 0xa2, 0xff, 0x0e, 0x01, 0x28,
   2242 ];
   2243 const DISCOVERY_PUBLICATION_STATE_TABLE_SHA256: [u8; 32] = [
   2244     0xc1, 0x61, 0x4f, 0xc6, 0x3e, 0x56, 0xae, 0xcd, 0xcf, 0x81, 0xe5, 0xea, 0x45, 0x93, 0x16, 0xc1,
   2245     0x44, 0x71, 0x97, 0x11, 0xda, 0x97, 0x9c, 0xd5, 0xe4, 0x2a, 0x62, 0x54, 0x01, 0x24, 0xa1, 0x62,
   2246 ];
   2247 const DISCOVERY_DESIRED_STATE_NO_UPDATE_SHA256: [u8; 32] = [
   2248     0x5a, 0x4e, 0x12, 0x67, 0x2a, 0xb5, 0x75, 0xb7, 0x91, 0x35, 0xb0, 0xd2, 0x87, 0xcb, 0x33, 0x83,
   2249     0x89, 0x8a, 0x51, 0x32, 0xf2, 0x34, 0xc1, 0x20, 0xd4, 0x5a, 0x56, 0x10, 0x6d, 0xe6, 0x92, 0x4c,
   2250 ];
   2251 const DISCOVERY_DESIRED_STATE_NO_DELETE_SHA256: [u8; 32] = [
   2252     0x5e, 0x1e, 0xcc, 0x9f, 0x37, 0x97, 0x38, 0xdf, 0x66, 0x0f, 0x89, 0xb2, 0xb6, 0x5d, 0x85, 0xd4,
   2253     0xd2, 0x2c, 0xa1, 0x47, 0x7f, 0x20, 0x2e, 0x9b, 0xcb, 0x52, 0xb8, 0x95, 0x55, 0x8f, 0xeb, 0xf0,
   2254 ];
   2255 const DISCOVERY_DOCUMENTS_NO_UPDATE_SHA256: [u8; 32] = [
   2256     0x80, 0xf0, 0x11, 0x68, 0xe6, 0x3e, 0x94, 0xd1, 0xa6, 0xcd, 0x63, 0xf6, 0x16, 0xed, 0xdf, 0x05,
   2257     0x7d, 0x58, 0xb4, 0x77, 0x8b, 0x83, 0xac, 0xc6, 0x07, 0xd3, 0x98, 0x11, 0xbf, 0x0d, 0x83, 0xf7,
   2258 ];
   2259 const DISCOVERY_DOCUMENTS_NO_DELETE_SHA256: [u8; 32] = [
   2260     0x23, 0xd4, 0x66, 0xe2, 0x21, 0xd3, 0x7a, 0xa1, 0xe0, 0xb7, 0xa6, 0x4e, 0x01, 0x5b, 0x1c, 0xf0,
   2261     0xd5, 0x8d, 0xad, 0x1c, 0x31, 0x5b, 0x1a, 0x9e, 0x88, 0x17, 0x5c, 0x6b, 0x59, 0xd4, 0x47, 0xec,
   2262 ];
   2263 const DISCOVERY_PUBLICATION_STATE_GUARD_UPDATE_SHA256: [u8; 32] = [
   2264     0xfc, 0xe8, 0x4a, 0xa7, 0x55, 0x00, 0x1c, 0x00, 0x12, 0x99, 0xc7, 0x58, 0xa1, 0xc6, 0x6a, 0x70,
   2265     0x99, 0xba, 0x07, 0x77, 0xc7, 0x8e, 0xce, 0x5a, 0xeb, 0xa7, 0xf8, 0x5a, 0x27, 0x52, 0xb7, 0x5f,
   2266 ];
   2267 const DISCOVERY_PUBLICATION_STATE_NO_DELETE_SHA256: [u8; 32] = [
   2268     0xcd, 0x1b, 0xb2, 0x56, 0x6e, 0x3e, 0x46, 0x14, 0x4a, 0x4d, 0x38, 0xf1, 0xcb, 0xf9, 0xa0, 0xc4,
   2269     0xb8, 0x94, 0xb8, 0x96, 0x71, 0x75, 0x49, 0x9c, 0x12, 0xb0, 0x15, 0x1d, 0xa0, 0x06, 0x1c, 0xa0,
   2270 ];
   2271 const NIP46_OPERATION_COMMITS_TABLE_SHA256: [u8; 32] = [
   2272     0x5f, 0x56, 0x46, 0xcf, 0xef, 0xee, 0x82, 0x58, 0xe6, 0xa7, 0x27, 0x53, 0x32, 0xbd, 0xb9, 0x92,
   2273     0xaf, 0xc5, 0x3c, 0x0c, 0xaf, 0x10, 0x87, 0xe5, 0x25, 0x1e, 0x89, 0x8c, 0x4c, 0xd6, 0xc5, 0x4d,
   2274 ];
   2275 const NIP46_OPERATION_COMMITS_NO_UPDATE_SHA256: [u8; 32] = [
   2276     0x52, 0xa9, 0x7d, 0x6c, 0xbd, 0x06, 0x9e, 0xe1, 0x19, 0x00, 0x98, 0xdd, 0x36, 0x6b, 0x38, 0xd7,
   2277     0xff, 0xa5, 0x9d, 0x04, 0x7b, 0x6b, 0xa9, 0x79, 0x54, 0xb7, 0x7f, 0x5c, 0x13, 0x97, 0x13, 0xd3,
   2278 ];
   2279 const NIP46_OPERATION_COMMITS_NO_DELETE_SHA256: [u8; 32] = [
   2280     0x99, 0x67, 0xd8, 0x61, 0xd2, 0xa7, 0x1e, 0x1a, 0x74, 0x3f, 0xb5, 0xe9, 0x7b, 0x96, 0xe0, 0x00,
   2281     0xa9, 0xaa, 0x38, 0xe4, 0xb6, 0x76, 0x47, 0xa0, 0x87, 0x0b, 0x48, 0x9b, 0x55, 0x20, 0xa9, 0xa3,
   2282 ];
   2283 const NIP46_SIGNED_RESPONSES_TABLE_SHA256: [u8; 32] = [
   2284     0x12, 0xf2, 0x9a, 0x4b, 0x24, 0x62, 0x5a, 0xf4, 0xcb, 0x0e, 0xa1, 0x16, 0x9d, 0x64, 0x9c, 0x1f,
   2285     0xe6, 0x4a, 0xe7, 0x10, 0x14, 0x52, 0xbc, 0x43, 0x9c, 0xdd, 0x86, 0x23, 0x47, 0x60, 0x96, 0x19,
   2286 ];
   2287 const NIP46_SIGNED_RESPONSES_NO_UPDATE_SHA256: [u8; 32] = [
   2288     0xee, 0xd8, 0xb0, 0x82, 0xc7, 0x46, 0x37, 0x53, 0x5a, 0x77, 0x77, 0x95, 0xb5, 0x29, 0x58, 0x41,
   2289     0x5a, 0x3f, 0xab, 0xc3, 0xa6, 0x7a, 0xcf, 0x44, 0xef, 0xe0, 0xc6, 0x82, 0xeb, 0xcb, 0x2d, 0x05,
   2290 ];
   2291 const NIP46_SIGNED_RESPONSES_NO_DELETE_SHA256: [u8; 32] = [
   2292     0x8e, 0x6a, 0x36, 0xe5, 0x89, 0x50, 0x81, 0x90, 0x5f, 0x1c, 0x32, 0x19, 0x25, 0xec, 0x37, 0x07,
   2293     0x1f, 0x42, 0xd9, 0x1a, 0x73, 0xd3, 0x89, 0x56, 0x3d, 0x2b, 0x4b, 0x3e, 0x9d, 0x3a, 0xf3, 0xa4,
   2294 ];
   2295 
   2296 /// Stable classes for invalid embedded Myc catalog definitions.
   2297 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
   2298 pub enum MycStateCatalogErrorKind {
   2299     MigrationCatalog,
   2300     SchemaCatalog,
   2301     CatalogMismatch,
   2302 }
   2303 
   2304 impl MycStateCatalogErrorKind {
   2305     /// Returns the stable machine-readable classification.
   2306     #[must_use]
   2307     pub const fn code(self) -> &'static str {
   2308         match self {
   2309             Self::MigrationCatalog => "migration_catalog_invalid",
   2310             Self::SchemaCatalog => "schema_catalog_invalid",
   2311             Self::CatalogMismatch => "state_catalog_mismatch",
   2312         }
   2313     }
   2314 }
   2315 
   2316 /// Source-free failure to construct or validate the embedded Myc catalogs.
   2317 #[derive(Clone, Copy, PartialEq, Eq)]
   2318 pub struct MycStateCatalogError {
   2319     kind: MycStateCatalogErrorKind,
   2320 }
   2321 
   2322 impl MycStateCatalogError {
   2323     const fn new(kind: MycStateCatalogErrorKind) -> Self {
   2324         Self { kind }
   2325     }
   2326 
   2327     /// Returns the stable failure class.
   2328     #[must_use]
   2329     pub const fn kind(self) -> MycStateCatalogErrorKind {
   2330         self.kind
   2331     }
   2332 
   2333     /// Returns the stable machine-readable failure code.
   2334     #[must_use]
   2335     pub const fn code(self) -> &'static str {
   2336         self.kind.code()
   2337     }
   2338 }
   2339 
   2340 impl fmt::Display for MycStateCatalogError {
   2341     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
   2342         formatter.write_str(match self.kind {
   2343             MycStateCatalogErrorKind::MigrationCatalog => {
   2344                 "Myc migration catalog definition is invalid"
   2345             }
   2346             MycStateCatalogErrorKind::SchemaCatalog => "Myc schema catalog definition is invalid",
   2347             MycStateCatalogErrorKind::CatalogMismatch => {
   2348                 "Myc state catalogs do not match the governed identity"
   2349             }
   2350         })
   2351     }
   2352 }
   2353 
   2354 impl fmt::Debug for MycStateCatalogError {
   2355     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
   2356         formatter
   2357             .debug_struct("MycStateCatalogError")
   2358             .field("kind", &self.kind)
   2359             .finish()
   2360     }
   2361 }
   2362 
   2363 impl Error for MycStateCatalogError {}
   2364 
   2365 /// Constructs the exact ordered Myc migration catalog.
   2366 pub fn myc_migration_catalog() -> Result<MigrationCatalog, MycStateCatalogError> {
   2367     let metadata = MigrationDescriptor::sql(
   2368         2,
   2369         "create_myc_state_metadata",
   2370         CREATE_MYC_STATE_METADATA_MIGRATION_SQL,
   2371         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_2_MIGRATION_SHA256),
   2372     )
   2373     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2374     let requests = MigrationDescriptor::sql(
   2375         3,
   2376         "create_nip46_request_admission",
   2377         CREATE_NIP46_REQUEST_ADMISSION_MIGRATION_SQL,
   2378         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_3_MIGRATION_SHA256),
   2379     )
   2380     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2381     let connections = MigrationDescriptor::sql(
   2382         4,
   2383         "create_connection_authorization_state",
   2384         CREATE_CONNECTION_STATE_MIGRATION_SQL,
   2385         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_4_MIGRATION_SHA256),
   2386     )
   2387     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2388     let governance = MigrationDescriptor::sql(
   2389         5,
   2390         "create_bounded_governance_state",
   2391         CREATE_GOVERNANCE_STATE_MIGRATION_SQL,
   2392         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_5_MIGRATION_SHA256),
   2393     )
   2394     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2395     let delivery = MigrationDescriptor::sql(
   2396         6,
   2397         "create_delivery_evidence_state",
   2398         CREATE_DELIVERY_STATE_MIGRATION_SQL,
   2399         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_6_MIGRATION_SHA256),
   2400     )
   2401     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2402     let discovery = MigrationDescriptor::sql(
   2403         7,
   2404         "create_discovery_desired_state",
   2405         CREATE_DISCOVERY_STATE_MIGRATION_SQL,
   2406         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_7_MIGRATION_SHA256),
   2407     )
   2408     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2409     let completion = MigrationDescriptor::sql(
   2410         8,
   2411         "create_nip46_operation_completion",
   2412         CREATE_NIP46_OPERATION_COMPLETION_MIGRATION_SQL,
   2413         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_8_MIGRATION_SHA256),
   2414     )
   2415     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2416     let response = MigrationDescriptor::sql(
   2417         9,
   2418         "create_nip46_atomic_response",
   2419         CREATE_NIP46_ATOMIC_RESPONSE_MIGRATION_SQL,
   2420         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_9_MIGRATION_SHA256),
   2421     )
   2422     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2423     let configuration = MigrationDescriptor::sql(
   2424         10,
   2425         "create_configuration_binding_history",
   2426         CREATE_MYC_CONFIG_BINDINGS_MIGRATION_SQL,
   2427         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_10_MIGRATION_SHA256),
   2428     )
   2429     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2430     let admin_operations = MigrationDescriptor::sql(
   2431         11,
   2432         "create_admin_operation_journal",
   2433         CREATE_MYC_ADMIN_OPERATIONS_MIGRATION_SQL,
   2434         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_11_MIGRATION_SHA256),
   2435     )
   2436     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2437     let pending_responses = MigrationDescriptor::sql(
   2438         12,
   2439         "create_nip46_pending_response_authority",
   2440         CREATE_NIP46_PENDING_RESPONSE_MIGRATION_SQL,
   2441         MigrationChecksum::from_bytes(MYC_STATE_SCHEMA_VERSION_12_MIGRATION_SHA256),
   2442     )
   2443     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2444     let catalog = MigrationCatalog::new([
   2445         metadata,
   2446         requests,
   2447         connections,
   2448         governance,
   2449         delivery,
   2450         discovery,
   2451         completion,
   2452         response,
   2453         configuration,
   2454         admin_operations,
   2455         pending_responses,
   2456     ])
   2457     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::MigrationCatalog))?;
   2458     if catalog.current_version() != MYC_STATE_SCHEMA_VERSION
   2459         || catalog.descriptors().len() != 11
   2460         || catalog.digest().as_bytes() != &MYC_MIGRATION_CATALOG_SHA256
   2461     {
   2462         return Err(MycStateCatalogError::new(
   2463             MycStateCatalogErrorKind::CatalogMismatch,
   2464         ));
   2465     }
   2466     Ok(catalog)
   2467 }
   2468 
   2469 /// Constructs the exact Myc schema catalog bound to the migration catalog.
   2470 pub fn myc_schema_catalog() -> Result<SchemaCatalog, MycStateCatalogError> {
   2471     let migrations = myc_migration_catalog()?;
   2472     let version_one = SchemaVersionCatalog::new(
   2473         MYC_STATE_BASE_SCHEMA_VERSION,
   2474         [],
   2475         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_1_SHA256),
   2476     )
   2477     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2478     let version_two = SchemaVersionCatalog::new(
   2479         2,
   2480         myc_state_metadata_objects()?,
   2481         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_2_SHA256),
   2482     )
   2483     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2484     let version_three = SchemaVersionCatalog::new(
   2485         3,
   2486         myc_state_request_objects()?,
   2487         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_3_SHA256),
   2488     )
   2489     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2490     let version_four = SchemaVersionCatalog::new(
   2491         4,
   2492         myc_state_connection_objects()?,
   2493         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_4_SHA256),
   2494     )
   2495     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2496     let version_five = SchemaVersionCatalog::new(
   2497         5,
   2498         myc_state_governance_objects()?,
   2499         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_5_SHA256),
   2500     )
   2501     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2502     let version_six = SchemaVersionCatalog::new(
   2503         6,
   2504         myc_state_delivery_objects()?,
   2505         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_6_SHA256),
   2506     )
   2507     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2508     let version_seven = SchemaVersionCatalog::new(
   2509         7,
   2510         myc_state_discovery_objects()?,
   2511         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_7_SHA256),
   2512     )
   2513     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2514     let version_eight = SchemaVersionCatalog::new(
   2515         8,
   2516         myc_state_completion_objects()?,
   2517         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_8_SHA256),
   2518     )
   2519     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2520     let version_nine = SchemaVersionCatalog::new(
   2521         9,
   2522         myc_state_response_objects()?,
   2523         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_9_SHA256),
   2524     )
   2525     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2526     let version_ten = SchemaVersionCatalog::new(
   2527         10,
   2528         myc_state_config_binding_objects()?,
   2529         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_10_SHA256),
   2530     )
   2531     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2532     let version_eleven = SchemaVersionCatalog::new(
   2533         11,
   2534         myc_state_admin_operation_objects()?,
   2535         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_11_SHA256),
   2536     )
   2537     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2538     let version_twelve = SchemaVersionCatalog::new(
   2539         12,
   2540         myc_state_pending_response_objects()?,
   2541         SchemaDigest::from_bytes(MYC_STATE_SCHEMA_VERSION_12_SHA256),
   2542     )
   2543     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2544     let catalog = SchemaCatalog::new(
   2545         &migrations,
   2546         [
   2547             version_one,
   2548             version_two,
   2549             version_three,
   2550             version_four,
   2551             version_five,
   2552             version_six,
   2553             version_seven,
   2554             version_eight,
   2555             version_nine,
   2556             version_ten,
   2557             version_eleven,
   2558             version_twelve,
   2559         ],
   2560     )
   2561     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2562     validate_myc_state_catalogs(&migrations, &catalog)?;
   2563     Ok(catalog)
   2564 }
   2565 
   2566 fn myc_state_metadata_objects() -> Result<[SchemaObject; 3], MycStateCatalogError> {
   2567     let table = SchemaObject::new(
   2568         SchemaObjectKind::Table,
   2569         "myc_state_metadata",
   2570         "myc_state_metadata",
   2571         CREATE_MYC_STATE_METADATA_TABLE_SQL,
   2572         SchemaDigest::from_bytes(MYC_STATE_METADATA_TABLE_SHA256),
   2573     )
   2574     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2575     let update = SchemaObject::new(
   2576         SchemaObjectKind::Trigger,
   2577         "myc_state_metadata_no_update",
   2578         "myc_state_metadata",
   2579         CREATE_MYC_STATE_METADATA_NO_UPDATE_SQL,
   2580         SchemaDigest::from_bytes(MYC_STATE_METADATA_NO_UPDATE_SHA256),
   2581     )
   2582     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2583     let delete = SchemaObject::new(
   2584         SchemaObjectKind::Trigger,
   2585         "myc_state_metadata_no_delete",
   2586         "myc_state_metadata",
   2587         CREATE_MYC_STATE_METADATA_NO_DELETE_SQL,
   2588         SchemaDigest::from_bytes(MYC_STATE_METADATA_NO_DELETE_SHA256),
   2589     )
   2590     .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?;
   2591     Ok([table, update, delete])
   2592 }
   2593 
   2594 fn myc_state_request_objects() -> Result<[SchemaObject; 7], MycStateCatalogError> {
   2595     let [metadata_table, metadata_update, metadata_delete] = myc_state_metadata_objects()?;
   2596     Ok([
   2597         metadata_table,
   2598         metadata_update,
   2599         metadata_delete,
   2600         SchemaObject::new(
   2601             SchemaObjectKind::Table,
   2602             "nip46_requests",
   2603             "nip46_requests",
   2604             CREATE_NIP46_REQUESTS_TABLE_SQL,
   2605             SchemaDigest::from_bytes(NIP46_REQUESTS_TABLE_SHA256),
   2606         )
   2607         .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?,
   2608         SchemaObject::new(
   2609             SchemaObjectKind::Table,
   2610             "nip46_request_dedup",
   2611             "nip46_request_dedup",
   2612             CREATE_NIP46_REQUEST_DEDUP_TABLE_SQL,
   2613             SchemaDigest::from_bytes(NIP46_REQUEST_DEDUP_TABLE_SHA256),
   2614         )
   2615         .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?,
   2616         SchemaObject::new(
   2617             SchemaObjectKind::Trigger,
   2618             "nip46_requests_no_update",
   2619             "nip46_requests",
   2620             CREATE_NIP46_REQUESTS_NO_UPDATE_SQL,
   2621             SchemaDigest::from_bytes(NIP46_REQUESTS_NO_UPDATE_SHA256),
   2622         )
   2623         .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?,
   2624         SchemaObject::new(
   2625             SchemaObjectKind::Trigger,
   2626             "nip46_request_dedup_guard_update",
   2627             "nip46_request_dedup",
   2628             CREATE_NIP46_REQUEST_DEDUP_GUARD_UPDATE_SQL,
   2629             SchemaDigest::from_bytes(NIP46_REQUEST_DEDUP_GUARD_UPDATE_SHA256),
   2630         )
   2631         .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))?,
   2632     ])
   2633 }
   2634 
   2635 fn myc_state_connection_objects() -> Result<[SchemaObject; 19], MycStateCatalogError> {
   2636     let [
   2637         metadata_table,
   2638         metadata_update,
   2639         metadata_delete,
   2640         request_table,
   2641         request_dedup,
   2642         request_update,
   2643         request_dedup_update,
   2644     ] = myc_state_request_objects()?;
   2645     let object = |kind, name, table, sql, digest| {
   2646         SchemaObject::new(kind, name, table, sql, SchemaDigest::from_bytes(digest))
   2647             .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   2648     };
   2649     Ok([
   2650         metadata_table,
   2651         metadata_update,
   2652         metadata_delete,
   2653         request_table,
   2654         request_dedup,
   2655         request_update,
   2656         request_dedup_update,
   2657         object(
   2658             SchemaObjectKind::Table,
   2659             "connections",
   2660             "connections",
   2661             CREATE_CONNECTIONS_TABLE_SQL,
   2662             CONNECTIONS_TABLE_SHA256,
   2663         )?,
   2664         object(
   2665             SchemaObjectKind::Table,
   2666             "connection_permissions",
   2667             "connection_permissions",
   2668             CREATE_CONNECTION_PERMISSIONS_TABLE_SQL,
   2669             CONNECTION_PERMISSIONS_TABLE_SHA256,
   2670         )?,
   2671         object(
   2672             SchemaObjectKind::Table,
   2673             "nip46_request_decisions",
   2674             "nip46_request_decisions",
   2675             CREATE_NIP46_REQUEST_DECISIONS_TABLE_SQL,
   2676             NIP46_REQUEST_DECISIONS_TABLE_SHA256,
   2677         )?,
   2678         object(
   2679             SchemaObjectKind::Table,
   2680             "connection_auth_challenges",
   2681             "connection_auth_challenges",
   2682             CREATE_CONNECTION_AUTH_CHALLENGES_TABLE_SQL,
   2683             CONNECTION_AUTH_CHALLENGES_TABLE_SHA256,
   2684         )?,
   2685         object(
   2686             SchemaObjectKind::Trigger,
   2687             "connections_guard_update",
   2688             "connections",
   2689             CREATE_CONNECTIONS_GUARD_UPDATE_SQL,
   2690             CONNECTIONS_GUARD_UPDATE_SHA256,
   2691         )?,
   2692         object(
   2693             SchemaObjectKind::Trigger,
   2694             "connections_no_delete",
   2695             "connections",
   2696             CREATE_CONNECTIONS_NO_DELETE_SQL,
   2697             CONNECTIONS_NO_DELETE_SHA256,
   2698         )?,
   2699         object(
   2700             SchemaObjectKind::Trigger,
   2701             "connection_permissions_no_update",
   2702             "connection_permissions",
   2703             CREATE_CONNECTION_PERMISSIONS_NO_UPDATE_SQL,
   2704             CONNECTION_PERMISSIONS_NO_UPDATE_SHA256,
   2705         )?,
   2706         object(
   2707             SchemaObjectKind::Trigger,
   2708             "connection_permissions_no_delete",
   2709             "connection_permissions",
   2710             CREATE_CONNECTION_PERMISSIONS_NO_DELETE_SQL,
   2711             CONNECTION_PERMISSIONS_NO_DELETE_SHA256,
   2712         )?,
   2713         object(
   2714             SchemaObjectKind::Trigger,
   2715             "nip46_request_decisions_guard_update",
   2716             "nip46_request_decisions",
   2717             CREATE_NIP46_REQUEST_DECISIONS_GUARD_UPDATE_SQL,
   2718             NIP46_REQUEST_DECISIONS_GUARD_UPDATE_SHA256,
   2719         )?,
   2720         object(
   2721             SchemaObjectKind::Trigger,
   2722             "nip46_request_decisions_no_delete",
   2723             "nip46_request_decisions",
   2724             CREATE_NIP46_REQUEST_DECISIONS_NO_DELETE_SQL,
   2725             NIP46_REQUEST_DECISIONS_NO_DELETE_SHA256,
   2726         )?,
   2727         object(
   2728             SchemaObjectKind::Trigger,
   2729             "connection_auth_challenges_guard_update",
   2730             "connection_auth_challenges",
   2731             CREATE_CONNECTION_AUTH_CHALLENGES_GUARD_UPDATE_SQL,
   2732             CONNECTION_AUTH_CHALLENGES_GUARD_UPDATE_SHA256,
   2733         )?,
   2734         object(
   2735             SchemaObjectKind::Trigger,
   2736             "connection_auth_challenges_no_delete",
   2737             "connection_auth_challenges",
   2738             CREATE_CONNECTION_AUTH_CHALLENGES_NO_DELETE_SQL,
   2739             CONNECTION_AUTH_CHALLENGES_NO_DELETE_SHA256,
   2740         )?,
   2741     ])
   2742 }
   2743 
   2744 fn myc_state_governance_objects() -> Result<Vec<SchemaObject>, MycStateCatalogError> {
   2745     let mut objects = Vec::from(myc_state_connection_objects()?);
   2746     let object = |kind, name, table, sql, digest| {
   2747         SchemaObject::new(kind, name, table, sql, SchemaDigest::from_bytes(digest))
   2748             .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   2749     };
   2750     objects.extend([
   2751         object(
   2752             SchemaObjectKind::Table,
   2753             "myc_audit_state",
   2754             "myc_audit_state",
   2755             CREATE_MYC_AUDIT_STATE_TABLE_SQL,
   2756             MYC_AUDIT_STATE_TABLE_SHA256,
   2757         )?,
   2758         object(
   2759             SchemaObjectKind::Table,
   2760             "operation_audit",
   2761             "operation_audit",
   2762             CREATE_OPERATION_AUDIT_TABLE_SQL,
   2763             OPERATION_AUDIT_TABLE_SHA256,
   2764         )?,
   2765         object(
   2766             SchemaObjectKind::Table,
   2767             "nip46_request_audit",
   2768             "nip46_request_audit",
   2769             CREATE_NIP46_REQUEST_AUDIT_TABLE_SQL,
   2770             NIP46_REQUEST_AUDIT_TABLE_SHA256,
   2771         )?,
   2772         object(
   2773             SchemaObjectKind::Table,
   2774             "connection_rate_windows",
   2775             "connection_rate_windows",
   2776             CREATE_CONNECTION_RATE_WINDOWS_TABLE_SQL,
   2777             CONNECTION_RATE_WINDOWS_TABLE_SHA256,
   2778         )?,
   2779         object(
   2780             SchemaObjectKind::Trigger,
   2781             "myc_audit_state_guard_update",
   2782             "myc_audit_state",
   2783             CREATE_MYC_AUDIT_STATE_GUARD_UPDATE_SQL,
   2784             MYC_AUDIT_STATE_GUARD_UPDATE_SHA256,
   2785         )?,
   2786         object(
   2787             SchemaObjectKind::Trigger,
   2788             "myc_audit_state_no_delete",
   2789             "myc_audit_state",
   2790             CREATE_MYC_AUDIT_STATE_NO_DELETE_SQL,
   2791             MYC_AUDIT_STATE_NO_DELETE_SHA256,
   2792         )?,
   2793         object(
   2794             SchemaObjectKind::Trigger,
   2795             "operation_audit_no_update",
   2796             "operation_audit",
   2797             CREATE_OPERATION_AUDIT_NO_UPDATE_SQL,
   2798             OPERATION_AUDIT_NO_UPDATE_SHA256,
   2799         )?,
   2800         object(
   2801             SchemaObjectKind::Trigger,
   2802             "nip46_request_audit_no_update",
   2803             "nip46_request_audit",
   2804             CREATE_NIP46_REQUEST_AUDIT_NO_UPDATE_SQL,
   2805             NIP46_REQUEST_AUDIT_NO_UPDATE_SHA256,
   2806         )?,
   2807         object(
   2808             SchemaObjectKind::Trigger,
   2809             "connection_rate_windows_guard_update",
   2810             "connection_rate_windows",
   2811             CREATE_CONNECTION_RATE_WINDOWS_GUARD_UPDATE_SQL,
   2812             CONNECTION_RATE_WINDOWS_GUARD_UPDATE_SHA256,
   2813         )?,
   2814     ]);
   2815     Ok(objects)
   2816 }
   2817 
   2818 fn myc_state_delivery_objects() -> Result<Vec<SchemaObject>, MycStateCatalogError> {
   2819     let mut objects = myc_state_governance_objects()?;
   2820     let object = |kind, name, table, sql, digest| {
   2821         SchemaObject::new(kind, name, table, sql, SchemaDigest::from_bytes(digest))
   2822             .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   2823     };
   2824     objects.extend([
   2825         object(
   2826             SchemaObjectKind::Table,
   2827             "publication_outbox",
   2828             "publication_outbox",
   2829             CREATE_PUBLICATION_OUTBOX_TABLE_SQL,
   2830             PUBLICATION_OUTBOX_TABLE_SHA256,
   2831         )?,
   2832         object(
   2833             SchemaObjectKind::Table,
   2834             "publication_targets",
   2835             "publication_targets",
   2836             CREATE_PUBLICATION_TARGETS_TABLE_SQL,
   2837             PUBLICATION_TARGETS_TABLE_SHA256,
   2838         )?,
   2839         object(
   2840             SchemaObjectKind::Table,
   2841             "publication_attempts",
   2842             "publication_attempts",
   2843             CREATE_PUBLICATION_ATTEMPTS_TABLE_SQL,
   2844             PUBLICATION_ATTEMPTS_TABLE_SHA256,
   2845         )?,
   2846         object(
   2847             SchemaObjectKind::Trigger,
   2848             "publication_outbox_guard_update",
   2849             "publication_outbox",
   2850             CREATE_PUBLICATION_OUTBOX_GUARD_UPDATE_SQL,
   2851             PUBLICATION_OUTBOX_GUARD_UPDATE_SHA256,
   2852         )?,
   2853         object(
   2854             SchemaObjectKind::Trigger,
   2855             "publication_targets_guard_update",
   2856             "publication_targets",
   2857             CREATE_PUBLICATION_TARGETS_GUARD_UPDATE_SQL,
   2858             PUBLICATION_TARGETS_GUARD_UPDATE_SHA256,
   2859         )?,
   2860         object(
   2861             SchemaObjectKind::Trigger,
   2862             "publication_attempts_guard_update",
   2863             "publication_attempts",
   2864             CREATE_PUBLICATION_ATTEMPTS_GUARD_UPDATE_SQL,
   2865             PUBLICATION_ATTEMPTS_GUARD_UPDATE_SHA256,
   2866         )?,
   2867         object(
   2868             SchemaObjectKind::Trigger,
   2869             "publication_outbox_no_delete",
   2870             "publication_outbox",
   2871             CREATE_PUBLICATION_OUTBOX_NO_DELETE_SQL,
   2872             PUBLICATION_OUTBOX_NO_DELETE_SHA256,
   2873         )?,
   2874         object(
   2875             SchemaObjectKind::Trigger,
   2876             "publication_targets_no_delete",
   2877             "publication_targets",
   2878             CREATE_PUBLICATION_TARGETS_NO_DELETE_SQL,
   2879             PUBLICATION_TARGETS_NO_DELETE_SHA256,
   2880         )?,
   2881         object(
   2882             SchemaObjectKind::Trigger,
   2883             "publication_attempts_no_delete",
   2884             "publication_attempts",
   2885             CREATE_PUBLICATION_ATTEMPTS_NO_DELETE_SQL,
   2886             PUBLICATION_ATTEMPTS_NO_DELETE_SHA256,
   2887         )?,
   2888     ]);
   2889     Ok(objects)
   2890 }
   2891 
   2892 fn myc_state_discovery_objects() -> Result<Vec<SchemaObject>, MycStateCatalogError> {
   2893     let mut objects = myc_state_delivery_objects()?;
   2894     objects.retain(|object| {
   2895         !matches!(
   2896             object.name(),
   2897             "publication_outbox"
   2898                 | "publication_targets"
   2899                 | "publication_attempts"
   2900                 | "publication_outbox_guard_update"
   2901                 | "publication_targets_guard_update"
   2902                 | "publication_attempts_guard_update"
   2903                 | "publication_outbox_no_delete"
   2904                 | "publication_targets_no_delete"
   2905                 | "publication_attempts_no_delete"
   2906         )
   2907     });
   2908     let object = |kind, name, table, sql, digest| {
   2909         SchemaObject::new(kind, name, table, sql, SchemaDigest::from_bytes(digest))
   2910             .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   2911     };
   2912     objects.extend([
   2913         object(
   2914             SchemaObjectKind::Table,
   2915             "delivery_jobs",
   2916             "delivery_jobs",
   2917             CREATE_DELIVERY_JOBS_TABLE_SQL,
   2918             DELIVERY_JOBS_TABLE_SHA256,
   2919         )?,
   2920         object(
   2921             SchemaObjectKind::Table,
   2922             "delivery_targets",
   2923             "delivery_targets",
   2924             CREATE_DELIVERY_TARGETS_TABLE_SQL,
   2925             DELIVERY_TARGETS_TABLE_SHA256,
   2926         )?,
   2927         object(
   2928             SchemaObjectKind::Table,
   2929             "delivery_attempts",
   2930             "delivery_attempts",
   2931             CREATE_DELIVERY_ATTEMPTS_TABLE_SQL,
   2932             DELIVERY_ATTEMPTS_TABLE_SHA256,
   2933         )?,
   2934         object(
   2935             SchemaObjectKind::Trigger,
   2936             "delivery_jobs_guard_update",
   2937             "delivery_jobs",
   2938             CREATE_DELIVERY_JOBS_GUARD_UPDATE_SQL,
   2939             DELIVERY_JOBS_GUARD_UPDATE_SHA256,
   2940         )?,
   2941         object(
   2942             SchemaObjectKind::Trigger,
   2943             "delivery_targets_guard_update",
   2944             "delivery_targets",
   2945             CREATE_DELIVERY_TARGETS_GUARD_UPDATE_SQL,
   2946             DELIVERY_TARGETS_GUARD_UPDATE_SHA256,
   2947         )?,
   2948         object(
   2949             SchemaObjectKind::Trigger,
   2950             "delivery_attempts_guard_update",
   2951             "delivery_attempts",
   2952             CREATE_DELIVERY_ATTEMPTS_GUARD_UPDATE_SQL,
   2953             DELIVERY_ATTEMPTS_GUARD_UPDATE_SHA256,
   2954         )?,
   2955         object(
   2956             SchemaObjectKind::Trigger,
   2957             "delivery_jobs_no_delete",
   2958             "delivery_jobs",
   2959             CREATE_DELIVERY_JOBS_NO_DELETE_SQL,
   2960             DELIVERY_JOBS_NO_DELETE_SHA256,
   2961         )?,
   2962         object(
   2963             SchemaObjectKind::Trigger,
   2964             "delivery_targets_no_delete",
   2965             "delivery_targets",
   2966             CREATE_DELIVERY_TARGETS_NO_DELETE_SQL,
   2967             DELIVERY_TARGETS_NO_DELETE_SHA256,
   2968         )?,
   2969         object(
   2970             SchemaObjectKind::Trigger,
   2971             "delivery_attempts_no_delete",
   2972             "delivery_attempts",
   2973             CREATE_DELIVERY_ATTEMPTS_NO_DELETE_SQL,
   2974             DELIVERY_ATTEMPTS_NO_DELETE_SHA256,
   2975         )?,
   2976         object(
   2977             SchemaObjectKind::Table,
   2978             "discovery_desired_state",
   2979             "discovery_desired_state",
   2980             CREATE_DISCOVERY_DESIRED_STATE_TABLE_SQL,
   2981             DISCOVERY_DESIRED_STATE_TABLE_SHA256,
   2982         )?,
   2983         object(
   2984             SchemaObjectKind::Table,
   2985             "discovery_documents",
   2986             "discovery_documents",
   2987             CREATE_DISCOVERY_DOCUMENTS_TABLE_SQL,
   2988             DISCOVERY_DOCUMENTS_TABLE_SHA256,
   2989         )?,
   2990         object(
   2991             SchemaObjectKind::Table,
   2992             "discovery_publication_state",
   2993             "discovery_publication_state",
   2994             CREATE_DISCOVERY_PUBLICATION_STATE_TABLE_SQL,
   2995             DISCOVERY_PUBLICATION_STATE_TABLE_SHA256,
   2996         )?,
   2997         object(
   2998             SchemaObjectKind::Trigger,
   2999             "delivery_jobs_guard_insert",
   3000             "delivery_jobs",
   3001             CREATE_DELIVERY_JOBS_GUARD_INSERT_SQL,
   3002             DELIVERY_JOBS_GUARD_INSERT_SHA256,
   3003         )?,
   3004         object(
   3005             SchemaObjectKind::Trigger,
   3006             "discovery_desired_state_no_update",
   3007             "discovery_desired_state",
   3008             CREATE_DISCOVERY_DESIRED_STATE_NO_UPDATE_SQL,
   3009             DISCOVERY_DESIRED_STATE_NO_UPDATE_SHA256,
   3010         )?,
   3011         object(
   3012             SchemaObjectKind::Trigger,
   3013             "discovery_desired_state_no_delete",
   3014             "discovery_desired_state",
   3015             CREATE_DISCOVERY_DESIRED_STATE_NO_DELETE_SQL,
   3016             DISCOVERY_DESIRED_STATE_NO_DELETE_SHA256,
   3017         )?,
   3018         object(
   3019             SchemaObjectKind::Trigger,
   3020             "discovery_documents_no_update",
   3021             "discovery_documents",
   3022             CREATE_DISCOVERY_DOCUMENTS_NO_UPDATE_SQL,
   3023             DISCOVERY_DOCUMENTS_NO_UPDATE_SHA256,
   3024         )?,
   3025         object(
   3026             SchemaObjectKind::Trigger,
   3027             "discovery_documents_no_delete",
   3028             "discovery_documents",
   3029             CREATE_DISCOVERY_DOCUMENTS_NO_DELETE_SQL,
   3030             DISCOVERY_DOCUMENTS_NO_DELETE_SHA256,
   3031         )?,
   3032         object(
   3033             SchemaObjectKind::Trigger,
   3034             "discovery_publication_state_guard_update",
   3035             "discovery_publication_state",
   3036             CREATE_DISCOVERY_PUBLICATION_STATE_GUARD_UPDATE_SQL,
   3037             DISCOVERY_PUBLICATION_STATE_GUARD_UPDATE_SHA256,
   3038         )?,
   3039         object(
   3040             SchemaObjectKind::Trigger,
   3041             "discovery_publication_state_no_delete",
   3042             "discovery_publication_state",
   3043             CREATE_DISCOVERY_PUBLICATION_STATE_NO_DELETE_SQL,
   3044             DISCOVERY_PUBLICATION_STATE_NO_DELETE_SHA256,
   3045         )?,
   3046     ]);
   3047     Ok(objects)
   3048 }
   3049 
   3050 fn myc_state_completion_objects() -> Result<Vec<SchemaObject>, MycStateCatalogError> {
   3051     let mut objects = myc_state_discovery_objects()?;
   3052     let object = |kind, name, table, sql, digest| {
   3053         SchemaObject::new(kind, name, table, sql, SchemaDigest::from_bytes(digest))
   3054             .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   3055     };
   3056     objects.extend([
   3057         object(
   3058             SchemaObjectKind::Table,
   3059             "nip46_operation_commits",
   3060             "nip46_operation_commits",
   3061             CREATE_NIP46_OPERATION_COMMITS_TABLE_SQL,
   3062             NIP46_OPERATION_COMMITS_TABLE_SHA256,
   3063         )?,
   3064         object(
   3065             SchemaObjectKind::Trigger,
   3066             "nip46_operation_commits_no_update",
   3067             "nip46_operation_commits",
   3068             CREATE_NIP46_OPERATION_COMMITS_NO_UPDATE_SQL,
   3069             NIP46_OPERATION_COMMITS_NO_UPDATE_SHA256,
   3070         )?,
   3071         object(
   3072             SchemaObjectKind::Trigger,
   3073             "nip46_operation_commits_no_delete",
   3074             "nip46_operation_commits",
   3075             CREATE_NIP46_OPERATION_COMMITS_NO_DELETE_SQL,
   3076             NIP46_OPERATION_COMMITS_NO_DELETE_SHA256,
   3077         )?,
   3078     ]);
   3079     Ok(objects)
   3080 }
   3081 
   3082 fn myc_state_response_objects() -> Result<Vec<SchemaObject>, MycStateCatalogError> {
   3083     let mut objects = myc_state_completion_objects()?;
   3084     let object = |kind, name, table, sql, digest| {
   3085         SchemaObject::new(kind, name, table, sql, SchemaDigest::from_bytes(digest))
   3086             .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   3087     };
   3088     objects.extend([
   3089         object(
   3090             SchemaObjectKind::Table,
   3091             "nip46_signed_responses",
   3092             "nip46_signed_responses",
   3093             CREATE_NIP46_SIGNED_RESPONSES_TABLE_SQL,
   3094             NIP46_SIGNED_RESPONSES_TABLE_SHA256,
   3095         )?,
   3096         object(
   3097             SchemaObjectKind::Trigger,
   3098             "nip46_signed_responses_no_update",
   3099             "nip46_signed_responses",
   3100             CREATE_NIP46_SIGNED_RESPONSES_NO_UPDATE_SQL,
   3101             NIP46_SIGNED_RESPONSES_NO_UPDATE_SHA256,
   3102         )?,
   3103         object(
   3104             SchemaObjectKind::Trigger,
   3105             "nip46_signed_responses_no_delete",
   3106             "nip46_signed_responses",
   3107             CREATE_NIP46_SIGNED_RESPONSES_NO_DELETE_SQL,
   3108             NIP46_SIGNED_RESPONSES_NO_DELETE_SHA256,
   3109         )?,
   3110     ]);
   3111     Ok(objects)
   3112 }
   3113 
   3114 fn myc_state_config_binding_objects() -> Result<Vec<SchemaObject>, MycStateCatalogError> {
   3115     let mut objects = myc_state_response_objects()?;
   3116     let object = |kind, name, sql, digest| {
   3117         SchemaObject::new(
   3118             kind,
   3119             name,
   3120             "myc_config_bindings",
   3121             sql,
   3122             SchemaDigest::from_bytes(digest),
   3123         )
   3124         .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   3125     };
   3126     objects.extend([
   3127         object(
   3128             SchemaObjectKind::Table,
   3129             "myc_config_bindings",
   3130             CREATE_MYC_CONFIG_BINDINGS_TABLE_SQL,
   3131             MYC_CONFIG_BINDINGS_TABLE_SHA256,
   3132         )?,
   3133         object(
   3134             SchemaObjectKind::Trigger,
   3135             "myc_config_bindings_guard_insert",
   3136             CREATE_MYC_CONFIG_BINDINGS_GUARD_INSERT_SQL,
   3137             MYC_CONFIG_BINDINGS_GUARD_INSERT_SHA256,
   3138         )?,
   3139         object(
   3140             SchemaObjectKind::Trigger,
   3141             "myc_config_bindings_no_update",
   3142             CREATE_MYC_CONFIG_BINDINGS_NO_UPDATE_SQL,
   3143             MYC_CONFIG_BINDINGS_NO_UPDATE_SHA256,
   3144         )?,
   3145         object(
   3146             SchemaObjectKind::Trigger,
   3147             "myc_config_bindings_no_delete",
   3148             CREATE_MYC_CONFIG_BINDINGS_NO_DELETE_SQL,
   3149             MYC_CONFIG_BINDINGS_NO_DELETE_SHA256,
   3150         )?,
   3151     ]);
   3152     Ok(objects)
   3153 }
   3154 
   3155 fn myc_state_admin_operation_objects() -> Result<Vec<SchemaObject>, MycStateCatalogError> {
   3156     let mut objects = myc_state_config_binding_objects()?;
   3157     let object = |kind, name, sql, digest| {
   3158         SchemaObject::new(
   3159             kind,
   3160             name,
   3161             "myc_admin_operations",
   3162             sql,
   3163             SchemaDigest::from_bytes(digest),
   3164         )
   3165         .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   3166     };
   3167     objects.extend([
   3168         object(
   3169             SchemaObjectKind::Table,
   3170             "myc_admin_operations",
   3171             CREATE_MYC_ADMIN_OPERATIONS_TABLE_SQL,
   3172             MYC_ADMIN_OPERATIONS_TABLE_SHA256,
   3173         )?,
   3174         object(
   3175             SchemaObjectKind::Trigger,
   3176             "myc_admin_operations_guard_update",
   3177             CREATE_MYC_ADMIN_OPERATIONS_GUARD_UPDATE_SQL,
   3178             MYC_ADMIN_OPERATIONS_GUARD_UPDATE_SHA256,
   3179         )?,
   3180     ]);
   3181     Ok(objects)
   3182 }
   3183 
   3184 fn myc_state_pending_response_objects() -> Result<Vec<SchemaObject>, MycStateCatalogError> {
   3185     let mut objects = myc_state_admin_operation_objects()?;
   3186     let object = |kind, name, table, sql, digest| {
   3187         SchemaObject::new(kind, name, table, sql, SchemaDigest::from_bytes(digest))
   3188             .map_err(|_| MycStateCatalogError::new(MycStateCatalogErrorKind::SchemaCatalog))
   3189     };
   3190     objects.extend([
   3191         object(
   3192             SchemaObjectKind::Table,
   3193             "nip46_pending_responses",
   3194             "nip46_pending_responses",
   3195             CREATE_NIP46_PENDING_RESPONSES_TABLE_SQL,
   3196             NIP46_PENDING_RESPONSES_TABLE_SHA256,
   3197         )?,
   3198         object(
   3199             SchemaObjectKind::Trigger,
   3200             "nip46_pending_responses_guard_insert",
   3201             "nip46_pending_responses",
   3202             CREATE_NIP46_PENDING_RESPONSES_GUARD_INSERT_SQL,
   3203             NIP46_PENDING_RESPONSES_GUARD_INSERT_SHA256,
   3204         )?,
   3205         object(
   3206             SchemaObjectKind::Trigger,
   3207             "nip46_pending_responses_no_delete",
   3208             "nip46_pending_responses",
   3209             CREATE_NIP46_PENDING_RESPONSES_NO_DELETE_SQL,
   3210             NIP46_PENDING_RESPONSES_NO_DELETE_SHA256,
   3211         )?,
   3212         object(
   3213             SchemaObjectKind::Trigger,
   3214             "nip46_pending_responses_no_update",
   3215             "nip46_pending_responses",
   3216             CREATE_NIP46_PENDING_RESPONSES_NO_UPDATE_SQL,
   3217             NIP46_PENDING_RESPONSES_NO_UPDATE_SHA256,
   3218         )?,
   3219         object(
   3220             SchemaObjectKind::Trigger,
   3221             "nip46_signed_responses_guard_pending_insert",
   3222             "nip46_signed_responses",
   3223             CREATE_NIP46_SIGNED_RESPONSES_GUARD_PENDING_INSERT_SQL,
   3224             NIP46_SIGNED_RESPONSES_GUARD_PENDING_INSERT_SHA256,
   3225         )?,
   3226     ]);
   3227     Ok(objects)
   3228 }
   3229 
   3230 /// Independently validates exact catalog versions, counts, and digests.
   3231 pub fn validate_myc_state_catalogs(
   3232     migrations: &MigrationCatalog,
   3233     schema: &SchemaCatalog,
   3234 ) -> Result<(), MycStateCatalogError> {
   3235     let versions = schema.versions();
   3236     let descriptors = migrations.descriptors();
   3237     let valid = migrations.current_version() == MYC_STATE_SCHEMA_VERSION
   3238         && descriptors.len() == 11
   3239         && descriptors[0].target_version() == 2
   3240         && descriptors[0].name().as_str() == "create_myc_state_metadata"
   3241         && descriptors[0].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_2_MIGRATION_SHA256
   3242         && descriptors[1].target_version() == 3
   3243         && descriptors[1].name().as_str() == "create_nip46_request_admission"
   3244         && descriptors[1].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_3_MIGRATION_SHA256
   3245         && descriptors[2].target_version() == 4
   3246         && descriptors[2].name().as_str() == "create_connection_authorization_state"
   3247         && descriptors[2].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_4_MIGRATION_SHA256
   3248         && descriptors[3].target_version() == 5
   3249         && descriptors[3].name().as_str() == "create_bounded_governance_state"
   3250         && descriptors[3].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_5_MIGRATION_SHA256
   3251         && descriptors[4].target_version() == 6
   3252         && descriptors[4].name().as_str() == "create_delivery_evidence_state"
   3253         && descriptors[4].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_6_MIGRATION_SHA256
   3254         && descriptors[5].target_version() == 7
   3255         && descriptors[5].name().as_str() == "create_discovery_desired_state"
   3256         && descriptors[5].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_7_MIGRATION_SHA256
   3257         && descriptors[6].target_version() == 8
   3258         && descriptors[6].name().as_str() == "create_nip46_operation_completion"
   3259         && descriptors[6].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_8_MIGRATION_SHA256
   3260         && descriptors[7].target_version() == 9
   3261         && descriptors[7].name().as_str() == "create_nip46_atomic_response"
   3262         && descriptors[7].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_9_MIGRATION_SHA256
   3263         && descriptors[8].target_version() == 10
   3264         && descriptors[8].name().as_str() == "create_configuration_binding_history"
   3265         && descriptors[8].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_10_MIGRATION_SHA256
   3266         && descriptors[9].target_version() == 11
   3267         && descriptors[9].name().as_str() == "create_admin_operation_journal"
   3268         && descriptors[9].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_11_MIGRATION_SHA256
   3269         && descriptors[10].target_version() == 12
   3270         && descriptors[10].name().as_str() == "create_nip46_pending_response_authority"
   3271         && descriptors[10].checksum().as_bytes() == &MYC_STATE_SCHEMA_VERSION_12_MIGRATION_SHA256
   3272         && migrations.digest().as_bytes() == &MYC_MIGRATION_CATALOG_SHA256
   3273         && schema.migration_catalog_digest() == migrations.digest()
   3274         && versions.len() == 12
   3275         && versions[0].version() == MYC_STATE_BASE_SCHEMA_VERSION
   3276         && versions[0].object_count() == MYC_STATE_SCHEMA_VERSION_1_OBJECT_COUNT
   3277         && versions[0].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_1_SHA256
   3278         && versions[1].version() == 2
   3279         && versions[1].object_count() == MYC_STATE_SCHEMA_VERSION_2_OBJECT_COUNT
   3280         && versions[1].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_2_SHA256
   3281         && versions[2].version() == 3
   3282         && versions[2].object_count() == MYC_STATE_SCHEMA_VERSION_3_OBJECT_COUNT
   3283         && versions[2].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_3_SHA256
   3284         && versions[3].version() == 4
   3285         && versions[3].object_count() == MYC_STATE_SCHEMA_VERSION_4_OBJECT_COUNT
   3286         && versions[3].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_4_SHA256
   3287         && versions[4].version() == 5
   3288         && versions[4].object_count() == MYC_STATE_SCHEMA_VERSION_5_OBJECT_COUNT
   3289         && versions[4].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_5_SHA256
   3290         && versions[5].version() == 6
   3291         && versions[5].object_count() == MYC_STATE_SCHEMA_VERSION_6_OBJECT_COUNT
   3292         && versions[5].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_6_SHA256
   3293         && versions[6].version() == 7
   3294         && versions[6].object_count() == MYC_STATE_SCHEMA_VERSION_7_OBJECT_COUNT
   3295         && versions[6].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_7_SHA256
   3296         && versions[7].version() == 8
   3297         && versions[7].object_count() == MYC_STATE_SCHEMA_VERSION_8_OBJECT_COUNT
   3298         && versions[7].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_8_SHA256
   3299         && versions[8].version() == 9
   3300         && versions[8].object_count() == MYC_STATE_SCHEMA_VERSION_9_OBJECT_COUNT
   3301         && versions[8].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_9_SHA256
   3302         && versions[9].version() == 10
   3303         && versions[9].object_count() == MYC_STATE_SCHEMA_VERSION_10_OBJECT_COUNT
   3304         && versions[9].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_10_SHA256
   3305         && versions[10].version() == 11
   3306         && versions[10].object_count() == MYC_STATE_SCHEMA_VERSION_11_OBJECT_COUNT
   3307         && versions[10].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_11_SHA256
   3308         && versions[11].version() == 12
   3309         && versions[11].object_count() == MYC_STATE_SCHEMA_VERSION_12_OBJECT_COUNT
   3310         && versions[11].digest().as_bytes() == &MYC_STATE_SCHEMA_VERSION_12_SHA256
   3311         && schema.digest().as_bytes() == &MYC_STATE_SCHEMA_CATALOG_SHA256;
   3312     if valid {
   3313         Ok(())
   3314     } else {
   3315         Err(MycStateCatalogError::new(
   3316             MycStateCatalogErrorKind::CatalogMismatch,
   3317         ))
   3318     }
   3319 }