From 866bb6f02cbe3d1671555c24de720db38d9dea34 Mon Sep 17 00:00:00 2001 From: Thibault Le Ouay Ducasse Date: Fri, 24 Jul 2026 16:30:35 +0200 Subject: [PATCH] fix pr --- apps/server/static/openapi.yaml | 6 ++ .../openstatus/monitor/v1/dns_monitor.proto | 4 +- .../openstatus/monitor/v1/http_monitor.proto | 4 +- .../openstatus/monitor/v1/tcp_monitor.proto | 4 +- packages/proto/gen/openapi.yaml | 6 ++ .../openstatus/monitor/v1/dns_monitor_pb.ts | 2 +- .../openstatus/monitor/v1/http_monitor_pb.ts | 2 +- .../openstatus/monitor/v1/tcp_monitor_pb.ts | 2 +- .../src/monitor/__tests__/reads.test.ts | 61 +++++++++++++++++++ .../services/src/monitor/private-locations.ts | 14 ++++- 10 files changed, 97 insertions(+), 8 deletions(-) diff --git a/apps/server/static/openapi.yaml b/apps/server/static/openapi.yaml index 1a0dd4bde..718e30c4d 100644 --- a/apps/server/static/openapi.yaml +++ b/apps/server/static/openapi.yaml @@ -589,8 +589,10 @@ components: type: array items: type: string + readOnly: true title: private_location_ids description: IDs of private locations that run this monitor. Read-only. + readOnly: true title: DNSMonitor additionalProperties: false description: DNSMonitor defines the configuration for a DNS monitor. @@ -944,8 +946,10 @@ components: type: array items: type: string + readOnly: true title: private_location_ids description: IDs of private locations that run this monitor. Read-only. + readOnly: true title: HTTPMonitor additionalProperties: false description: HTTPMonitor defines the configuration for an HTTP monitor. @@ -1582,8 +1586,10 @@ components: type: array items: type: string + readOnly: true title: private_location_ids description: IDs of private locations that run this monitor. Read-only. + readOnly: true title: TCPMonitor additionalProperties: false description: TCPMonitor defines the configuration for a TCP monitor. diff --git a/packages/proto/api/openstatus/monitor/v1/dns_monitor.proto b/packages/proto/api/openstatus/monitor/v1/dns_monitor.proto index d1367e3db..9d5dc52dc 100644 --- a/packages/proto/api/openstatus/monitor/v1/dns_monitor.proto +++ b/packages/proto/api/openstatus/monitor/v1/dns_monitor.proto @@ -85,5 +85,7 @@ message DNSMonitor { MonitorStatus status = 14; // IDs of private locations that run this monitor. Read-only. - repeated string private_location_ids = 15; + repeated string private_location_ids = 15 [ + (gnostic.openapi.v3.property) = {read_only: true} + ]; } diff --git a/packages/proto/api/openstatus/monitor/v1/http_monitor.proto b/packages/proto/api/openstatus/monitor/v1/http_monitor.proto index 672feba0e..62eb0c107 100644 --- a/packages/proto/api/openstatus/monitor/v1/http_monitor.proto +++ b/packages/proto/api/openstatus/monitor/v1/http_monitor.proto @@ -143,5 +143,7 @@ message HTTPMonitor { MonitorStatus status = 20; // IDs of private locations that run this monitor. Read-only. - repeated string private_location_ids = 21; + repeated string private_location_ids = 21 [ + (gnostic.openapi.v3.property) = {read_only: true} + ]; } diff --git a/packages/proto/api/openstatus/monitor/v1/tcp_monitor.proto b/packages/proto/api/openstatus/monitor/v1/tcp_monitor.proto index 840006adc..435427566 100644 --- a/packages/proto/api/openstatus/monitor/v1/tcp_monitor.proto +++ b/packages/proto/api/openstatus/monitor/v1/tcp_monitor.proto @@ -81,5 +81,7 @@ message TCPMonitor { MonitorStatus status = 13; // IDs of private locations that run this monitor. Read-only. - repeated string private_location_ids = 14; + repeated string private_location_ids = 14 [ + (gnostic.openapi.v3.property) = {read_only: true} + ]; } diff --git a/packages/proto/gen/openapi.yaml b/packages/proto/gen/openapi.yaml index 1a0dd4bde..718e30c4d 100644 --- a/packages/proto/gen/openapi.yaml +++ b/packages/proto/gen/openapi.yaml @@ -589,8 +589,10 @@ components: type: array items: type: string + readOnly: true title: private_location_ids description: IDs of private locations that run this monitor. Read-only. + readOnly: true title: DNSMonitor additionalProperties: false description: DNSMonitor defines the configuration for a DNS monitor. @@ -944,8 +946,10 @@ components: type: array items: type: string + readOnly: true title: private_location_ids description: IDs of private locations that run this monitor. Read-only. + readOnly: true title: HTTPMonitor additionalProperties: false description: HTTPMonitor defines the configuration for an HTTP monitor. @@ -1582,8 +1586,10 @@ components: type: array items: type: string + readOnly: true title: private_location_ids description: IDs of private locations that run this monitor. Read-only. + readOnly: true title: TCPMonitor additionalProperties: false description: TCPMonitor defines the configuration for a TCP monitor. diff --git a/packages/proto/gen/ts/openstatus/monitor/v1/dns_monitor_pb.ts b/packages/proto/gen/ts/openstatus/monitor/v1/dns_monitor_pb.ts index 786ff4916..edb8e1591 100644 --- a/packages/proto/gen/ts/openstatus/monitor/v1/dns_monitor_pb.ts +++ b/packages/proto/gen/ts/openstatus/monitor/v1/dns_monitor_pb.ts @@ -18,7 +18,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file openstatus/monitor/v1/dns_monitor.proto. */ export const file_openstatus_monitor_v1_dns_monitor: GenFile = /*@__PURE__*/ - fileDesc("CidvcGVuc3RhdHVzL21vbml0b3IvdjEvZG5zX21vbml0b3IucHJvdG8SFW9wZW5zdGF0dXMubW9uaXRvci52MSKPBQoKRE5TTW9uaXRvchIKCgJpZBgBIAEoCRIzCgRuYW1lGAIgASgJQiW6Rxg6FhIURE5TIFJlc29sdXRpb24gQ2hlY2u6SAdyBRABGIACEikKA3VyaRgDIAEoCUIcukcPOg0SC2V4YW1wbGUuY29tukgHcgUQARiAEBJBCgtwZXJpb2RpY2l0eRgEIAEoDjIiLm9wZW5zdGF0dXMubW9uaXRvci52MS5QZXJpb2RpY2l0eUIIukgFggECIAASHAoHdGltZW91dBgFIAEoA0ILukgIIgYYwKkHKAASJQoLZGVncmFkZWRfYXQYBiABKANCC7pICCIGGMCpBygASACIAQESGAoFcmV0cnkYByABKANCCbpIBiIEGAooABJLChFyZWNvcmRfYXNzZXJ0aW9ucxgIIAMoCzImLm9wZW5zdGF0dXMubW9uaXRvci52MS5SZWNvcmRBc3NlcnRpb25CCLpIBZIBAhAKEh0KC2Rlc2NyaXB0aW9uGAkgASgJQgi6SAVyAxiACBIOCgZhY3RpdmUYCiABKAgSDgoGcHVibGljGAsgASgIEj8KB3JlZ2lvbnMYDCADKA4yHS5vcGVuc3RhdHVzLm1vbml0b3IudjEuUmVnaW9uQg+6SAySAQkQHCIFggECIAASQgoOb3Blbl90ZWxlbWV0cnkYDSABKAsyKi5vcGVuc3RhdHVzLm1vbml0b3IudjEuT3BlblRlbGVtZXRyeUNvbmZpZxI0CgZzdGF0dXMYDiABKA4yJC5vcGVuc3RhdHVzLm1vbml0b3IudjEuTW9uaXRvclN0YXR1cxIcChRwcml2YXRlX2xvY2F0aW9uX2lkcxgPIAMoCUIOCgxfZGVncmFkZWRfYXRCU1pRZ2l0aHViLmNvbS9vcGVuc3RhdHVzaHEvb3BlbnN0YXR1cy9wYWNrYWdlcy9wcm90by9vcGVuc3RhdHVzL21vbml0b3IvdjE7bW9uaXRvcnYxYgZwcm90bzM", [file_buf_validate_validate, file_gnostic_openapi_v3_annotations, file_openstatus_monitor_v1_assertions, file_openstatus_monitor_v1_http_monitor, file_openstatus_monitor_v1_monitor]); + fileDesc("CidvcGVuc3RhdHVzL21vbml0b3IvdjEvZG5zX21vbml0b3IucHJvdG8SFW9wZW5zdGF0dXMubW9uaXRvci52MSKWBQoKRE5TTW9uaXRvchIKCgJpZBgBIAEoCRIzCgRuYW1lGAIgASgJQiW6Rxg6FhIURE5TIFJlc29sdXRpb24gQ2hlY2u6SAdyBRABGIACEikKA3VyaRgDIAEoCUIcukcPOg0SC2V4YW1wbGUuY29tukgHcgUQARiAEBJBCgtwZXJpb2RpY2l0eRgEIAEoDjIiLm9wZW5zdGF0dXMubW9uaXRvci52MS5QZXJpb2RpY2l0eUIIukgFggECIAASHAoHdGltZW91dBgFIAEoA0ILukgIIgYYwKkHKAASJQoLZGVncmFkZWRfYXQYBiABKANCC7pICCIGGMCpBygASACIAQESGAoFcmV0cnkYByABKANCCbpIBiIEGAooABJLChFyZWNvcmRfYXNzZXJ0aW9ucxgIIAMoCzImLm9wZW5zdGF0dXMubW9uaXRvci52MS5SZWNvcmRBc3NlcnRpb25CCLpIBZIBAhAKEh0KC2Rlc2NyaXB0aW9uGAkgASgJQgi6SAVyAxiACBIOCgZhY3RpdmUYCiABKAgSDgoGcHVibGljGAsgASgIEj8KB3JlZ2lvbnMYDCADKA4yHS5vcGVuc3RhdHVzLm1vbml0b3IudjEuUmVnaW9uQg+6SAySAQkQHCIFggECIAASQgoOb3Blbl90ZWxlbWV0cnkYDSABKAsyKi5vcGVuc3RhdHVzLm1vbml0b3IudjEuT3BlblRlbGVtZXRyeUNvbmZpZxI0CgZzdGF0dXMYDiABKA4yJC5vcGVuc3RhdHVzLm1vbml0b3IudjEuTW9uaXRvclN0YXR1cxIjChRwcml2YXRlX2xvY2F0aW9uX2lkcxgPIAMoCUIFukcCGAFCDgoMX2RlZ3JhZGVkX2F0QlNaUWdpdGh1Yi5jb20vb3BlbnN0YXR1c2hxL29wZW5zdGF0dXMvcGFja2FnZXMvcHJvdG8vb3BlbnN0YXR1cy9tb25pdG9yL3YxO21vbml0b3J2MWIGcHJvdG8z", [file_buf_validate_validate, file_gnostic_openapi_v3_annotations, file_openstatus_monitor_v1_assertions, file_openstatus_monitor_v1_http_monitor, file_openstatus_monitor_v1_monitor]); /** * DNSMonitor defines the configuration for a DNS monitor. diff --git a/packages/proto/gen/ts/openstatus/monitor/v1/http_monitor_pb.ts b/packages/proto/gen/ts/openstatus/monitor/v1/http_monitor_pb.ts index c5f6da295..2aa29b77d 100644 --- a/packages/proto/gen/ts/openstatus/monitor/v1/http_monitor_pb.ts +++ b/packages/proto/gen/ts/openstatus/monitor/v1/http_monitor_pb.ts @@ -16,7 +16,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file openstatus/monitor/v1/http_monitor.proto. */ export const file_openstatus_monitor_v1_http_monitor: GenFile = /*@__PURE__*/ - fileDesc("CihvcGVuc3RhdHVzL21vbml0b3IvdjEvaHR0cF9tb25pdG9yLnByb3RvEhVvcGVuc3RhdHVzLm1vbml0b3IudjEiWgoHSGVhZGVycxIoCgNrZXkYASABKAlCG7pHEToPEg1BdXRob3JpemF0aW9uukgEcgIQARIlCgV2YWx1ZRgCIAEoCUIWukcTOhESD0JlYXJlciB0b2tlbjEyMyJsChNPcGVuVGVsZW1ldHJ5Q29uZmlnEhoKCGVuZHBvaW50GAEgASgJQgi6SAVyAxiAEBI5CgdoZWFkZXJzGAIgAygLMh4ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhlYWRlcnNCCLpIBZIBAhAUIp8ICgtIVFRQTW9uaXRvchIKCgJpZBgBIAEoCRI6CgRuYW1lGAIgASgJQiy6Rx86HRIbUHJvZHVjdGlvbiBBUEkgSGVhbHRoIENoZWNrukgHcgUQARiAAhI/CgN1cmwYAyABKAlCMrpHIjogEh5odHRwczovL2FwaS5leGFtcGxlLmNvbS9oZWFsdGi6SApyCBABGIAQiAEBEkEKC3BlcmlvZGljaXR5GAQgASgOMiIub3BlbnN0YXR1cy5tb25pdG9yLnYxLlBlcmlvZGljaXR5Qgi6SAWCAQIgABI7CgZtZXRob2QYBSABKA4yIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuSFRUUE1ldGhvZEIIukgFggECIAASJQoEYm9keRgGIAEoCUIXukcUOhISEHsia2V5IjogInZhbHVlIn0SHAoHdGltZW91dBgHIAEoA0ILukgIIgYYwKkHKAASJQoLZGVncmFkZWRfYXQYCCABKANCC7pICCIGGMCpBygASACIAQESGAoFcmV0cnkYCSABKANCCbpIBiIEGAooABIdChBmb2xsb3dfcmVkaXJlY3RzGAogASgISAGIAQESOQoHaGVhZGVycxgLIAMoCzIeLm9wZW5zdGF0dXMubW9uaXRvci52MS5IZWFkZXJzQgi6SAWSAQIQFBJUChZzdGF0dXNfY29kZV9hc3NlcnRpb25zGAwgAygLMioub3BlbnN0YXR1cy5tb25pdG9yLnYxLlN0YXR1c0NvZGVBc3NlcnRpb25CCLpIBZIBAhAKEkcKD2JvZHlfYXNzZXJ0aW9ucxgNIAMoCzIkLm9wZW5zdGF0dXMubW9uaXRvci52MS5Cb2R5QXNzZXJ0aW9uQgi6SAWSAQIQChJLChFoZWFkZXJfYXNzZXJ0aW9ucxgOIAMoCzImLm9wZW5zdGF0dXMubW9uaXRvci52MS5IZWFkZXJBc3NlcnRpb25CCLpIBZIBAhAKEh0KC2Rlc2NyaXB0aW9uGA8gASgJQgi6SAVyAxiACBIOCgZhY3RpdmUYECABKAgSDgoGcHVibGljGBEgASgIEj8KB3JlZ2lvbnMYEiADKA4yHS5vcGVuc3RhdHVzLm1vbml0b3IudjEuUmVnaW9uQg+6SAySAQkQHCIFggECIAASQgoOb3Blbl90ZWxlbWV0cnkYEyABKAsyKi5vcGVuc3RhdHVzLm1vbml0b3IudjEuT3BlblRlbGVtZXRyeUNvbmZpZxI0CgZzdGF0dXMYFCABKA4yJC5vcGVuc3RhdHVzLm1vbml0b3IudjEuTW9uaXRvclN0YXR1cxIcChRwcml2YXRlX2xvY2F0aW9uX2lkcxgVIAMoCUIOCgxfZGVncmFkZWRfYXRCEwoRX2ZvbGxvd19yZWRpcmVjdHMq9wEKCkhUVFBNZXRob2QSGwoXSFRUUF9NRVRIT0RfVU5TUEVDSUZJRUQQABITCg9IVFRQX01FVEhPRF9HRVQQARIUChBIVFRQX01FVEhPRF9QT1NUEAISFAoQSFRUUF9NRVRIT0RfSEVBRBADEhMKD0hUVFBfTUVUSE9EX1BVVBAEEhUKEUhUVFBfTUVUSE9EX1BBVENIEAUSFgoSSFRUUF9NRVRIT0RfREVMRVRFEAYSFQoRSFRUUF9NRVRIT0RfVFJBQ0UQBxIXChNIVFRQX01FVEhPRF9DT05ORUNUEAgSFwoTSFRUUF9NRVRIT0RfT1BUSU9OUxAJQlNaUWdpdGh1Yi5jb20vb3BlbnN0YXR1c2hxL29wZW5zdGF0dXMvcGFja2FnZXMvcHJvdG8vb3BlbnN0YXR1cy9tb25pdG9yL3YxO21vbml0b3J2MWIGcHJvdG8z", [file_buf_validate_validate, file_gnostic_openapi_v3_annotations, file_openstatus_monitor_v1_assertions, file_openstatus_monitor_v1_monitor]); + fileDesc("CihvcGVuc3RhdHVzL21vbml0b3IvdjEvaHR0cF9tb25pdG9yLnByb3RvEhVvcGVuc3RhdHVzLm1vbml0b3IudjEiWgoHSGVhZGVycxIoCgNrZXkYASABKAlCG7pHEToPEg1BdXRob3JpemF0aW9uukgEcgIQARIlCgV2YWx1ZRgCIAEoCUIWukcTOhESD0JlYXJlciB0b2tlbjEyMyJsChNPcGVuVGVsZW1ldHJ5Q29uZmlnEhoKCGVuZHBvaW50GAEgASgJQgi6SAVyAxiAEBI5CgdoZWFkZXJzGAIgAygLMh4ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhlYWRlcnNCCLpIBZIBAhAUIqYICgtIVFRQTW9uaXRvchIKCgJpZBgBIAEoCRI6CgRuYW1lGAIgASgJQiy6Rx86HRIbUHJvZHVjdGlvbiBBUEkgSGVhbHRoIENoZWNrukgHcgUQARiAAhI/CgN1cmwYAyABKAlCMrpHIjogEh5odHRwczovL2FwaS5leGFtcGxlLmNvbS9oZWFsdGi6SApyCBABGIAQiAEBEkEKC3BlcmlvZGljaXR5GAQgASgOMiIub3BlbnN0YXR1cy5tb25pdG9yLnYxLlBlcmlvZGljaXR5Qgi6SAWCAQIgABI7CgZtZXRob2QYBSABKA4yIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuSFRUUE1ldGhvZEIIukgFggECIAASJQoEYm9keRgGIAEoCUIXukcUOhISEHsia2V5IjogInZhbHVlIn0SHAoHdGltZW91dBgHIAEoA0ILukgIIgYYwKkHKAASJQoLZGVncmFkZWRfYXQYCCABKANCC7pICCIGGMCpBygASACIAQESGAoFcmV0cnkYCSABKANCCbpIBiIEGAooABIdChBmb2xsb3dfcmVkaXJlY3RzGAogASgISAGIAQESOQoHaGVhZGVycxgLIAMoCzIeLm9wZW5zdGF0dXMubW9uaXRvci52MS5IZWFkZXJzQgi6SAWSAQIQFBJUChZzdGF0dXNfY29kZV9hc3NlcnRpb25zGAwgAygLMioub3BlbnN0YXR1cy5tb25pdG9yLnYxLlN0YXR1c0NvZGVBc3NlcnRpb25CCLpIBZIBAhAKEkcKD2JvZHlfYXNzZXJ0aW9ucxgNIAMoCzIkLm9wZW5zdGF0dXMubW9uaXRvci52MS5Cb2R5QXNzZXJ0aW9uQgi6SAWSAQIQChJLChFoZWFkZXJfYXNzZXJ0aW9ucxgOIAMoCzImLm9wZW5zdGF0dXMubW9uaXRvci52MS5IZWFkZXJBc3NlcnRpb25CCLpIBZIBAhAKEh0KC2Rlc2NyaXB0aW9uGA8gASgJQgi6SAVyAxiACBIOCgZhY3RpdmUYECABKAgSDgoGcHVibGljGBEgASgIEj8KB3JlZ2lvbnMYEiADKA4yHS5vcGVuc3RhdHVzLm1vbml0b3IudjEuUmVnaW9uQg+6SAySAQkQHCIFggECIAASQgoOb3Blbl90ZWxlbWV0cnkYEyABKAsyKi5vcGVuc3RhdHVzLm1vbml0b3IudjEuT3BlblRlbGVtZXRyeUNvbmZpZxI0CgZzdGF0dXMYFCABKA4yJC5vcGVuc3RhdHVzLm1vbml0b3IudjEuTW9uaXRvclN0YXR1cxIjChRwcml2YXRlX2xvY2F0aW9uX2lkcxgVIAMoCUIFukcCGAFCDgoMX2RlZ3JhZGVkX2F0QhMKEV9mb2xsb3dfcmVkaXJlY3RzKvcBCgpIVFRQTWV0aG9kEhsKF0hUVFBfTUVUSE9EX1VOU1BFQ0lGSUVEEAASEwoPSFRUUF9NRVRIT0RfR0VUEAESFAoQSFRUUF9NRVRIT0RfUE9TVBACEhQKEEhUVFBfTUVUSE9EX0hFQUQQAxITCg9IVFRQX01FVEhPRF9QVVQQBBIVChFIVFRQX01FVEhPRF9QQVRDSBAFEhYKEkhUVFBfTUVUSE9EX0RFTEVURRAGEhUKEUhUVFBfTUVUSE9EX1RSQUNFEAcSFwoTSFRUUF9NRVRIT0RfQ09OTkVDVBAIEhcKE0hUVFBfTUVUSE9EX09QVElPTlMQCUJTWlFnaXRodWIuY29tL29wZW5zdGF0dXNocS9vcGVuc3RhdHVzL3BhY2thZ2VzL3Byb3RvL29wZW5zdGF0dXMvbW9uaXRvci92MTttb25pdG9ydjFiBnByb3RvMw", [file_buf_validate_validate, file_gnostic_openapi_v3_annotations, file_openstatus_monitor_v1_assertions, file_openstatus_monitor_v1_monitor]); /** * Headers represents a key-value pair for HTTP headers. diff --git a/packages/proto/gen/ts/openstatus/monitor/v1/tcp_monitor_pb.ts b/packages/proto/gen/ts/openstatus/monitor/v1/tcp_monitor_pb.ts index 110ef0503..5148cbc86 100644 --- a/packages/proto/gen/ts/openstatus/monitor/v1/tcp_monitor_pb.ts +++ b/packages/proto/gen/ts/openstatus/monitor/v1/tcp_monitor_pb.ts @@ -16,7 +16,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file openstatus/monitor/v1/tcp_monitor.proto. */ export const file_openstatus_monitor_v1_tcp_monitor: GenFile = /*@__PURE__*/ - fileDesc("CidvcGVuc3RhdHVzL21vbml0b3IvdjEvdGNwX21vbml0b3IucHJvdG8SFW9wZW5zdGF0dXMubW9uaXRvci52MSLVBAoKVENQTW9uaXRvchIKCgJpZBgBIAEoCRI4CgRuYW1lGAIgASgJQiq6Rx06GxIZRGF0YWJhc2UgQ29ubmVjdGlvbiBDaGVja7pIB3IFEAEYgAISNwoDdXJpGAMgASgJQiq6Rx06GxIZdGNwOi8vZGIuZXhhbXBsZS5jb206NTQzMrpIB3IFEAEYgBASQQoLcGVyaW9kaWNpdHkYBCABKA4yIi5vcGVuc3RhdHVzLm1vbml0b3IudjEuUGVyaW9kaWNpdHlCCLpIBYIBAiAAEhwKB3RpbWVvdXQYBSABKANCC7pICCIGGMCpBygAEiUKC2RlZ3JhZGVkX2F0GAYgASgDQgu6SAgiBhjAqQcoAEgAiAEBEhgKBXJldHJ5GAcgASgDQgm6SAYiBBgKKAASHQoLZGVzY3JpcHRpb24YCCABKAlCCLpIBXIDGIAIEg4KBmFjdGl2ZRgJIAEoCBIOCgZwdWJsaWMYCiABKAgSPwoHcmVnaW9ucxgLIAMoDjIdLm9wZW5zdGF0dXMubW9uaXRvci52MS5SZWdpb25CD7pIDJIBCRAcIgWCAQIgABJCCg5vcGVuX3RlbGVtZXRyeRgMIAEoCzIqLm9wZW5zdGF0dXMubW9uaXRvci52MS5PcGVuVGVsZW1ldHJ5Q29uZmlnEjQKBnN0YXR1cxgNIAEoDjIkLm9wZW5zdGF0dXMubW9uaXRvci52MS5Nb25pdG9yU3RhdHVzEhwKFHByaXZhdGVfbG9jYXRpb25faWRzGA4gAygJQg4KDF9kZWdyYWRlZF9hdEJTWlFnaXRodWIuY29tL29wZW5zdGF0dXNocS9vcGVuc3RhdHVzL3BhY2thZ2VzL3Byb3RvL29wZW5zdGF0dXMvbW9uaXRvci92MTttb25pdG9ydjFiBnByb3RvMw", [file_buf_validate_validate, file_gnostic_openapi_v3_annotations, file_openstatus_monitor_v1_http_monitor, file_openstatus_monitor_v1_monitor]); + fileDesc("CidvcGVuc3RhdHVzL21vbml0b3IvdjEvdGNwX21vbml0b3IucHJvdG8SFW9wZW5zdGF0dXMubW9uaXRvci52MSLcBAoKVENQTW9uaXRvchIKCgJpZBgBIAEoCRI4CgRuYW1lGAIgASgJQiq6Rx06GxIZRGF0YWJhc2UgQ29ubmVjdGlvbiBDaGVja7pIB3IFEAEYgAISNwoDdXJpGAMgASgJQiq6Rx06GxIZdGNwOi8vZGIuZXhhbXBsZS5jb206NTQzMrpIB3IFEAEYgBASQQoLcGVyaW9kaWNpdHkYBCABKA4yIi5vcGVuc3RhdHVzLm1vbml0b3IudjEuUGVyaW9kaWNpdHlCCLpIBYIBAiAAEhwKB3RpbWVvdXQYBSABKANCC7pICCIGGMCpBygAEiUKC2RlZ3JhZGVkX2F0GAYgASgDQgu6SAgiBhjAqQcoAEgAiAEBEhgKBXJldHJ5GAcgASgDQgm6SAYiBBgKKAASHQoLZGVzY3JpcHRpb24YCCABKAlCCLpIBXIDGIAIEg4KBmFjdGl2ZRgJIAEoCBIOCgZwdWJsaWMYCiABKAgSPwoHcmVnaW9ucxgLIAMoDjIdLm9wZW5zdGF0dXMubW9uaXRvci52MS5SZWdpb25CD7pIDJIBCRAcIgWCAQIgABJCCg5vcGVuX3RlbGVtZXRyeRgMIAEoCzIqLm9wZW5zdGF0dXMubW9uaXRvci52MS5PcGVuVGVsZW1ldHJ5Q29uZmlnEjQKBnN0YXR1cxgNIAEoDjIkLm9wZW5zdGF0dXMubW9uaXRvci52MS5Nb25pdG9yU3RhdHVzEiMKFHByaXZhdGVfbG9jYXRpb25faWRzGA4gAygJQgW6RwIYAUIOCgxfZGVncmFkZWRfYXRCU1pRZ2l0aHViLmNvbS9vcGVuc3RhdHVzaHEvb3BlbnN0YXR1cy9wYWNrYWdlcy9wcm90by9vcGVuc3RhdHVzL21vbml0b3IvdjE7bW9uaXRvcnYxYgZwcm90bzM", [file_buf_validate_validate, file_gnostic_openapi_v3_annotations, file_openstatus_monitor_v1_http_monitor, file_openstatus_monitor_v1_monitor]); /** * TCPMonitor defines the configuration for a TCP monitor. diff --git a/packages/services/src/monitor/__tests__/reads.test.ts b/packages/services/src/monitor/__tests__/reads.test.ts index 0a4725808..0b872a5b6 100644 --- a/packages/services/src/monitor/__tests__/reads.test.ts +++ b/packages/services/src/monitor/__tests__/reads.test.ts @@ -1,4 +1,6 @@ +import { eq } from "@openstatus/db"; import { + monitor, monitorStatusTable, privateLocation, privateLocationToMonitors, @@ -534,6 +536,65 @@ describe("getPrivateLocationIdsByMonitor", () => { }); }); + test("excludes attachments whose monitor was soft-deleted", async () => { + await withTestTransaction(async (tx) => { + const ctx: ServiceContext = { ...teamCtx, db: tx }; + const mon = await createHttpMonitor(ctx, "deleted-monitor"); + + const [pl] = await tx + .insert(privateLocation) + .values({ + workspaceId: teamCtx.workspace.id, + name: `${TEST_PREFIX}-deleted-monitor-pl`, + token: `${TEST_PREFIX}-deleted-monitor-pl-token`, + }) + .returning(); + await tx + .insert(privateLocationToMonitors) + .values({ privateLocationId: pl.id, monitorId: mon.id }); + await tx + .update(monitor) + .set({ deletedAt: new Date() }) + .where(eq(monitor.id, mon.id)); + + const map = await getPrivateLocationIdsByMonitor({ + ctx, + input: { monitorIds: [mon.id] }, + }); + + expect(map.has(mon.id)).toBe(false); + }); + }); + + test("excludes attachments whose monitor belongs to another workspace", async () => { + await withTestTransaction(async (tx) => { + // Legacy/corrupt pivot: a team private location wired to a free-workspace + // monitor. The workspace-scoped monitor join must drop it. + const foreignMon = await createHttpMonitor( + { ...freeCtx, db: tx }, + "foreign-monitor", + ); + const [pl] = await tx + .insert(privateLocation) + .values({ + workspaceId: teamCtx.workspace.id, + name: `${TEST_PREFIX}-foreign-monitor-pl`, + token: `${TEST_PREFIX}-foreign-monitor-pl-token`, + }) + .returning(); + await tx + .insert(privateLocationToMonitors) + .values({ privateLocationId: pl.id, monitorId: foreignMon.id }); + + const map = await getPrivateLocationIdsByMonitor({ + ctx: { ...teamCtx, db: tx }, + input: { monitorIds: [foreignMon.id] }, + }); + + expect(map.has(foreignMon.id)).toBe(false); + }); + }); + test("returns an empty map for empty input", async () => { await withTestTransaction(async (tx) => { const map = await getPrivateLocationIdsByMonitor({ diff --git a/packages/services/src/monitor/private-locations.ts b/packages/services/src/monitor/private-locations.ts index 8aa59ccd9..d64e4a7d1 100644 --- a/packages/services/src/monitor/private-locations.ts +++ b/packages/services/src/monitor/private-locations.ts @@ -1,5 +1,9 @@ import { and, eq, inArray, isNull } from "@openstatus/db"; -import { privateLocation, privateLocationToMonitors } from "@openstatus/db/src/schema"; +import { + monitor, + privateLocation, + privateLocationToMonitors, +} from "@openstatus/db/src/schema"; import { type ServiceContext, getReadDb } from "../context"; import { GetPrivateLocationIdsByMonitorInput } from "./schemas"; @@ -30,12 +34,18 @@ export async function getPrivateLocationIdsByMonitor(args: { privateLocation, eq(privateLocationToMonitors.privateLocationId, privateLocation.id), ) + .innerJoin(monitor, eq(privateLocationToMonitors.monitorId, monitor.id)) .where( and( inArray(privateLocationToMonitors.monitorId, ids), + // Scope both sides to the workspace so a legacy/corrupt pivot row can't + // surface a foreign private location or monitor. eq(privateLocation.workspaceId, args.ctx.workspace.id), - // Match the checker: a soft-deleted attachment no longer runs the monitor. + eq(monitor.workspaceId, args.ctx.workspace.id), + // Match the checker/monitor reads: a soft-deleted attachment or monitor + // no longer runs the monitor. isNull(privateLocationToMonitors.deletedAt), + isNull(monitor.deletedAt), ), ) .all(); -- 2.51.2