diff --git a/docs/site/src/lib/mcp-catalog.snapshot.json b/docs/site/src/lib/mcp-catalog.snapshot.json index caadf3c2..584bc418 100644 --- a/docs/site/src/lib/mcp-catalog.snapshot.json +++ b/docs/site/src/lib/mcp-catalog.snapshot.json @@ -54,13 +54,9 @@ "type": "object", "properties": { "activeWatcherId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "id": { @@ -117,7 +113,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -129,7 +125,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -149,7 +145,7 @@ "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ @@ -266,7 +262,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -274,33 +270,21 @@ ] }, "activeWatcherId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "activeWatcherHostname": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "activeWatcherWatchDirectory": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "activeWatcherDeregistered": { @@ -311,7 +295,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -333,13 +317,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -382,12 +362,12 @@ "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "updatedAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ @@ -648,13 +628,9 @@ "type": "string" }, "instrument_display_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "instrument_type": { @@ -700,14 +676,14 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "acquired_at": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -717,14 +693,14 @@ "updated_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "deleted_at": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -767,13 +743,9 @@ "maximum": 9007199254740991 }, "total_size_bytes": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - } + "type": [ + "number", + "string" ] }, "error_messages": { @@ -797,13 +769,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -974,14 +942,14 @@ "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "acquiredAt": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -991,14 +959,14 @@ "updatedAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "deletedAt": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -1006,13 +974,9 @@ ] }, "deletedBy": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "instrumentDisplayName": { @@ -1049,13 +1013,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -1110,13 +1070,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -1143,13 +1099,9 @@ "type": "string" }, "relativePath": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "category": { @@ -1171,46 +1123,34 @@ ] }, "sizeBytes": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] }, "contentType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "errorMessage": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "uploadedAt": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -1222,7 +1162,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -1308,13 +1248,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -1357,14 +1293,14 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "edited_at": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -1411,13 +1347,9 @@ "type": "string" }, "errorMessage": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -1589,13 +1521,9 @@ ] }, "contentType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "status": { @@ -1610,13 +1538,9 @@ ] }, "sizeBytes": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] } }, @@ -1652,13 +1576,9 @@ ] }, "contentType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "status": { @@ -1673,13 +1593,9 @@ ] }, "sizeBytes": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] } }, @@ -1722,13 +1638,9 @@ "type": "string" }, "errorMessage": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -1841,13 +1753,9 @@ "type": "string" }, "relativePath": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "category": { @@ -1869,46 +1777,34 @@ ] }, "sizeBytes": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] }, "contentType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "errorMessage": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "uploadedAt": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -1920,7 +1816,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -2042,13 +1938,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -2134,13 +2026,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -2230,13 +2118,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -2369,13 +2253,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -2418,14 +2298,14 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "edited_at": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -2510,13 +2390,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -2559,14 +2435,14 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "edited_at": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -2639,13 +2515,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -2688,14 +2560,14 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "edited_at": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -2862,7 +2734,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -2870,13 +2742,9 @@ ] }, "deletedBy": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "deletedByToken": { @@ -2962,7 +2830,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3057,7 +2925,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3377,53 +3245,33 @@ "type": "string" }, "relativePath": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "s3Bucket": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "s3Key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "contentType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "sizeBytes": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] }, "category": { @@ -3452,13 +3300,9 @@ "additionalProperties": {} }, "errorMessage": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "detectedAt": { @@ -3466,7 +3310,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3478,7 +3322,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3490,7 +3334,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3502,7 +3346,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3514,7 +3358,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3526,7 +3370,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3536,14 +3380,14 @@ "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "deletedAt": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3687,13 +3531,9 @@ "type": "string" }, "sizeBytes": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] }, "expiresInSeconds": { @@ -3845,7 +3685,7 @@ "deletedAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "alreadyApplied": { "type": "boolean" @@ -3910,33 +3750,21 @@ "type": "string" }, "instrumentDisplayName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "hostname": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "watcherVersion": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "effectiveStatus": { @@ -3953,7 +3781,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -3963,14 +3791,14 @@ "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "deletedAt": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -4033,33 +3861,21 @@ "type": "string" }, "instrumentDisplayName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "hostname": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "watcherVersion": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "effectiveStatus": { @@ -4076,7 +3892,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -4086,14 +3902,14 @@ "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "deletedAt": { "anyOf": [ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -4101,39 +3917,27 @@ ] }, "osInfo": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "configYaml": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "configChecksum": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "updatedAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "deregisteredByUser": { "anyOf": [ @@ -4150,13 +3954,9 @@ "type": "string" }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -4287,7 +4087,7 @@ "sinceIso": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "lookbackHours": { "type": "integer", @@ -4326,7 +4126,7 @@ "timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ @@ -4394,7 +4194,7 @@ "sinceIso": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "lookbackHours": { "type": "integer", @@ -4419,7 +4219,7 @@ "timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "status": { "type": "string" @@ -4576,7 +4376,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -4586,7 +4386,7 @@ "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "fileCount": { "type": "integer", @@ -4606,13 +4406,9 @@ ] }, "matchedFilename": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -4659,13 +4455,9 @@ "type": "string" }, "sizeBytes": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] } }, @@ -4718,7 +4510,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -4738,13 +4530,9 @@ ] }, "matchedPattern": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -4775,33 +4563,21 @@ "type": "string" }, "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "image": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -4833,7 +4609,7 @@ "createdAt": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "instrumentId": { "type": "string" @@ -4845,23 +4621,15 @@ "type": "string" }, "userId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "userName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "token": { @@ -4985,33 +4753,21 @@ "type": "string" }, "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "image": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "isAdmin": { @@ -5076,7 +4832,7 @@ { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { "type": "null" @@ -5155,24 +4911,16 @@ "type": "string" }, "section": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Heading ID of the matching section, or null for the intro." + "description": "Heading ID of the matching section, or null for the intro.", + "type": [ + "string", + "null" + ] }, "heading": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "excerpt": { @@ -5266,23 +5014,15 @@ "type": "string" }, "section": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "heading": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "url": { @@ -5393,15 +5133,11 @@ "description": "Link that opens this entry in Data Hub's changelog. Cite it in your answer." }, "docsUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The docs page that explains the change. Null when the entry has none." + "description": "The docs page that explains the change. Null when the entry has none.", + "type": [ + "string", + "null" + ] } }, "required": [ @@ -5519,33 +5255,21 @@ "type": "string" }, "attemptedAction": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toolName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "errorMessage": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "source": { @@ -5556,33 +5280,21 @@ ] }, "oauthClientId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "oauthClientName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "pageUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "status": { @@ -5602,23 +5314,15 @@ "type": "string" }, "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -5635,13 +5339,9 @@ ] }, "statusUpdatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "createdAt": { @@ -5672,23 +5372,15 @@ "type": "string" }, "priority": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] }, "priorityLabel": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "labels": { @@ -5719,23 +5411,15 @@ "type": "string" }, "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "userId": { @@ -5756,13 +5440,9 @@ ] }, "projectName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "teamName": { @@ -5803,53 +5483,33 @@ "type": "string" }, "actorName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "fromState": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toState": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toStateColor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "body": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -5974,33 +5634,21 @@ "type": "string" }, "attemptedAction": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toolName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "errorMessage": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "source": { @@ -6011,33 +5659,21 @@ ] }, "oauthClientId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "oauthClientName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "pageUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "status": { @@ -6057,23 +5693,15 @@ "type": "string" }, "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -6090,13 +5718,9 @@ ] }, "statusUpdatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "createdAt": { @@ -6127,23 +5751,15 @@ "type": "string" }, "priority": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] }, "priorityLabel": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "labels": { @@ -6174,23 +5790,15 @@ "type": "string" }, "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "userId": { @@ -6211,13 +5819,9 @@ ] }, "projectName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "teamName": { @@ -6258,53 +5862,33 @@ "type": "string" }, "actorName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "fromState": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toState": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toStateColor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "body": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -6477,33 +6061,21 @@ "type": "string" }, "attemptedAction": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toolName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "errorMessage": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "source": { @@ -6514,33 +6086,21 @@ ] }, "oauthClientId": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "oauthClientName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "pageUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "status": { @@ -6560,23 +6120,15 @@ "type": "string" }, "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, @@ -6593,13 +6145,9 @@ ] }, "statusUpdatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "createdAt": { @@ -6630,23 +6178,15 @@ "type": "string" }, "priority": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } + "type": [ + "number", + "null" ] }, "priorityLabel": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "labels": { @@ -6677,23 +6217,15 @@ "type": "string" }, "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "avatarUrl": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "userId": { @@ -6714,13 +6246,9 @@ ] }, "projectName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "teamName": { @@ -6761,53 +6289,33 @@ "type": "string" }, "actorName": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "fromState": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toState": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "toStateColor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "body": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] } }, diff --git a/web/lib/auth.ts b/web/lib/auth.ts index 473ad0ab..3acde356 100644 --- a/web/lib/auth.ts +++ b/web/lib/auth.ts @@ -15,9 +15,12 @@ import { accounts, jwks, oauthAccessTokens, + oauthClientAssertions, + oauthClientResources, oauthClients, oauthConsents, oauthRefreshTokens, + oauthResources, sessions, users, verifications, @@ -140,6 +143,9 @@ export const authInstance = betterAuth({ oauthRefreshToken: oauthRefreshTokens, oauthAccessToken: oauthAccessTokens, oauthConsent: oauthConsents, + oauthResource: oauthResources, + oauthClientResource: oauthClientResources, + oauthClientAssertion: oauthClientAssertions, }, }), ...(googleClientId && googleClientSecret @@ -258,9 +264,12 @@ export const authInstance = betterAuth({ loginPage: "/login", consentPage: "/consent", scopes: [...oauthScopes], - // One audience per deployment: GHSA-p2fr-6hmx-4528 lets a client pick any - // allow-listed `resource` at the token endpoint until 1.7 ships stable. - validAudiences: [mcpResourceAudience], + // One audience per deployment, seeded into `oauth_resource` at boot. + resources: [mcpResourceAudience], + // Clients registered under Better Auth 1.6 have no `oauth_client_resource` + // link and would get `invalid_target`. With a single resource, linking + // each client restricts nothing. + enforcePerClientResources: false, // Cursor / mcp-remote still require RFC 7591 Dynamic Client Registration. // Open registration only creates OAuth clients — Google Workspace still // gates who can sign in. @@ -274,11 +283,10 @@ export const authInstance = betterAuth({ allowUnauthenticatedClientRegistration: true, clientRegistrationDefaultScopes: [...oauthScopes], clientRegistrationAllowedScopes: [...oauthScopes], - // Path-aware AS metadata lives at - // `/.well-known/oauth-authorization-server/api/auth` (issuer path). - silenceWarnings: { - oauthAuthServerConfig: true, - }, + // Cursor and Claude Code omit `application_type`, and the `web` default + // rejects their `cursor://` and loopback callbacks. "infer" registers + // them as `native`; clients with only https callbacks stay `web`. + clientRegistrationDefaultApplicationType: "infer", }), // Must be last so Set-Cookie from server actions (sign-in / sign-out) // reaches the browser via Next's `cookies()` helper. diff --git a/web/lib/db/schema.ts b/web/lib/db/schema.ts index 6623bb79..e114d8ac 100644 --- a/web/lib/db/schema.ts +++ b/web/lib/db/schema.ts @@ -121,8 +121,9 @@ export const accounts = pgTable( .references(() => users.id, { onDelete: "cascade" }), // Provider's account ID, or the user id for `credential` accounts. accountId: text("accountId").notNull(), - // Written by Better Auth 1.7 only. Left nullable so the 1.6 runtime, - // which does not know this column, can still insert account rows. + // Only Better Auth 1.7.0–1.7.2 wrote this; 1.7.3+ identifies accounts by + // `providerId` and `accountId` again. Must stay nullable, because new rows + // leave it empty. issuer: text("issuer"), // OAuth provider id (e.g. `google`) or `credential` for email/password. providerId: text("providerId").notNull(), diff --git a/web/lib/db/seed.ts b/web/lib/db/seed.ts index f6531182..dae73c13 100644 --- a/web/lib/db/seed.ts +++ b/web/lib/db/seed.ts @@ -51,11 +51,15 @@ export const SEED_WATCHER_VERSION = "1.0.0"; // --------------------------------------------------------------------------- // clearAll — schema-driven TRUNCATE of every `pgTable` declared in -// `lib/db/schema.ts`. Uses CASCADE so FK ordering doesn't matter; the -// previous static `TRUNCATE_ORDER` list was a maintenance hazard (every -// new table required a manual edit) and is replaced by this. +// `lib/db/schema.ts` except `jwks`. Uses CASCADE so FK ordering doesn't +// matter; the previous static `TRUNCATE_ORDER` list was a maintenance hazard +// (every new table required a manual edit) and is replaced by this. // --------------------------------------------------------------------------- +// The MCP route caches the published signing keys and rate-limits refetches, +// so a running server would reject tokens signed by a replacement key. +const KEPT_TABLES = new Set([getTableName(schema.jwks)]); + export async function clearAll(db: Db): Promise { // Cast through `unknown[]` so the `isTable` type predicate can narrow // away the `PgEnum`s and other non-table exports in the schema module @@ -64,7 +68,8 @@ export async function clearAll(db: Db): Promise { // but TS won't accept the union as-is). const tableNames = (Object.values(schema) as unknown[]) .filter(isTable) - .map((t) => getTableName(t)); + .map((t) => getTableName(t)) + .filter((name) => !KEPT_TABLES.has(name)); if (tableNames.length === 0) { return; @@ -199,6 +204,24 @@ export async function seedSlackChannelConfig( ); } +// The MCP audience row that `resources` in `lib/auth.ts` declares. Better Auth +// inserts it only once per server process, so a server that outlives a reset +// rejects every MCP token request with `invalid_target` until this restores it. +export async function seedMcpResource(db: Db, origin: string): Promise { + const identifier = `${origin}/mcp/v1`; + const now = new Date(); + await db + .insert(schema.oauthResources) + .values({ + id: crypto.randomUUID(), + identifier, + name: identifier, + createdAt: now, + updatedAt: now, + }) + .onConflictDoNothing({ target: schema.oauthResources.identifier }); +} + // --------------------------------------------------------------------------- // Instruments — mirrors the production catalog (ids + display names) so docs // screenshots look real, plus one pending instrument for the activate- diff --git a/web/lib/mcp/auth.ts b/web/lib/mcp/auth.ts index 7bfc38a4..0aa10021 100644 --- a/web/lib/mcp/auth.ts +++ b/web/lib/mcp/auth.ts @@ -30,12 +30,11 @@ export async function verifyMcpToken( } try { - // better-auth 1.6 exposes `verifyAccessToken(token)`; 1.7's - // `verifyAccessTokenRequest(req)` (DPoP-aware) is not available yet. - // Opaque tokens (no `resource` at token exchange) are rejected — JWKS - // verification requires a JWT, and we intentionally do not hand-roll - // DB lookups that skip audience checks. - const payload = await resourceClient.verifyAccessToken(bearerToken, { + // MCP already extracted the Bearer token, so DPoP-bound tokens are + // rejected here. Opaque tokens (no `resource` at token exchange) fail + // JWKS verification, and we do not hand-roll DB lookups that skip + // audience checks. + const payload = await resourceClient.verifyBearerToken(bearerToken, { verifyOptions: { audience: mcpResourceAudience, // Must match JWT `iss` / AS metadata issuer (`{origin}/api/auth`). diff --git a/web/package-lock.json b/web/package-lock.json index f6237a76..2eaefd00 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -15,7 +15,7 @@ "@aws-sdk/crc64-nvme": "^3.972.5", "@aws-sdk/s3-request-presigner": "^3.1021.0", "@base-ui/react": "^1.7.0", - "@better-auth/oauth-provider": "1.6.27", + "@better-auth/oauth-provider": "1.7.10", "@modelcontextprotocol/client": "^2.0.0", "@modelcontextprotocol/server": "^2.0.0", "@slack/web-api": "^7.17.0", @@ -27,7 +27,7 @@ "@vercel/functions": "^3.7.3", "@vercel/microfrontends": "^2.4.0", "@vercel/oidc-aws-credentials-provider": "^3.0.7", - "better-auth": "1.6.27", + "better-auth": "1.7.10", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", @@ -1566,43 +1566,39 @@ "license": "MIT" }, "node_modules/@better-auth/core": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.6.27.tgz", - "integrity": "sha512-A6/mQW4AT2kSHCRZDh9+k8jPUqnCUUCymzBgIroK0l60wLioMtJdcmZiTwrAn6KVUw+4XWw64MgaRn7LOie3wg==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.7.10.tgz", + "integrity": "sha512-c5vxtnk7UxWe/iF/X5sKSgmPcN5n6biuwJBs2dMkceMwvMWBHLosue6h/vmvKns9SYKbkBNWsurFe7yIbv13dQ==", "license": "MIT", "dependencies": { - "@opentelemetry/semantic-conventions": "^1.39.0", + "@opentelemetry/semantic-conventions": "^1.41.1", "@standard-schema/spec": "^1.1.0", - "zod": "^4.3.6" + "zod": "^4.5.4" }, "peerDependencies": { - "@better-auth/utils": "0.4.2", - "@better-fetch/fetch": "1.3.1", - "@cloudflare/workers-types": ">=4", + "@better-auth/utils": "^0.4.2 || ^0.5.0", + "@better-fetch/fetch": "1.3.2", "@opentelemetry/api": "^1.9.0", - "better-call": "1.4.0", + "better-call": "1.4.2", "jose": "^6.1.0", "kysely": "^0.28.5 || ^0.29.0", "nanostores": "^1.0.1" }, "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - }, "@opentelemetry/api": { "optional": true } } }, "node_modules/@better-auth/drizzle-adapter": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@better-auth/drizzle-adapter/-/drizzle-adapter-1.6.27.tgz", - "integrity": "sha512-BDJ02ra/fji/ah3aIpxjjNOu/JQVex0UisxS4S0vGZZyiAs+DL24mn3/iovyD5dWB3u3NaGg1n8zpTOntiIXcg==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@better-auth/drizzle-adapter/-/drizzle-adapter-1.7.10.tgz", + "integrity": "sha512-Uc/Eh9cnvorIWA6J97Hv8zjR8sCVUP6G7M3xHJGTD9qJXC69zoY4ULmNGA73AmGJB1q+VEYs2cRMtJ6fR6HP6g==", "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.27", - "@better-auth/utils": "0.4.2", - "drizzle-orm": "^0.45.2" + "@better-auth/core": "^1.7.10", + "@better-auth/utils": "^0.4.2 || ^0.5.0", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0" }, "peerDependenciesMeta": { "drizzle-orm": { @@ -1611,13 +1607,13 @@ } }, "node_modules/@better-auth/kysely-adapter": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@better-auth/kysely-adapter/-/kysely-adapter-1.6.27.tgz", - "integrity": "sha512-aavv7W4+b3QVObYo166baplWvwocCk8ORDxRqQ9ytzVl/waiUpSXAOtDHdXZHFsoVHFVPtEzyEq0Tqr3Qvvfig==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@better-auth/kysely-adapter/-/kysely-adapter-1.7.10.tgz", + "integrity": "sha512-ZWWc6h5lgcwQMTcqMLNWw+jTEMFfrqJHD+VamiCUdaAxZzVAkjLZzVA2r0vZ5w7xnTY9vWS7wuNVqAKNLRTlYQ==", "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.27", - "@better-auth/utils": "0.4.2", + "@better-auth/core": "^1.7.10", + "@better-auth/utils": "^0.4.2 || ^0.5.0", "kysely": "^0.28.17 || ^0.29.0" }, "peerDependenciesMeta": { @@ -1627,23 +1623,23 @@ } }, "node_modules/@better-auth/memory-adapter": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@better-auth/memory-adapter/-/memory-adapter-1.6.27.tgz", - "integrity": "sha512-p4NB37MdaVFkxkpLEAKjORgTPhaOAPu1M2zgQXiTJJ3F6Uq3Y1YcCgoz+VxJu0TQfxibCsJD/dZlJMVgf+CF7A==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@better-auth/memory-adapter/-/memory-adapter-1.7.10.tgz", + "integrity": "sha512-3Di7y8BK5I2pCdpRaJ2ggkVliO/Swr6a/J+y9RFdwkbxhEMU1o9WD9IwoG3LFH8dvFF3kVo+GilsZsVNlYD+sw==", "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.27", - "@better-auth/utils": "0.4.2" + "@better-auth/core": "^1.7.10", + "@better-auth/utils": "^0.4.2 || ^0.5.0" } }, "node_modules/@better-auth/mongo-adapter": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@better-auth/mongo-adapter/-/mongo-adapter-1.6.27.tgz", - "integrity": "sha512-IOYbJMIjEC//f+JpFlmIQjh6x1R/rGAfdzlojFk6HeAJqbsELuMcI+27dIoesbfHLF/icTrSpZtK986XhJrCfA==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@better-auth/mongo-adapter/-/mongo-adapter-1.7.10.tgz", + "integrity": "sha512-7z48PlXtlSKGvdOXfVmbjZE1vRmYyOQqHiPbeLpw+NvAPSTI9N4r7OO47u2MebA3q25e3GoGEwk5BAEE07u+PQ==", "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.27", - "@better-auth/utils": "0.4.2", + "@better-auth/core": "^1.7.10", + "@better-auth/utils": "^0.4.2 || ^0.5.0", "mongodb": "^6.0.0 || ^7.0.0" }, "peerDependenciesMeta": { @@ -1653,30 +1649,30 @@ } }, "node_modules/@better-auth/oauth-provider": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@better-auth/oauth-provider/-/oauth-provider-1.6.27.tgz", - "integrity": "sha512-xUQ8GgbWUOYesO5wocrzbHdGa0Jojrxh59Vdew/1xzRRDYfXPEP/vq8Sj754BBwXjGAoKkvU/u6BaLXLBNOlYA==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@better-auth/oauth-provider/-/oauth-provider-1.7.10.tgz", + "integrity": "sha512-4amjFIuLYiUxlUzvvRagiyLPUz977OTMfS74A1IWW0WFu0PC4x7+daWnTXcLYywrf09ulBjTUJEzVGS2jmc4jA==", "license": "MIT", "dependencies": { - "jose": "^6.1.3", - "zod": "^4.3.6" + "jose": "^6.2.3", + "zod": "^4.5.4" }, "peerDependencies": { - "@better-auth/core": "^1.6.27", - "@better-auth/utils": "0.4.2", - "@better-fetch/fetch": "1.3.1", - "better-auth": "^1.6.27", - "better-call": "1.4.0" + "@better-auth/core": "^1.7.10", + "@better-auth/utils": "^0.4.2 || ^0.5.0", + "@better-fetch/fetch": "1.3.2", + "better-auth": "^1.7.10", + "better-call": "1.4.2" } }, "node_modules/@better-auth/prisma-adapter": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@better-auth/prisma-adapter/-/prisma-adapter-1.6.27.tgz", - "integrity": "sha512-v7DXVyaFbkrfLoiFDtcVF7BkEZgFa/DgEGE7XjrAXmMACa5pjDvb7lm8W5X+/qgIbQP04eThhgFQ6EWOsjr8OQ==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@better-auth/prisma-adapter/-/prisma-adapter-1.7.10.tgz", + "integrity": "sha512-hNlhn0Kcq/O76SehvqznFsjqfEMdM2m2ctazU/BLv+jT8+hGvvxCInXZi6x86/xpAyDTgU7t7KsK50r6mdNR1g==", "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.27", - "@better-auth/utils": "0.4.2", + "@better-auth/core": "^1.7.10", + "@better-auth/utils": "^0.4.2 || ^0.5.0", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" }, @@ -1690,41 +1686,29 @@ } }, "node_modules/@better-auth/telemetry": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@better-auth/telemetry/-/telemetry-1.6.27.tgz", - "integrity": "sha512-aYrSiVWQfua8w5YX8X1cM6ca48EdS0t5k+CvYXIsruaNIpR1DXMe1DOD0M5FWAVABnlCf9joyHXbFRSIZSNY/A==", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@better-auth/telemetry/-/telemetry-1.7.10.tgz", + "integrity": "sha512-1OamUtbGRaYHB0tRjKK3Jv6hzI6mZMv3pujkg8k7tr3idQuToMoVXsWAD9oFbUTmOLeix58n+grzsl7r0fR0Sw==", "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.27", - "@better-auth/utils": "0.4.2", - "@better-fetch/fetch": "1.3.1" + "@better-auth/core": "^1.7.10", + "@better-auth/utils": "^0.4.2 || ^0.5.0", + "@better-fetch/fetch": "1.3.2" } }, "node_modules/@better-auth/utils": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.4.2.tgz", - "integrity": "sha512-AUxrvu+HaaODsUyzDxFgwd/8RZ1yZaYo42LXKSrU2oGgR38pS1ij8nqQKNgtTWoYGpNevNXtCfgTy6loHveW9A==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.5.0.tgz", + "integrity": "sha512-BL8W4EfIZFwlu0r54m3v1ztjDhu6dDe/amLTm0xybmbZaNgYUqhD3SjpAsnq0q8YD6/ki4iwIgxJNLP/N3TxiA==", "license": "MIT", "dependencies": { "@noble/hashes": "^2.0.1" } }, - "node_modules/@better-auth/utils/node_modules/@noble/hashes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz", - "integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@better-fetch/fetch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.3.1.tgz", - "integrity": "sha512-ABkD1WhyfPZprKRQI3bhATjeiFuNWC9PXhfGWqL+sg/gKrM977oFrYkdb4msM3hgUGonr7KlOsOFT5TU2rht9g==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.3.2.tgz", + "integrity": "sha512-Gs7n99b5tqUC6cQAPbV0uED3IraHB6xQbHLQ/C3l7ZFafHScOx9pQ+DYmP5blbLFShVWLqxNUlI9wi4xU/X+ow==", "license": "MIT" }, "node_modules/@biomejs/biome": { @@ -3581,6 +3565,30 @@ "node": ">= 10" } }, + "node_modules/@noble/ciphers": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.4.0.tgz", + "integrity": "sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz", + "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodable/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz", @@ -8121,38 +8129,37 @@ } }, "node_modules/better-auth": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.6.27.tgz", - "integrity": "sha512-x3jyxpAiBSsMO/DaXMFSVwM8bTqnYZlCKsZxBV43zL3ZtsGa/CzeUuNKxPT2Lsz7ahTBY90Ku1tibN6nRpVEbw==", - "license": "MIT", - "dependencies": { - "@better-auth/core": "1.6.27", - "@better-auth/drizzle-adapter": "1.6.27", - "@better-auth/kysely-adapter": "1.6.27", - "@better-auth/memory-adapter": "1.6.27", - "@better-auth/mongo-adapter": "1.6.27", - "@better-auth/prisma-adapter": "1.6.27", - "@better-auth/telemetry": "1.6.27", - "@better-auth/utils": "0.4.2", - "@better-fetch/fetch": "1.3.1", - "@noble/ciphers": "^2.1.1", - "@noble/hashes": "^2.0.1", - "better-call": "1.4.0", + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.7.10.tgz", + "integrity": "sha512-Paf0X8cHKQc8jCgM3vl4AoxRicWdNf0zw8Aggn1q6aNSWCDDxSZCb6rkXa/O9cPc8idjVPK0rV/eHPHAbs07ZA==", + "license": "MIT", + "dependencies": { + "@better-auth/core": "1.7.10", + "@better-auth/drizzle-adapter": "1.7.10", + "@better-auth/kysely-adapter": "1.7.10", + "@better-auth/memory-adapter": "1.7.10", + "@better-auth/mongo-adapter": "1.7.10", + "@better-auth/prisma-adapter": "1.7.10", + "@better-auth/telemetry": "1.7.10", + "@better-auth/utils": "0.5.0", + "@better-fetch/fetch": "1.3.2", + "@noble/ciphers": "^2.2.0", + "@noble/hashes": "^2.2.0", + "better-call": "1.4.2", "defu": "^6.1.4", - "jose": "^6.1.3", + "jose": "^6.2.3", "kysely": "^0.28.17 || ^0.29.0", - "nanostores": "^1.1.1", - "zod": "^4.3.6" + "nanostores": "^1.3.0", + "zod": "^4.5.4" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", - "@sveltejs/kit": "^2.0.0", + "@sveltejs/kit": "^2.0.0 || ^3.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", - "better-sqlite3": "^12.0.0", - "drizzle-kit": ">=0.31.4", - "drizzle-orm": "^0.45.2", + "drizzle-kit": ">=0.31.4 || >=1.0.0-beta.1", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", @@ -8162,7 +8169,7 @@ "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", - "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", + "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "vue": "^3.0.0" }, "peerDependenciesMeta": { @@ -8181,9 +8188,6 @@ "@tanstack/solid-start": { "optional": true }, - "better-sqlite3": { - "optional": true - }, "drizzle-kit": { "optional": true }, @@ -8225,34 +8229,10 @@ } } }, - "node_modules/better-auth/node_modules/@noble/ciphers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.2.0.tgz", - "integrity": "sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/better-auth/node_modules/@noble/hashes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz", - "integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/better-call": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.4.0.tgz", - "integrity": "sha512-bBKOT4vv1kZLDgxVePdilk/Jwkn+dtRRsmi3DzHcDP+WnswyVl6dR59l2HEeP/0cB+bDoopASAesWDPIdd/zZA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.4.2.tgz", + "integrity": "sha512-lOmFCTG1KcE60YWxoff2Wx0Fv7v7drP/fQTDYnhJUCdkA7V6QWXdLPUiMpOQCq7Fd0Ts3AkrRwD23xoiootlGA==", "license": "MIT", "dependencies": { "@better-auth/utils": "^0.5.0", @@ -8269,27 +8249,6 @@ } } }, - "node_modules/better-call/node_modules/@better-auth/utils": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.5.0.tgz", - "integrity": "sha512-BL8W4EfIZFwlu0r54m3v1ztjDhu6dDe/amLTm0xybmbZaNgYUqhD3SjpAsnq0q8YD6/ki4iwIgxJNLP/N3TxiA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^2.0.1" - } - }, - "node_modules/better-call/node_modules/@noble/hashes": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.3.0.tgz", - "integrity": "sha512-oN+QwyX7VSHotibwubG3kpzbwKrfnyR6OOO+3Nk/53ADL7FmgHHz4TgrbaYKvvOw09u6QTx0oiH1cNCIOuN0CQ==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/body-parser": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", @@ -10820,9 +10779,9 @@ } }, "node_modules/kysely": { - "version": "0.29.4", - "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.29.4.tgz", - "integrity": "sha512-y5mVgQNkMbs1eK9Xyc0pmNdabN2wHhRYY/5r4W5HrUT1rYCEPeVNSj1RUJeSDKT3U0p+mXCvLgkrFuIafYI6BA==", + "version": "0.29.6", + "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.29.6.tgz", + "integrity": "sha512-hHaB8C/rfzDDtr/t8YZwxAuPJTT0zHyaPoVzcXwDYhYNAgH/4sIfVhi/XLLIY+bL/FqaIJnjATDbi8ObSELmxg==", "license": "MIT", "engines": { "node": ">=22.0.0" @@ -12242,9 +12201,9 @@ } }, "node_modules/nanostores": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.4.2.tgz", - "integrity": "sha512-Wxv8Roefr2nqtiRG0bnaFlpYqpIVtOEeJZHaH+4nGgOK1/7n6OHOuHCb/bhqrNQgZM8fyd0s1PqhdrJc9Ib44g==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.5.5.tgz", + "integrity": "sha512-FixtE239Gl6Gz0ZGCK0WzvNwObNCIwVT+L7zQcf1QgcA6AzBxblzqe9OT88qiucNkhsjSOqiogSaF5jVbJiqSA==", "funding": [ { "type": "github", @@ -13938,9 +13897,9 @@ } }, "node_modules/set-cookie-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.2.tgz", - "integrity": "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.4.tgz", + "integrity": "sha512-iEmdEew+Tn1BwMGMP8LzGBEPC7Mf1sySjglCeEPb/Vchm9bnGezePvacYcId+fGprQzIng+TBkzqfJ/qS7AsBg==", "license": "MIT" }, "node_modules/setprototypeof": { @@ -15545,9 +15504,9 @@ } }, "node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/web/package.json b/web/package.json index eb000b95..237cb18e 100644 --- a/web/package.json +++ b/web/package.json @@ -40,7 +40,7 @@ "@aws-sdk/crc64-nvme": "^3.972.5", "@aws-sdk/s3-request-presigner": "^3.1021.0", "@base-ui/react": "^1.7.0", - "@better-auth/oauth-provider": "1.6.27", + "@better-auth/oauth-provider": "1.7.10", "@modelcontextprotocol/client": "^2.0.0", "@modelcontextprotocol/server": "^2.0.0", "@slack/web-api": "^7.17.0", @@ -52,7 +52,7 @@ "@vercel/functions": "^3.7.3", "@vercel/microfrontends": "^2.4.0", "@vercel/oidc-aws-credentials-provider": "^3.0.7", - "better-auth": "1.6.27", + "better-auth": "1.7.10", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", @@ -105,7 +105,6 @@ "vitest": "^4.1.2" }, "overrides": { - "@better-auth/core": "1.6.27", "body-parser": "^2.3.0", "brace-expansion": "^5.0.7", "esbuild": "^0.28.1", diff --git a/web/scripts/seed-workspace.ts b/web/scripts/seed-workspace.ts index 45502f47..31d57baa 100644 --- a/web/scripts/seed-workspace.ts +++ b/web/scripts/seed-workspace.ts @@ -6,6 +6,7 @@ // caller reaches the app. import type { NodePgDatabase } from "drizzle-orm/node-postgres"; +import { appOrigin } from "@/lib/app-origin"; import type * as schema from "@/lib/db/schema"; import { clearAll, @@ -18,6 +19,7 @@ import { seedDevUser, seedInstrumentSubscriptions, seedInstruments, + seedMcpResource, seedNotifications, seedRunAttributions, seedRunComments, @@ -49,6 +51,9 @@ export async function seedWorkspace(db: Db): Promise { console.log("Seeding slack_channel_config…"); await seedSlackChannelConfig(db); + console.log("Seeding oauth_resource…"); + await seedMcpResource(db, appOrigin()); + console.log("Seeding admin user…"); const { userId, email, token } = await seedDevUser(db, { email: SEED_ADMIN_EMAIL, diff --git a/web/tests/integration/helpers.ts b/web/tests/integration/helpers.ts index 02e9f501..1fa03dfa 100644 --- a/web/tests/integration/helpers.ts +++ b/web/tests/integration/helpers.ts @@ -8,6 +8,7 @@ import { clearAll, type SeedUserOptions, seedDevUser, + seedMcpResource, seedSlackChannelConfig, seedWatcherReleaseConfig, } from "@/lib/db/seed"; @@ -41,11 +42,11 @@ export async function closeTestDb() { } } -// TRUNCATE every `pgTable` declared in `lib/db/schema.ts`, then re-seed -// singleton config rows with deterministic baselines. Tests previously -// hard-coded both the table list and the singleton SQL inline; both now -// live in `@/lib/db/seed` so adding a new table doesn't require touching -// this file. +// TRUNCATE every `pgTable` declared in `lib/db/schema.ts` (except the auth +// signing keys; see `clearAll`), then re-seed singleton config rows with +// deterministic baselines. Tests previously hard-coded both the table list +// and the singleton SQL inline; both now live in `@/lib/db/seed` so adding a +// new table doesn't require touching this file. // // `clearAll` uses TRUNCATE CASCADE, which ignores the `ON DELETE SET NULL` // on singleton `updated_by → user.id` FKs and wipes the rows regardless @@ -60,6 +61,7 @@ export async function resetDb() { db, captureBase ? `${captureBase}/webhook` : null ); + await seedMcpResource(db, getBaseUrl()); } // --------------------------------------------------------------------------- diff --git a/web/tests/integration/mcp-oauth.test.ts b/web/tests/integration/mcp-oauth.test.ts index b201e339..53b25803 100644 --- a/web/tests/integration/mcp-oauth.test.ts +++ b/web/tests/integration/mcp-oauth.test.ts @@ -188,7 +188,7 @@ describe("MCP OAuth authorization-code flow", () => { scope: "openid profile email offline_access read write", }, }); - expect(registerRes.status).toBe(200); + expect(registerRes.status).toBe(201); const registered = (await registerRes.json()) as { client_id?: string; }; @@ -323,28 +323,38 @@ describe("MCP OAuth authorization-code flow", () => { ); }); - it("DCR without scope body still allows authorize with read write", async () => { - // Cursor registers without `scope`, then requests `read write` from the - // WWW-Authenticate challenge. The client's stored scopes must include write - // or authorize redirects with invalid_scope. + it("registers Cursor's DCR request and authorizes read write", async () => { + // Cursor's real registration body: no `application_type`, no `scope`, and + // a host-bearing `cursor://` callback. It then requests `read write` from + // the WWW-Authenticate challenge, so the stored scopes must include write. const issuer = expectedIssuer(); - const redirectUri = "http://127.0.0.1:8787/callback"; + const redirectUri = "cursor://anysphere.cursor-mcp/oauth/callback"; const { challenge } = pkcePair(); const registerRes = await api("/api/auth/oauth2/register", { method: "POST", body: { - client_name: "Cursor-like MCP Client", - redirect_uris: [redirectUri], - token_endpoint_auth_method: "none", - grant_types: ["authorization_code"], + client_name: "Cursor", + redirect_uris: [ + redirectUri, + "https://www.cursor.com/agents/mcp/oauth/callback", + "http://localhost:8787/callback", + ], + grant_types: ["authorization_code", "refresh_token"], response_types: ["code"], + token_endpoint_auth_method: "none", }, }); - expect(registerRes.status).toBe(200); + expect(registerRes.status).toBe(201); const { client_id: clientId } = (await registerRes.json()) as { client_id: string; }; + const [storedClient] = await getTestDb() + .select({ applicationType: schema.oauthClients.applicationType }) + .from(schema.oauthClients) + .where(eq(schema.oauthClients.clientId, clientId)) + .limit(1); + expect(storedClient?.applicationType).toBe("native"); const sessionCookie = await seedSessionCookie(userId); const authorizeUrl = new URL(`${issuer}/oauth2/authorize`); @@ -379,7 +389,7 @@ describe("MCP OAuth authorization-code flow", () => { // the AS advertises it. Both lists must agree or authorize redirects with // invalid_scope. const issuer = expectedIssuer(); - const redirectUri = "http://127.0.0.1:8788/callback"; + const redirectUri = "http://localhost:3118/callback"; const { challenge } = pkcePair(); const prmRes = await api("/.well-known/oauth-protected-resource/mcp/v1"); @@ -399,7 +409,7 @@ describe("MCP OAuth authorization-code flow", () => { scope: advertisedScopes.join(" "), }, }); - expect(registerRes.status).toBe(200); + expect(registerRes.status).toBe(201); const { client_id: clientId } = (await registerRes.json()) as { client_id: string; }; @@ -431,6 +441,27 @@ describe("MCP OAuth authorization-code flow", () => { expect(consentUrl.search).not.toMatch(/invalid_scope/); }); + it("DCR rejects a routable http callback next to a custom scheme", async () => { + // The custom scheme makes "infer" treat the client as native, and native + // clients may only use loopback for plain http. + const registerRes = await api("/api/auth/oauth2/register", { + method: "POST", + body: { + client_name: "Mixed Redirect Client", + redirect_uris: [ + "cursor://anysphere.cursor-mcp/oauth/callback", + "http://example.com/callback", + ], + token_endpoint_auth_method: "none", + grant_types: ["authorization_code"], + response_types: ["code"], + }, + }); + expect(registerRes.status).toBe(400); + const body = (await registerRes.json()) as { error?: string }; + expect(body.error).toBe("invalid_redirect_uri"); + }); + it("read-only OAuth token can read but not mutate via MCP", async () => { const accessToken = await getMcpAccessToken(userId, "read"); diff --git a/web/tests/unit/mcp-verify-token.test.ts b/web/tests/unit/mcp-verify-token.test.ts index 76460706..04911cfa 100644 --- a/web/tests/unit/mcp-verify-token.test.ts +++ b/web/tests/unit/mcp-verify-token.test.ts @@ -5,14 +5,14 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; // verify → `authInfoFromPayload`, and that `dhub_` tokens never reach the // token table. -const { mockVerifyAccessToken, mockAuthenticateWithToken } = vi.hoisted(() => ({ - mockVerifyAccessToken: vi.fn(), +const { mockVerifyBearerToken, mockAuthenticateWithToken } = vi.hoisted(() => ({ + mockVerifyBearerToken: vi.fn(), mockAuthenticateWithToken: vi.fn(), })); vi.mock("better-auth/client", () => ({ createAuthClient: () => ({ - verifyAccessToken: mockVerifyAccessToken, + verifyBearerToken: mockVerifyBearerToken, }), })); @@ -35,7 +35,7 @@ import { verifyMcpToken } from "@/lib/mcp/auth"; describe("verifyMcpToken", () => { beforeEach(() => { - mockVerifyAccessToken.mockReset(); + mockVerifyBearerToken.mockReset(); mockAuthenticateWithToken.mockReset(); }); @@ -43,11 +43,11 @@ describe("verifyMcpToken", () => { await expect( verifyMcpToken(new Request("http://localhost/mcp/v1")) ).resolves.toBeUndefined(); - expect(mockVerifyAccessToken).not.toHaveBeenCalled(); + expect(mockVerifyBearerToken).not.toHaveBeenCalled(); }); it("maps a verified JWT payload onto AuthInfo", async () => { - mockVerifyAccessToken.mockResolvedValue({ + mockVerifyBearerToken.mockResolvedValue({ sub: "user-1", client_id: "client-1", scope: "read write", @@ -70,7 +70,7 @@ describe("verifyMcpToken", () => { }); it("rejects verified JWTs that look like client_credentials", async () => { - mockVerifyAccessToken.mockResolvedValue({ + mockVerifyBearerToken.mockResolvedValue({ sub: "client-1", client_id: "client-1", scope: "read", @@ -82,7 +82,7 @@ describe("verifyMcpToken", () => { }); it("returns undefined when JWT verification fails", async () => { - mockVerifyAccessToken.mockRejectedValue(new Error("invalid access token")); + mockVerifyBearerToken.mockRejectedValue(new Error("invalid access token")); await expect( verifyMcpToken(new Request("http://localhost/mcp/v1"), "not-a-jwt") @@ -91,7 +91,7 @@ describe("verifyMcpToken", () => { }); it("does not accept dhub_ personal access tokens", async () => { - mockVerifyAccessToken.mockRejectedValue(new Error("JWSInvalid")); + mockVerifyBearerToken.mockRejectedValue(new Error("JWSInvalid")); mockAuthenticateWithToken.mockResolvedValue({ userId: "pat-user", scopes: ["*"],