Multi-tenancy boundary
Главный security-инвариант: каждый PromQL-запрос проходит через `composeQuery` или `rewritePromQL`. Оба внедряют organization_id как mandatory label matcher. Raw-query path для пользовательского input отсутствует.
composeQuery
Принимает bare metric name + filters → строит PromQL вида:
metric{organization_id="<org-id>", host="web-01"}Mandatory filters всегда побеждают. Optional (из URL params) добавляются если не конфликтуют.
rewritePromQL
Парсит пользовательский PromQL через prometheus/promql/parser, обходит AST через parser.Inspect. На каждом VectorSelector и MatrixSelector LabelMatchers заменяются на merged set, где organization_id побеждает.
Пользователь не может «обойти» organization_id даже явным указанием в запросе — rewrite перезаписывает.