From 8fc84433cd9a75750b1f26854aa8332211754ce7 Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 12:39:41 +0000 Subject: [PATCH 01/10] Add storage toggle to the telemetry schema BrowserTelemetryConfig gains a storage block whose enabled flag defaults to true when omitted, so existing callers keep today's behavior. PUT and PATCH /telemetry gain a 409 for disabling storage on an instance that has already started it. Co-Authored-By: Claude Fable 5.1 --- server/lib/oapi/oapi.go | 1325 ++++++++++++++++++++------------------- server/openapi.yaml | 31 +- 2 files changed, 714 insertions(+), 642 deletions(-) diff --git a/server/lib/oapi/oapi.go b/server/lib/oapi/oapi.go index 8921b1a9..e405df8e 100644 --- a/server/lib/oapi/oapi.go +++ b/server/lib/oapi/oapi.go @@ -6154,6 +6154,9 @@ type BrowserTelemetryConfig struct { // Export Forwarding of captured telemetry to an external destination. Independent of what is captured: export is off unless explicitly enabled here, even when an export destination is configured. In a PUT (full replace) an omitted export block resets export to off, the same as omitted categories turn off; in a PATCH an omitted field leaves the current setting unchanged. Export *BrowserTelemetryExportConfig `json:"export,omitempty"` + + // Storage Durable storage of captured telemetry in Kernel's event store. On by default, so a caller that omits this block keeps today's behavior: in a PUT (full replace) an omitted block means enabled, unlike `export`, whose omitted block means off; in a PATCH an omitted field leaves the current setting unchanged. Storage opens with the first capture session that has it enabled and stays open for the life of the instance, so once it has started a request that disables it is rejected with 409. + Storage *BrowserTelemetryStorageConfig `json:"storage,omitempty"` } // BrowserTelemetryControlConfig Configuration for the control category. Same `enabled` semantics as any other category, plus settings for the browser-control commands the CDP proxy reports. @@ -6177,6 +6180,12 @@ type BrowserTelemetryOTLPExportConfig struct { Enabled *bool `json:"enabled,omitempty"` } +// BrowserTelemetryStorageConfig Durable storage of captured telemetry in Kernel's event store. On by default, so a caller that omits this block keeps today's behavior: in a PUT (full replace) an omitted block means enabled, unlike `export`, whose omitted block means off; in a PATCH an omitted field leaves the current setting unchanged. Storage opens with the first capture session that has it enabled and stays open for the life of the instance, so once it has started a request that disables it is rejected with 409. +type BrowserTelemetryStorageConfig struct { + // Enabled Whether captured telemetry is written to Kernel's event store. Defaults to true. Set false to keep events on the live stream and any enabled export destination only. Cannot be set false on an instance that has already started storage (409). + Enabled *bool `json:"enabled,omitempty"` +} + // ChromiumConfigureError Failure from batched chromium configure — includes which phase failed. type ChromiumConfigureError struct { Message string `json:"message"` @@ -15054,6 +15063,7 @@ type PatchTelemetryResponse struct { JSON200 *TelemetryState JSON400 *BadRequestError JSON404 *NotFoundError + JSON409 *ConflictError JSON500 *InternalError } @@ -15079,6 +15089,7 @@ type PutTelemetryResponse struct { JSON200 *TelemetryState JSON201 *TelemetryState JSON400 *BadRequestError + JSON409 *ConflictError JSON500 *InternalError } @@ -18108,6 +18119,13 @@ func ParsePatchTelemetryResponse(rsp *http.Response) (*PatchTelemetryResponse, e } response.JSON404 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest ConflictError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: var dest InternalError if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -18155,6 +18173,13 @@ func ParsePutTelemetryResponse(rsp *http.Response) (*PutTelemetryResponse, error } response.JSON400 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest ConflictError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: var dest InternalError if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -22619,6 +22644,15 @@ func (response PatchTelemetry404JSONResponse) VisitPatchTelemetryResponse(w http return json.NewEncoder(w).Encode(response) } +type PatchTelemetry409JSONResponse struct{ ConflictErrorJSONResponse } + +func (response PatchTelemetry409JSONResponse) VisitPatchTelemetryResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(409) + + return json.NewEncoder(w).Encode(response) +} + type PatchTelemetry500JSONResponse struct{ InternalErrorJSONResponse } func (response PatchTelemetry500JSONResponse) VisitPatchTelemetryResponse(w http.ResponseWriter) error { @@ -22663,6 +22697,15 @@ func (response PutTelemetry400JSONResponse) VisitPutTelemetryResponse(w http.Res return json.NewEncoder(w).Encode(response) } +type PutTelemetry409JSONResponse struct{ ConflictErrorJSONResponse } + +func (response PutTelemetry409JSONResponse) VisitPutTelemetryResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(409) + + return json.NewEncoder(w).Encode(response) +} + type PutTelemetry500JSONResponse struct{ InternalErrorJSONResponse } func (response PutTelemetry500JSONResponse) VisitPutTelemetryResponse(w http.ResponseWriter) error { @@ -24837,647 +24880,647 @@ func (sh *strictHandler) GetWebMCPTools(w http.ResponseWriter, r *http.Request) // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "+vTp/wUAAP//x5vyWueVAwA=", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/server/openapi.yaml b/server/openapi.yaml index dd305667..3f678f35 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -1547,7 +1547,9 @@ paths: previously configured; returns 200 if it was. Selection is opt-in: a request that enables no categories (a browser config with nothing set to true, or every category disabled) clears the configuration; this is - idempotent when telemetry is not configured. + idempotent when telemetry is not configured. Returns 409 when + `storage.enabled` is false on an instance that has already started + storage; the configuration is left unchanged. operationId: putTelemetry x-telemetry-category: platform requestBody: @@ -1571,6 +1573,8 @@ paths: $ref: "#/components/schemas/TelemetryState" "400": $ref: "#/components/responses/BadRequestError" + "409": + $ref: "#/components/responses/ConflictError" "500": $ref: "#/components/responses/InternalError" patch: @@ -1580,6 +1584,8 @@ paths: set in the request body are changed; omitted categories retain their current settings. Returns 404 if telemetry is not configured. Setting every configurable category to enabled: false clears the configuration. + Returns 409 when `storage.enabled` is false on an instance that has + already started storage; the configuration is left unchanged. operationId: patchTelemetry x-telemetry-category: platform requestBody: @@ -1599,6 +1605,8 @@ paths: $ref: "#/components/responses/BadRequestError" "404": $ref: "#/components/responses/NotFoundError" + "409": + $ref: "#/components/responses/ConflictError" "500": $ref: "#/components/responses/InternalError" /telemetry/events: @@ -1870,6 +1878,8 @@ components: $ref: "#/components/schemas/BrowserTelemetryCategoriesConfig" export: $ref: "#/components/schemas/BrowserTelemetryExportConfig" + storage: + $ref: "#/components/schemas/BrowserTelemetryStorageConfig" additionalProperties: false BrowserTelemetryExportConfig: type: object @@ -1894,6 +1904,25 @@ components: destination. Off by default. Has no effect (export stays inactive) when no export destination is configured. additionalProperties: false + BrowserTelemetryStorageConfig: + type: object + description: > + Durable storage of captured telemetry in Kernel's event store. On by + default, so a caller that omits this block keeps today's behavior: in a + PUT (full replace) an omitted block means enabled, unlike `export`, + whose omitted block means off; in a PATCH an omitted field leaves the + current setting unchanged. Storage opens with the first capture session + that has it enabled and stays open for the life of the instance, so + once it has started a request that disables it is rejected with 409. + properties: + enabled: + type: boolean + description: > + Whether captured telemetry is written to Kernel's event store. + Defaults to true. Set false to keep events on the live stream and + any enabled export destination only. Cannot be set false on an + instance that has already started storage (409). + additionalProperties: false BrowserTelemetryCategoriesConfig: type: object description: Per-category telemetry capture settings for browser events. From 39572a0d526f25ba1696e561b96b2e2e536ab291 Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 12:43:35 +0000 Subject: [PATCH 02/10] Carry the storage toggle through the telemetry config TelemetryConfig gains StoreS2. PUT reads it with an omitted block meaning true, PATCH leaves an omitted field unchanged, and every response echoes it, including the cleared config, which keeps the toggle the clearing request carried. Nothing acts on it yet. Co-Authored-By: Claude Fable 5.1 --- server/cmd/api/api/telemetry.go | 62 ++++++++---- server/cmd/api/api/telemetry_test.go | 127 +++++++++++++++++++++++++ server/lib/telemetry/telemetry.go | 15 ++- server/lib/telemetry/telemetry_test.go | 15 +++ 4 files changed, 199 insertions(+), 20 deletions(-) diff --git a/server/cmd/api/api/telemetry.go b/server/cmd/api/api/telemetry.go index c752fd19..680cfc61 100644 --- a/server/cmd/api/api/telemetry.go +++ b/server/cmd/api/api/telemetry.go @@ -52,7 +52,7 @@ func (s *ApiService) PutTelemetry(ctx context.Context, req oapi.PutTelemetryRequ s.telemetrySession.Stop() s.stopTelemetryState() } - return oapi.PutTelemetry200JSONResponse(s.stoppedTelemetryResponse()), nil + return oapi.PutTelemetry200JSONResponse(s.stoppedTelemetryResponse(cfg.StoreS2)), nil } // Commit the config first so the filter is live before the collector emits, @@ -91,9 +91,9 @@ func (s *ApiService) PatchTelemetry(ctx context.Context, req oapi.PatchTelemetry return oapi.PatchTelemetry404JSONResponse{NotFoundErrorJSONResponse: oapi.NotFoundErrorJSONResponse{Message: "telemetry is not configured"}}, nil } - // Nothing to merge when neither the category block nor the export toggle is + // Nothing to merge when neither the category block nor a sink toggle is // present; skip the reconcile and echo current state, as before. - if req.Body == nil || (req.Body.Browser == nil && req.Body.Export == nil) { + if req.Body == nil || (req.Body.Browser == nil && req.Body.Export == nil && req.Body.Storage == nil) { return oapi.PatchTelemetry200JSONResponse(s.buildTelemetryResponse()), nil } @@ -102,7 +102,7 @@ func (s *ApiService) PatchTelemetry(ctx context.Context, req oapi.PatchTelemetry if allDisabled { s.telemetrySession.Stop() s.stopTelemetryState() - return oapi.PatchTelemetry200JSONResponse(s.stoppedTelemetryResponse()), nil + return oapi.PatchTelemetry200JSONResponse(s.stoppedTelemetryResponse(cfg.StoreS2)), nil } // Commit first so the filter is live before the collector emits, then @@ -200,11 +200,12 @@ func (s *ApiService) buildTelemetryResponse() oapi.TelemetryState { return resp } -// stoppedTelemetryResponse reports the cleared configuration. Seq and the -// dropped count are process-scoped, so they survive a session ending. -func (s *ApiService) stoppedTelemetryResponse() oapi.TelemetryState { +// stoppedTelemetryResponse reports the cleared configuration, echoing the +// storage toggle the clearing request carried. Seq and the dropped count are +// process-scoped, so they survive a session ending. +func (s *ApiService) stoppedTelemetryResponse(storeS2 bool) oapi.TelemetryState { return oapi.TelemetryState{ - Config: disabledConfig(), + Config: disabledConfig(storeS2), Seq: int64(s.telemetrySession.Seq()), DroppedEvents: lo.ToPtr(int64(s.telemetrySession.DroppedEvents())), } @@ -276,11 +277,12 @@ func containsCategory(cats []oapi.TelemetryEventCategory, target oapi.TelemetryE // config, whether the result is empty (stop signal), and any error. func telemetryConfigFromOAPI(cfg *oapi.BrowserTelemetryConfig) (telemetry.TelemetryConfig, bool, error) { exportOTLP := exportOTLPFromOAPI(cfg) + storeS2 := storeS2FromOAPI(cfg) if cfg == nil || cfg.Browser == nil { // No per-category settings: resolve to the explicit default set so the // effective categories are known before the collector is reconciled. cats := append([]oapi.TelemetryEventCategory(nil), events.DefaultCategories...) - return telemetry.TelemetryConfig{Categories: cats, ExportOTLP: exportOTLP}, false, nil + return telemetry.TelemetryConfig{Categories: cats, ExportOTLP: exportOTLP, StoreS2: storeS2}, false, nil } cats := make([]oapi.TelemetryEventCategory, 0, len(events.UserCategories)) @@ -290,11 +292,14 @@ func telemetryConfigFromOAPI(cfg *oapi.BrowserTelemetryConfig) (telemetry.Teleme } } if len(cats) == 0 { - return telemetry.TelemetryConfig{}, true, nil + // The stop signal keeps the storage toggle: a clear is still checked + // against storage that has already started, and echoes what it asked for. + return telemetry.TelemetryConfig{StoreS2: storeS2}, true, nil } return telemetry.TelemetryConfig{ Categories: cats, ExportOTLP: exportOTLP, + StoreS2: storeS2, ExcludedCdpMethods: excludedCdpMethodsFromOAPI(cfg), }, false, nil } @@ -308,6 +313,16 @@ func exportOTLPFromOAPI(cfg *oapi.BrowserTelemetryConfig) bool { return false } +// storeS2FromOAPI reads the storage toggle from a config, defaulting to true +// (on) when the storage block is omitted: the opposite of export, so callers +// that predate the field keep storing. +func storeS2FromOAPI(cfg *oapi.BrowserTelemetryConfig) bool { + if cfg != nil && cfg.Storage != nil && cfg.Storage.Enabled != nil { + return *cfg.Storage.Enabled + } + return true +} + // mergeTelemetryConfig applies patch overrides onto current, returning the merged config and // whether every configurable category ended up disabled (stop signal). Only categories with an // explicit Enabled field in patch are changed; omitted categories keep their current state. @@ -333,11 +348,16 @@ func mergeTelemetryConfig(current telemetry.TelemetryConfig, patch *oapi.Browser } } - // Export follows the same patch semantics: an omitted toggle is unchanged. + // Export and storage follow the same patch semantics: an omitted toggle is + // unchanged. exportOTLP := current.ExportOTLP if patch.Export != nil && patch.Export.Otlp != nil && patch.Export.Otlp.Enabled != nil { exportOTLP = *patch.Export.Otlp.Enabled } + storeS2 := current.StoreS2 + if patch.Storage != nil && patch.Storage.Enabled != nil { + storeS2 = *patch.Storage.Enabled + } // So do the cdp_command exclusions: an omitted list is unchanged, an empty // one clears them. @@ -347,17 +367,18 @@ func mergeTelemetryConfig(current telemetry.TelemetryConfig, patch *oapi.Browser } if len(active) == 0 { - return telemetry.TelemetryConfig{}, true + return telemetry.TelemetryConfig{StoreS2: storeS2}, true } cats := make([]oapi.TelemetryEventCategory, 0, len(active)) for c := range active { cats = append(cats, c) } - return telemetry.TelemetryConfig{Categories: cats, ExportOTLP: exportOTLP, ExcludedCdpMethods: excluded}, false + return telemetry.TelemetryConfig{Categories: cats, ExportOTLP: exportOTLP, StoreS2: storeS2, ExcludedCdpMethods: excluded}, false } -// disabledConfig returns a BrowserTelemetryConfig with every configurable category explicitly disabled. -func disabledConfig() oapi.BrowserTelemetryConfig { +// disabledConfig returns a BrowserTelemetryConfig with every configurable +// category explicitly disabled and the given storage toggle. +func disabledConfig(storeS2 bool) oapi.BrowserTelemetryConfig { off := func() *oapi.BrowserTelemetryCategoryConfig { return &oapi.BrowserTelemetryCategoryConfig{Enabled: lo.ToPtr(false)} } @@ -374,7 +395,8 @@ func disabledConfig() oapi.BrowserTelemetryConfig { Screenshot: off(), Captcha: off(), }, - Export: exportConfigToOAPI(false), + Export: exportConfigToOAPI(false), + Storage: storageConfigToOAPI(storeS2), } } @@ -385,6 +407,11 @@ func exportConfigToOAPI(enabled bool) *oapi.BrowserTelemetryExportConfig { } } +// storageConfigToOAPI renders the storage toggle for API responses. +func storageConfigToOAPI(enabled bool) *oapi.BrowserTelemetryStorageConfig { + return &oapi.BrowserTelemetryStorageConfig{Enabled: lo.ToPtr(enabled)} +} + // telemetryConfigToOAPI converts a telemetry.TelemetryConfig to an oapi.BrowserTelemetryConfig // suitable for API responses. The auto-managed Monitor category is not represented. func telemetryConfigToOAPI(cfg telemetry.TelemetryConfig) oapi.BrowserTelemetryConfig { @@ -410,6 +437,7 @@ func telemetryConfigToOAPI(cfg telemetry.TelemetryConfig) oapi.BrowserTelemetryC Screenshot: enabled(events.Screenshot), Captcha: enabled(events.Captcha), }, - Export: exportConfigToOAPI(cfg.ExportOTLP), + Export: exportConfigToOAPI(cfg.ExportOTLP), + Storage: storageConfigToOAPI(cfg.StoreS2), } } diff --git a/server/cmd/api/api/telemetry_test.go b/server/cmd/api/api/telemetry_test.go index 3e11e4fd..4377dac5 100644 --- a/server/cmd/api/api/telemetry_test.go +++ b/server/cmd/api/api/telemetry_test.go @@ -13,6 +13,7 @@ import ( oapi "github.com/kernel/kernel-images/server/lib/oapi" "github.com/kernel/kernel-images/server/lib/recorder" "github.com/kernel/kernel-images/server/lib/scaletozero" + "github.com/kernel/kernel-images/server/lib/telemetry" "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -720,3 +721,129 @@ func TestTelemetryStateStaysCompatibleWithOlderImages(t *testing.T) { assert.True(t, *cfg.Browser.Control.Enabled) assert.Nil(t, cfg.Browser.Control.Cdp) } + +func TestTelemetryStorageToggle(t *testing.T) { + ctx := context.Background() + tr, fa := true, false + storageOff := func() *oapi.BrowserTelemetryConfig { + return &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Network: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &fa}, + } + } + storageOmitted := func() *oapi.BrowserTelemetryConfig { + return &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Network: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + } + } + storageOf := func(t *testing.T, cfg oapi.BrowserTelemetryConfig) bool { + t.Helper() + require.NotNil(t, cfg.Storage, "storage must always be echoed") + require.NotNil(t, cfg.Storage.Enabled) + return *cfg.Storage.Enabled + } + + t.Run("omitted storage means on", func(t *testing.T) { + cfg, allDisabled, err := telemetryConfigFromOAPI(nil) + require.NoError(t, err) + assert.False(t, allDisabled) + assert.True(t, cfg.StoreS2) + + cfg, _, err = telemetryConfigFromOAPI(storageOmitted()) + require.NoError(t, err) + assert.True(t, cfg.StoreS2) + + cfg, _, err = telemetryConfigFromOAPI(storageOff()) + require.NoError(t, err) + assert.False(t, cfg.StoreS2) + }) + + t.Run("a clear keeps the storage toggle it carried", func(t *testing.T) { + cfg, allDisabled, err := telemetryConfigFromOAPI(&oapi.BrowserTelemetryConfig{ + Browser: allCategoriesDisabled(), + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &fa}, + }) + require.NoError(t, err) + assert.True(t, allDisabled) + assert.False(t, cfg.StoreS2) + + // The zero value is off, so the positive case is what proves the + // toggle is carried rather than dropped. + cfg, allDisabled, err = telemetryConfigFromOAPI(&oapi.BrowserTelemetryConfig{Browser: allCategoriesDisabled()}) + require.NoError(t, err) + assert.True(t, allDisabled) + assert.True(t, cfg.StoreS2) + + for _, current := range []bool{false, true} { + merged, allDisabled := mergeTelemetryConfig(telemetry.TelemetryConfig{Categories: events.DefaultCategories, StoreS2: current}, &oapi.BrowserTelemetryConfig{Browser: allCategoriesDisabled()}) + assert.True(t, allDisabled) + assert.Equal(t, current, merged.StoreS2, "an all-disabled patch must keep the current storage toggle") + } + }) + + t.Run("patch leaves an omitted toggle alone", func(t *testing.T) { + current := telemetry.TelemetryConfig{Categories: []oapi.TelemetryEventCategory{events.Network}, StoreS2: false} + merged, _ := mergeTelemetryConfig(current, &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Console: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + }) + assert.False(t, merged.StoreS2) + + merged, _ = mergeTelemetryConfig(current, &oapi.BrowserTelemetryConfig{ + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &tr}, + }) + assert.True(t, merged.StoreS2) + }) + + t.Run("GET, PUT and PATCH echo storage exactly", func(t *testing.T) { + svc := newTestService(t, newMockRecordManager()) + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: storageOff()}) + require.NoError(t, err) + r201, ok := resp.(oapi.PutTelemetry201JSONResponse) + require.True(t, ok, "expected 201, got %T", resp) + assert.False(t, storageOf(t, r201.Config)) + + got, err := svc.GetTelemetry(ctx, oapi.GetTelemetryRequestObject{}) + require.NoError(t, err) + assert.False(t, storageOf(t, got.(oapi.GetTelemetry200JSONResponse).Config)) + + // A category-only PATCH is not a storage change. + presp, err := svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Console: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + }}) + require.NoError(t, err) + assert.False(t, storageOf(t, presp.(oapi.PatchTelemetry200JSONResponse).Config)) + + // A storage-only PATCH is applied, not treated as an empty body. + presp, err = svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &tr}, + }}) + require.NoError(t, err) + assert.True(t, storageOf(t, presp.(oapi.PatchTelemetry200JSONResponse).Config)) + assert.True(t, svc.telemetrySession.Config().StoreS2) + + resp, err = svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: storageOmitted()}) + require.NoError(t, err) + assert.True(t, storageOf(t, resp.(oapi.PutTelemetry200JSONResponse).Config)) + }) + + t.Run("a clear echoes the storage toggle it carried", func(t *testing.T) { + svc := newTestService(t, newMockRecordManager()) + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: storageOff()}) + require.NoError(t, err) + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Browser: allCategoriesDisabled(), + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &fa}, + }}) + require.NoError(t, err) + assert.False(t, storageOf(t, resp.(oapi.PutTelemetry200JSONResponse).Config)) + assert.False(t, svc.telemetrySession.Active()) + + _, err = svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: storageOff()}) + require.NoError(t, err) + presp, err := svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{Browser: allCategoriesDisabled()}}) + require.NoError(t, err) + assert.False(t, storageOf(t, presp.(oapi.PatchTelemetry200JSONResponse).Config), "a clearing PATCH keeps the session's storage toggle") + }) +} diff --git a/server/lib/telemetry/telemetry.go b/server/lib/telemetry/telemetry.go index c155ed71..d638e368 100644 --- a/server/lib/telemetry/telemetry.go +++ b/server/lib/telemetry/telemetry.go @@ -20,6 +20,11 @@ type TelemetryConfig struct { // ExportOTLP forwards captured events to the configured OTLP endpoint. // Off by default and independent of what is captured. ExportOTLP bool + // StoreS2 writes captured events to the S2 storage sink. The API default + // is on (an omitted storage block means true), so unlike the other fields + // the zero value here is not the default: a config that leaves it unset + // does not store, which is the safe way to fail. + StoreS2 bool // ExcludedCdpMethods leaves the named browser-control methods out of the // cdp_command stream. Empty reports every supported method. Telemetry only: // an excluded command still reaches the browser. @@ -41,6 +46,7 @@ type TelemetrySession struct { sessionStartSeq uint64 categories map[oapi.TelemetryEventCategory]struct{} exportOTLP bool + storeS2 bool appliedAt time.Time excludedCdp map[string]struct{} // active mirrors "a session is running with these categories" for callers @@ -114,6 +120,7 @@ func (s *TelemetrySession) Start(telemetrySessionID string, cfg TelemetryConfig) s.appliedAt = time.Now() s.categories = categorySet(cfg.Categories) s.exportOTLP = cfg.ExportOTLP + s.storeS2 = cfg.StoreS2 s.excludedCdp = excludedSet(cfg.ExcludedCdpMethods) s.setActiveLocked() } @@ -196,7 +203,7 @@ func (s *TelemetrySession) Config() TelemetryConfig { excluded = append(excluded, oapi.BrowserCdpCommandMethod(m)) } sort.Slice(excluded, func(i, j int) bool { return excluded[i] < excluded[j] }) - return TelemetryConfig{Categories: cats, ExportOTLP: s.exportOTLP, ExcludedCdpMethods: excluded} + return TelemetryConfig{Categories: cats, ExportOTLP: s.exportOTLP, StoreS2: s.storeS2, ExcludedCdpMethods: excluded} } // AppliedAt returns when the current configuration was applied, or the zero @@ -213,6 +220,7 @@ func (s *TelemetrySession) UpdateConfig(cfg TelemetryConfig) { defer s.mu.Unlock() s.categories = categorySet(cfg.Categories) s.exportOTLP = cfg.ExportOTLP + s.storeS2 = cfg.StoreS2 s.excludedCdp = excludedSet(cfg.ExcludedCdpMethods) s.setActiveLocked() } @@ -252,8 +260,9 @@ func (s *TelemetrySession) Stop() { defer s.mu.Unlock() s.id = "" s.appliedAt = time.Time{} - // The session is over, so export is off; keep Config() authoritative for the - // desired export state after a clear. + // The session is over, so export and storage are off; keep Config() + // authoritative for the desired sink state after a clear. s.exportOTLP = false + s.storeS2 = false s.setActiveLocked() } diff --git a/server/lib/telemetry/telemetry_test.go b/server/lib/telemetry/telemetry_test.go index 18d2929d..5d6028bd 100644 --- a/server/lib/telemetry/telemetry_test.go +++ b/server/lib/telemetry/telemetry_test.go @@ -232,3 +232,18 @@ func TestTelemetrySession(t *testing.T) { assert.True(t, json.Valid(env.Event.Data)) }) } + +func TestTelemetrySessionStoreS2(t *testing.T) { + ts := newTestTelemetrySession(t) + assert.False(t, ts.Config().StoreS2, "nothing is stored before a session") + + ts.Start("session-1", TelemetryConfig{StoreS2: true}) + assert.True(t, ts.Config().StoreS2) + + ts.UpdateConfig(TelemetryConfig{StoreS2: false}) + assert.False(t, ts.Config().StoreS2) + + ts.UpdateConfig(TelemetryConfig{StoreS2: true}) + ts.Stop() + assert.False(t, ts.Config().StoreS2, "a clear must leave the desired storage state off") +} From bda8778cb29db4b2231840acaefcd0669286700a Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 13:06:52 +0000 Subject: [PATCH 03/10] Open the S2 sink from the telemetry handler and refuse to close it reconcileStorage, deferred from PUT and PATCH like reconcileExport, opens the S2 sink once a capture session with storage on is committed. It never closes it: the writer binds its stream for the life of the instance, so instead a request that turns storage off after the sink has opened gets a 409 before anything is committed. That guard holds storageMu across the check and the commit so a start already in flight settles first; otherwise a storage-off config could be committed while the sink was opening. Co-Authored-By: Claude Fable 5.1 --- server/cmd/api/api/api.go | 7 +- server/cmd/api/api/telemetry.go | 71 +++++- server/cmd/api/api/telemetry_test.go | 306 +++++++++++++++++++++++++ server/lib/telemetry/telemetry_test.go | 22 ++ 4 files changed, 399 insertions(+), 7 deletions(-) diff --git a/server/cmd/api/api/api.go b/server/cmd/api/api/api.go index d7a528d2..d322ba6d 100644 --- a/server/cmd/api/api/api.go +++ b/server/cmd/api/api/api.go @@ -133,7 +133,12 @@ type ApiService struct { // exportMu serializes OTLP export reconciliation independently of monitorMu, // so a toggle-off drain (bounded by otlpStopTimeout) never blocks concurrent // telemetry reads/writes on monitorMu. - exportMu sync.Mutex + exportMu sync.Mutex + // storageMu serializes S2 storage reconciliation. Unlike exportMu it is also + // taken under monitorMu, by the storage-off guard in PUT and PATCH, so that + // guard sees a start reconcileStorage has in flight. reconcileStorage never + // takes monitorMu, so the order is always monitorMu then storageMu. + storageMu sync.Mutex lifecycleCtx context.Context lifecycleCancel context.CancelFunc } diff --git a/server/cmd/api/api/telemetry.go b/server/cmd/api/api/telemetry.go index 680cfc61..513a1a0d 100644 --- a/server/cmd/api/api/telemetry.go +++ b/server/cmd/api/api/telemetry.go @@ -16,6 +16,10 @@ import ( // otlpStopTimeout bounds how long a runtime export toggle-off waits to drain. const otlpStopTimeout = 5 * time.Second +// storageDisableConflict is the 409 for turning storage off after the sink has +// opened on this instance. +const storageDisableConflict = "storage cannot be disabled on an instance that has already started storage" + // GetTelemetry handles GET /telemetry. // Returns the current telemetry configuration. Returns 404 if telemetry is not configured. func (s *ApiService) GetTelemetry(_ context.Context, _ oapi.GetTelemetryRequestObject) (oapi.GetTelemetryResponseObject, error) { @@ -32,10 +36,11 @@ func (s *ApiService) GetTelemetry(_ context.Context, _ oapi.GetTelemetryRequestO // Sets the telemetry configuration. Returns 201 if not previously configured, 200 if it was. // Setting every configurable category to enabled:false clears the configuration (200). func (s *ApiService) PutTelemetry(ctx context.Context, req oapi.PutTelemetryRequestObject) (oapi.PutTelemetryResponseObject, error) { - // Reconcile export after monitorMu is released (defers run LIFO), so the - // toggle-off drain does not hold the API-wide lock. It reads the committed - // desired state from the session, so it is correct regardless of how this - // request exits. + // Reconcile the sinks after monitorMu is released (defers run LIFO), so the + // export toggle-off drain does not hold the API-wide lock. Both read the + // committed desired state from the session, so they are correct regardless + // of how this request exits. + defer s.reconcileStorage(ctx) defer s.reconcileExport(ctx) s.monitorMu.Lock() defer s.monitorMu.Unlock() @@ -45,6 +50,19 @@ func (s *ApiService) PutTelemetry(ctx context.Context, req oapi.PutTelemetryRequ return oapi.PutTelemetry400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil } + // Storage cannot be turned off once anything may have been persisted, a + // clear included. Checked before anything is committed, so a 409 leaves the + // session exactly as it was. storageMu stays held through the commit so a + // start reconcileStorage has in flight finishes first; without that a + // storage-off config could be committed while the sink was opening. + if !cfg.StoreS2 { + s.storageMu.Lock() + defer s.storageMu.Unlock() + if s.storageEverStarted() { + return oapi.PutTelemetry409JSONResponse{ConflictErrorJSONResponse: oapi.ConflictErrorJSONResponse{Message: storageDisableConflict}}, nil + } + } + wasActive := s.telemetrySession.Active() if allDisabled { @@ -82,7 +100,8 @@ func (s *ApiService) PutTelemetry(ctx context.Context, req oapi.PutTelemetryRequ // Partially updates the telemetry configuration. Returns 404 if not configured. // Setting every configurable category to enabled:false clears the configuration (200). func (s *ApiService) PatchTelemetry(ctx context.Context, req oapi.PatchTelemetryRequestObject) (oapi.PatchTelemetryResponseObject, error) { - // See PutTelemetry: reconcile export after monitorMu is released. + // See PutTelemetry: reconcile the sinks after monitorMu is released. + defer s.reconcileStorage(ctx) defer s.reconcileExport(ctx) s.monitorMu.Lock() defer s.monitorMu.Unlock() @@ -99,6 +118,14 @@ func (s *ApiService) PatchTelemetry(ctx context.Context, req oapi.PatchTelemetry prev := s.telemetrySession.Config() cfg, allDisabled := mergeTelemetryConfig(prev, req.Body) + // See PutTelemetry: the storage-off guard runs before anything is committed. + if !cfg.StoreS2 { + s.storageMu.Lock() + defer s.storageMu.Unlock() + if s.storageEverStarted() { + return oapi.PatchTelemetry409JSONResponse{ConflictErrorJSONResponse: oapi.ConflictErrorJSONResponse{Message: storageDisableConflict}}, nil + } + } if allDisabled { s.telemetrySession.Stop() s.stopTelemetryState() @@ -178,8 +205,40 @@ func (s *ApiService) reconcileExport(ctx context.Context) { } } +// reconcileStorage opens the S2 storage sink once the committed telemetry +// config calls for it: a capture session is active and storage is on. It never +// closes the sink. The writer is single-use and binds its stream for the life +// of the instance, so it stops only at shutdown, and the storage-off guard in +// PUT and PATCH is what keeps a storage-off config from ever coexisting with an +// open sink. Like reconcileExport it reads the desired state from the session, +// runs after monitorMu is released, holds its own lock, and is best-effort: a +// failed start is logged, never surfaced, and retried by the next request. +// No-op when the VM has no storage controller. +func (s *ApiService) reconcileStorage(ctx context.Context) { + if s.s2Storage == nil { + return + } + s.storageMu.Lock() + defer s.storageMu.Unlock() + + if !s.telemetrySession.Active() || !s.telemetrySession.Config().StoreS2 || s.s2Storage.EverStarted() { + return + } + // Root the sink on the app lifecycle, not this request; only its logs + // carry the request context. + if err := s.s2Storage.Start(s.lifecycleCtx); err != nil { + logger.FromContext(ctx).Error("s2 storage failed to start", "err", err) + } +} + +// storageEverStarted reports whether the S2 sink has opened on this instance, +// which is false when the VM has no storage controller. +func (s *ApiService) storageEverStarted() bool { + return s.s2Storage != nil && s.s2Storage.EverStarted() +} + // stopTelemetryState tears down optional capture and middleware after a session is -// cleared. Export is reconciled separately, after monitorMu is released. +// cleared. The sinks are reconciled separately, after monitorMu is released. func (s *ApiService) stopTelemetryState() { if err := s.cdpMonitor.SetTelemetry(false); err != nil { logger.FromContext(s.lifecycleCtx).Warn("failed to clean up telemetry capture", "err", err) diff --git a/server/cmd/api/api/telemetry_test.go b/server/cmd/api/api/telemetry_test.go index 4377dac5..fac13733 100644 --- a/server/cmd/api/api/telemetry_test.go +++ b/server/cmd/api/api/telemetry_test.go @@ -847,3 +847,309 @@ func TestTelemetryStorageToggle(t *testing.T) { assert.False(t, storageOf(t, presp.(oapi.PatchTelemetry200JSONResponse).Config), "a clearing PATCH keeps the session's storage toggle") }) } + +// stubS2Storage records starts for storage-toggle tests. Locked because +// reconcileStorage runs outside monitorMu. +type stubS2Storage struct { + mu sync.Mutex + starts int + running bool + everStarted bool + startErr error +} + +func (s *stubS2Storage) Start(context.Context) error { + s.mu.Lock() + defer s.mu.Unlock() + if s.startErr != nil { + return s.startErr + } + s.starts++ + s.running, s.everStarted = true, true + return nil +} + +func (s *stubS2Storage) Stop(context.Context) error { + s.mu.Lock() + defer s.mu.Unlock() + s.running = false + return nil +} + +func (s *stubS2Storage) Running() bool { + s.mu.Lock() + defer s.mu.Unlock() + return s.running +} + +func (s *stubS2Storage) EverStarted() bool { + s.mu.Lock() + defer s.mu.Unlock() + return s.everStarted +} + +func (s *stubS2Storage) startCount() int { + s.mu.Lock() + defer s.mu.Unlock() + return s.starts +} + +func TestTelemetryStorageStart(t *testing.T) { + ctx := context.Background() + tr, fa := true, false + networkOn := func(storage *bool) *oapi.BrowserTelemetryConfig { + cfg := &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Network: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + } + if storage != nil { + cfg.Storage = &oapi.BrowserTelemetryStorageConfig{Enabled: storage} + } + return cfg + } + cleared := func(storage *bool) *oapi.BrowserTelemetryConfig { + cfg := &oapi.BrowserTelemetryConfig{Browser: allCategoriesDisabled()} + if storage != nil { + cfg.Storage = &oapi.BrowserTelemetryStorageConfig{Enabled: storage} + } + return cfg + } + newStorageService := func(t *testing.T) (*ApiService, *stubS2Storage) { + svc := newTestService(t, newMockRecordManager()) + st := &stubS2Storage{} + svc.s2Storage = st + return svc, st + } + publishNetwork := func(t *testing.T, svc *ApiService) { + t.Helper() + _, ok := svc.telemetrySession.Publish(events.Event{Type: "network.request", Category: events.Network, Source: oapi.BrowserEventSource{Kind: oapi.Cdp}}) + require.True(t, ok, "the session must admit the event") + } + + t.Run("storage off never opens the sink", func(t *testing.T) { + svc, st := newStorageService(t) + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(&fa)}) + require.NoError(t, err) + r201, ok := resp.(oapi.PutTelemetry201JSONResponse) + require.True(t, ok, "expected 201, got %T", resp) + assert.False(t, *r201.Config.Storage.Enabled) + require.True(t, svc.telemetrySession.Active(), "the session runs; only storage is off") + + // Events flow to the ring (and so to the live stream and export) but + // nothing is opened that could persist them. + publishNetwork(t, svc) + assert.False(t, st.EverStarted()) + assert.Equal(t, 0, st.startCount()) + }) + + t.Run("storage omitted opens the sink once", func(t *testing.T) { + svc, st := newStorageService(t) + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry201JSONResponse{}, resp) + assert.Equal(t, 1, st.startCount()) + assert.True(t, st.Running()) + + resp, err = svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry200JSONResponse{}, resp) + _, err = svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Console: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + }}) + require.NoError(t, err) + assert.Equal(t, 1, st.startCount(), "the sink opens at most once per process") + }) + + t.Run("storage off after the sink opened is rejected", func(t *testing.T) { + svc, st := newStorageService(t) + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + require.True(t, st.EverStarted()) + publishNetwork(t, svc) + before := svc.telemetrySession.Config() + seq := svc.eventStream.Seq() + appliedAt := svc.telemetrySession.AppliedAt() + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Console: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &fa}, + }}) + require.NoError(t, err) + r409, ok := resp.(oapi.PutTelemetry409JSONResponse) + require.True(t, ok, "expected 409, got %T", resp) + assert.Equal(t, storageDisableConflict, r409.Message) + + after := svc.telemetrySession.Config() + assert.ElementsMatch(t, before.Categories, after.Categories, "a 409 must not change the categories") + assert.True(t, after.StoreS2, "a 409 must not change the storage toggle") + assert.Equal(t, appliedAt, svc.telemetrySession.AppliedAt(), "a 409 must not re-apply the session") + assert.Equal(t, seq, svc.eventStream.Seq()) + assert.True(t, st.Running(), "the sink keeps running") + assert.True(t, svc.telemetrySession.Active()) + + // A clear that carries storage off is refused the same way: the request + // asks for a state this instance can no longer honor. + resp, err = svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: cleared(&fa)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry409JSONResponse{}, resp) + assert.True(t, svc.telemetrySession.Active(), "a refused clear leaves the session running") + + // A clear that leaves storage alone still works. + resp, err = svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: cleared(nil)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry200JSONResponse{}, resp) + assert.False(t, svc.telemetrySession.Active()) + assert.True(t, st.Running(), "the handler never stops the sink") + }) + + t.Run("patch off after the sink opened is rejected", func(t *testing.T) { + svc, st := newStorageService(t) + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + require.True(t, st.EverStarted()) + + resp, err := svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &fa}, + }}) + require.NoError(t, err) + r409, ok := resp.(oapi.PatchTelemetry409JSONResponse) + require.True(t, ok, "expected 409, got %T", resp) + assert.Equal(t, storageDisableConflict, r409.Message) + assert.True(t, svc.telemetrySession.Config().StoreS2) + + resp, err = svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Browser: allCategoriesDisabled(), + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &fa}, + }}) + require.NoError(t, err) + require.IsType(t, oapi.PatchTelemetry409JSONResponse{}, resp) + assert.True(t, svc.telemetrySession.Active(), "a refused clearing patch leaves the session running") + + // Omitting storage keeps it on and is not a conflict. + resp, err = svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Console: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + }}) + require.NoError(t, err) + r200, ok := resp.(oapi.PatchTelemetry200JSONResponse) + require.True(t, ok, "expected 200, got %T", resp) + assert.True(t, *r200.Config.Storage.Enabled) + }) + + t.Run("a clear does not open the sink", func(t *testing.T) { + svc, st := newStorageService(t) + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: cleared(nil)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry200JSONResponse{}, resp) + resp, err = svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: cleared(&fa)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry200JSONResponse{}, resp, "storage off is fine while nothing has started") + assert.Equal(t, 0, st.startCount()) + assert.False(t, st.EverStarted()) + }) + + t.Run("a session that never stored can start storing", func(t *testing.T) { + svc, st := newStorageService(t) + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(&fa)}) + require.NoError(t, err) + publishNetwork(t, svc) + require.Equal(t, 0, st.startCount()) + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry200JSONResponse{}, resp) + assert.Equal(t, 1, st.startCount()) + }) + + t.Run("a failed start is retried by the next request", func(t *testing.T) { + svc, st := newStorageService(t) + st.startErr = errors.New("basin unreachable") + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry201JSONResponse{}, resp, "storage is best-effort") + assert.False(t, st.EverStarted()) + + st.mu.Lock() + st.startErr = nil + st.mu.Unlock() + _, err = svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Console: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + }}) + require.NoError(t, err) + assert.Equal(t, 1, st.startCount()) + }) + + t.Run("no controller means no storage and no conflict", func(t *testing.T) { + svc := newTestService(t, newMockRecordManager()) // s2Storage left nil + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(&fa)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry200JSONResponse{}, resp) + }) + + t.Run("storage off waits for a start in flight", func(t *testing.T) { + svc := newTestService(t, newMockRecordManager()) + st := &blockingStartS2Storage{entered: make(chan struct{}), release: make(chan struct{})} + svc.s2Storage = st + + // The PUT that turns storage on does not return until its deferred + // reconcile has run Start, which this stub holds open. + onDone := make(chan oapi.PutTelemetryResponseObject, 1) + go func() { + resp, _ := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + onDone <- resp + }() + select { + case <-st.entered: + case <-time.After(2 * time.Second): + t.Fatal("PUT did not reach the storage start") + } + + // A storage-off request arriving now must not slip past the guard: it + // waits for the start to settle, then sees it and refuses. + offDone := make(chan oapi.PutTelemetryResponseObject, 1) + go func() { + resp, _ := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(&fa)}) + offDone <- resp + }() + select { + case resp := <-offDone: + t.Fatalf("storage-off request returned %T while the sink was still opening", resp) + case <-time.After(100 * time.Millisecond): + } + + close(st.release) + require.IsType(t, oapi.PutTelemetry201JSONResponse{}, <-onDone) + require.IsType(t, oapi.PutTelemetry409JSONResponse{}, <-offDone) + assert.True(t, svc.telemetrySession.Config().StoreS2, "the committed config never said off while the sink was open") + }) +} + +// blockingStartS2Storage holds Start open until released, to prove the guard +// waits on storageMu rather than reading EverStarted mid-start. +type blockingStartS2Storage struct { + mu sync.Mutex + entered chan struct{} + release chan struct{} + everStarted bool +} + +func (s *blockingStartS2Storage) Start(context.Context) error { + close(s.entered) + <-s.release + s.mu.Lock() + defer s.mu.Unlock() + s.everStarted = true + return nil +} + +func (s *blockingStartS2Storage) Stop(context.Context) error { return nil } +func (s *blockingStartS2Storage) Running() bool { return s.EverStarted() } +func (s *blockingStartS2Storage) EverStarted() bool { + s.mu.Lock() + defer s.mu.Unlock() + return s.everStarted +} diff --git a/server/lib/telemetry/telemetry_test.go b/server/lib/telemetry/telemetry_test.go index 5d6028bd..63a03974 100644 --- a/server/lib/telemetry/telemetry_test.go +++ b/server/lib/telemetry/telemetry_test.go @@ -247,3 +247,25 @@ func TestTelemetrySessionStoreS2(t *testing.T) { ts.Stop() assert.False(t, ts.Config().StoreS2, "a clear must leave the desired storage state off") } + +// The S2 sink opens with the first storing session and reads the ring from +// its oldest event, so this is what makes deferring it lossless: with no +// session there is no publisher (TelemetrySession is the ring's only one), so +// the ring is empty when the first session starts. +func TestPublishWithoutSessionReachesNothing(t *testing.T) { + es := newTestEventStream(t, 16) + ts := NewTelemetrySession(es) + + for _, cat := range events.UserCategories { + _, ok := ts.Publish(cdpEvent("before.session", cat)) + assert.False(t, ok) + } + assert.Zero(t, es.Seq(), "nothing may reach the ring before a session") + + ts.Start("session-1", TelemetryConfig{Categories: events.UserCategories, StoreS2: true}) + ts.Publish(cdpEvent("in.session", events.Network)) + ts.Stop() + _, ok := ts.Publish(cdpEvent("after.session", events.Network)) + assert.False(t, ok) + assert.Equal(t, uint64(1), es.Seq(), "nothing may reach the ring after a clear either") +} From b26d52c7a84df4c452202b7a51a79ea35e2d6d90 Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 13:25:01 +0000 Subject: [PATCH 04/10] Open the S2 sink only from the telemetry handler main no longer starts the controller at boot or from the fork-identity hook; the hook only records the applied payload's stream. While a fork is still waiting for its identity the resolver returns no stream, so a session applied before the handoff leaves the sink closed instead of binding the parent's stream, and the next config after the handoff opens it. Co-Authored-By: Claude Opus 5.5 --- server/cmd/api/fork_identity_test.go | 68 ++++++++++---------- server/cmd/api/main.go | 96 +++++++++++----------------- 2 files changed, 74 insertions(+), 90 deletions(-) diff --git a/server/cmd/api/fork_identity_test.go b/server/cmd/api/fork_identity_test.go index a8345380..3d750caf 100644 --- a/server/cmd/api/fork_identity_test.go +++ b/server/cmd/api/fork_identity_test.go @@ -1,7 +1,6 @@ package main import ( - "context" "encoding/json" "log/slog" "net/http" @@ -212,10 +211,11 @@ func TestAppliedS2StreamPrefersForkIdentity(t *testing.T) { markForkIdentityWaitArmed(t) cfg := &config.Config{S2Stream: "seed-stream"} - // Nothing applied yet: the env this process started with is all there is. - stream, applied := appliedS2Stream(cfg) - assert.False(t, applied) - assert.Equal(t, "seed-stream", stream) + // Nothing applied yet: the env this process started with belongs to the + // parent, so there is nothing this instance may bind. + stream, pending := appliedS2Stream(cfg) + assert.True(t, pending) + assert.Empty(t, stream) // A payload written but not yet applied is not the instance's identity. writeForkIdentityPayloadForTest(t, forkidentity.Payload{ @@ -223,14 +223,14 @@ func TestAppliedS2StreamPrefersForkIdentity(t *testing.T) { "session_intel_url": "https://intel.example.test", "s2_stream": "fork-stream", }) - stream, applied = appliedS2Stream(cfg) - assert.False(t, applied) - assert.Equal(t, "seed-stream", stream) + stream, pending = appliedS2Stream(cfg) + assert.True(t, pending) + assert.Empty(t, stream) // Once applied it survives a restart of this process, which is the point. require.NoError(t, forkidentity.WriteAppliedMarker("fork")) - stream, applied = appliedS2Stream(cfg) - assert.True(t, applied) + stream, pending = appliedS2Stream(cfg) + assert.False(t, pending) assert.Equal(t, "fork-stream", stream) } @@ -246,9 +246,9 @@ func TestAppliedS2StreamIgnoresMarkerForAnotherInstance(t *testing.T) { }) require.NoError(t, forkidentity.WriteAppliedMarker("someone-else")) - stream, applied := appliedS2Stream(cfg) - assert.False(t, applied) - assert.Equal(t, "seed-stream", stream) + stream, pending := appliedS2Stream(cfg) + assert.True(t, pending) + assert.Empty(t, stream) } func TestAppliedS2StreamIgnoresMarkerFromBeforeThisBoot(t *testing.T) { @@ -264,32 +264,34 @@ func TestAppliedS2StreamIgnoresMarkerFromBeforeThisBoot(t *testing.T) { }) require.NoError(t, forkidentity.WriteAppliedMarker("stale-fork")) - stream, applied := appliedS2Stream(cfg) - assert.False(t, applied) + stream, pending := appliedS2Stream(cfg) + assert.False(t, pending) assert.Equal(t, "seed-stream", stream) } func TestS2StreamResolverUsesHookPayloadWithoutReadyFile(t *testing.T) { useTempForkIdentityFiles(t) - resolver := newS2StreamResolver(&config.Config{S2Stream: "seed-stream"}) - started := make(chan string, 1) - - resolver.StartForAppliedPayload( - context.Background(), - forkidentity.Payload{"s2_stream": "fork-stream"}, - func(context.Context) error { - started <- resolver.Resolve() - return nil - }, - slog.Default(), - ) + resolver := newS2StreamResolver(&config.Config{S2Stream: "seed-stream"}, slog.Default()) - select { - case stream := <-started: - assert.Equal(t, "fork-stream", stream) - case <-time.After(time.Second): - t.Fatal("S2 storage did not start") - } + resolver.RecordAppliedPayload(forkidentity.Payload{"s2_stream": "fork-stream"}) + + assert.Equal(t, "fork-stream", resolver.Resolve()) +} + +// A telemetry config applied to a fork before its identity must not bind the +// parent's stream: the sink stays closed until the handoff has happened. +func TestS2StreamResolverHoldsBackSeedStreamWhilePending(t *testing.T) { + useTempForkIdentityFiles(t) + markForkIdentityWaitArmed(t) + resolver := newS2StreamResolver(&config.Config{S2Stream: "seed-stream"}, slog.Default()) + + assert.Empty(t, resolver.Resolve()) + + resolver.RecordAppliedPayload(forkidentity.Payload{"instance_name": "fork", "session_intel_url": "https://intel.example.test"}) + assert.Equal(t, "seed-stream", resolver.Resolve(), "a payload without a stream keeps the boot configuration") + + resolver.RecordAppliedPayload(forkidentity.Payload{"s2_stream": "fork-stream"}) + assert.Equal(t, "fork-stream", resolver.Resolve()) } // markForkIdentityWaitArmed stands in for the wrapper having entered the wait, diff --git a/server/cmd/api/main.go b/server/cmd/api/main.go index 30285c72..bbfbdf16 100644 --- a/server/cmd/api/main.go +++ b/server/cmd/api/main.go @@ -129,31 +129,14 @@ func main() { slogger.Error("sysmon: kmsg OOM monitor disabled", "err", err) } - // Malformed flag: treat as disabled but surface it, matching how the OTLP - // identity provider handles the same flag. Exiting would crashloop the VM - // over a provisioning typo. - forkIdentityWait, err := forkidentity.WaitEnabled() - if err != nil { - slogger.Warn("fork-identity wait flag invalid; treating as disabled", "err", err) - } - // An instance that already took a fork identity keeps it across a restart of - // this process, which the env captured at boot does not reflect. - _, s2StreamApplied := appliedS2Stream(config) - - // Optional S2 storage sink. The append session is bound to one stream when - // it starts, and an instance still holding for a fork identity is carrying - // the stream name of the instance it was forked from, so defer the writer - // until the identity that owns the events arrives. - s2Streams := newS2StreamResolver(config) + // Optional S2 storage sink. Constructed here but opened by the telemetry + // handler, with the first capture session that has storage on, so an + // instance whose sessions keep storage off never opens an append session. + // The session binds one stream when it opens, and an instance still holding + // for a fork identity is carrying the stream of the instance it was forked + // from, so the resolver hands out no stream until that identity arrives. + s2Streams := newS2StreamResolver(config, slogger) s2Storage := events.NewS2StorageController(eventStream, config.S2Basin, config.S2AccessToken, s2Streams.Resolve, events.S2Config{}, slogger) - if !forkIdentityWait || s2StreamApplied { - // An optional sink that cannot open must not take the browser down: the - // api runs under supervisord with autorestart, so exiting here would - // crashloop the VM over a misconfigured basin or token. - if err := s2Storage.Start(ctx); err != nil { - slogger.Error("failed to start S2 storage writer, continuing without it", "err", err) - } - } // Optional OTLP export sink. Independent of S2; both can run together. // Constructed when an endpoint is provisioned, but left stopped: export is @@ -194,15 +177,15 @@ func main() { }, slogger) } - // A fork boots carrying the stream of the instance it came from, and the S2 - // writer binds a stream when it starts, so it is opened here once the guest - // has taken an identity of its own. OTLP needs no hook here: its credential - // resolves per request and its resource attributes at exporter build, and - // export is turned on per session, which the platform does after the - // handoff. An export started before then keeps the source's resource - // attributes until it is restarted. + // A fork boots carrying the stream of the instance it came from, so the + // hook records the stream of the identity the guest has taken for the S2 + // writer to bind when the telemetry handler opens it, which the platform + // does after the handoff. OTLP needs no hook here: its credential resolves + // per request and its resource attributes at exporter build, and export is + // turned on per session, likewise after the handoff. An export started + // before then keeps the source's resource attributes until it is restarted. onForkIdentityApplied := func(payload forkidentity.Payload) { - s2Streams.StartForAppliedPayload(ctx, payload, s2Storage.Start, slogger) + s2Streams.RecordAppliedPayload(payload) } apiService, err := api.New( @@ -438,7 +421,7 @@ func main() { // S2 storage shuts down after the servers above, since they might produce // events we want to capture into the stream; we must let them finish before - // closing the writer. + // closing the writer. A no-op when no session ever opened it. s2StopCtx, s2StopCancel := context.WithTimeout(context.Background(), 10*time.Second) defer s2StopCancel() if err := s2Storage.Stop(s2StopCtx); err != nil { @@ -465,68 +448,67 @@ func mustFFmpeg() { } // s2StreamResolver uses the hook payload once applied and the persisted payload -// after an API process restart. +// after an API process restart. Resolve is called by the S2 controller when the +// telemetry handler opens the sink, which on a fork happens after the handoff. type s2StreamResolver struct { cfg *config.Config + log *slog.Logger hookStream atomic.Pointer[string] } -func newS2StreamResolver(cfg *config.Config) *s2StreamResolver { - return &s2StreamResolver{cfg: cfg} +func newS2StreamResolver(cfg *config.Config, log *slog.Logger) *s2StreamResolver { + return &s2StreamResolver{cfg: cfg, log: log} } +// Resolve returns the stream the S2 writer may bind, or "" while the instance +// is still waiting for a fork identity, which keeps the sink closed rather than +// bound to the parent's stream. func (r *s2StreamResolver) Resolve() string { if stream := r.hookStream.Load(); stream != nil { return *stream } - stream, _ := appliedS2Stream(r.cfg) + stream, pending := appliedS2Stream(r.cfg) + if pending { + r.log.Warn("S2 storage not opened: fork identity pending; it opens with the next telemetry config applied after the handoff") + } return stream } -func (r *s2StreamResolver) StartForAppliedPayload( - ctx context.Context, - payload forkidentity.Payload, - start func(context.Context) error, - log *slog.Logger, -) { +// RecordAppliedPayload records the applied identity's stream in-process so a +// resolve that follows the handoff does not depend on re-reading the identity +// files. It does not block: the handler contract forbids holding up the handoff. +func (r *s2StreamResolver) RecordAppliedPayload(payload forkidentity.Payload) { stream := forkidentity.FirstNonEmpty(forkidentity.Env(payload)["S2_STREAM"], r.cfg.S2Stream) r.hookStream.Store(&stream) - // The handler contract forbids blocking the handoff on an optional sink. - go func() { - if err := start(ctx); err != nil { - log.Error("failed to start S2 storage writer for fork identity", "err", err) - } - }() } // appliedS2Stream resolves the stream the S2 writer should bind, preferring a // fork identity the guest has already taken over the env this process started // with. The env belongs to the instance this one was forked from, and it is what // a restarted api would otherwise bind for the rest of the instance's life. -// Reports whether an applied fork identity supplied it. +// While the wait is armed and no identity has been applied there is no stream +// this instance may bind yet, so the result is empty; pending reports that case. // // OTLP resolves its identity per use instead (otlpIdentityProvider), so a stale // read there self-corrects; an S2 append session binds once, so this read has to // be right the first time. -func appliedS2Stream(cfg *config.Config) (string, bool) { - stream := cfg.S2Stream - +func appliedS2Stream(cfg *config.Config) (stream string, pending bool) { // The wrapper clears stale identity state and writes the ready file before // starting this process. Its presence distinguishes a fork-wait boot; once // the fork is applied, the marker and payload survive API restarts and must // take precedence over the seed identity in the boot environment. if _, err := os.Stat(forkidentity.ReadyFile); err != nil { - return stream, false + return cfg.S2Stream, false } applied, err := forkidentity.ReadAppliedMarker() if err != nil || applied == "" { - return stream, false + return "", true } payload, err := forkidentity.ReadPayload() if err != nil || payload.InstanceName() != applied { - return stream, false + return "", true } - return forkidentity.FirstNonEmpty(forkidentity.Env(payload)["S2_STREAM"], stream), true + return forkidentity.FirstNonEmpty(forkidentity.Env(payload)["S2_STREAM"], cfg.S2Stream), false } // chromeJSONProxyHandler returns a handler that proxies a JSON endpoint from From 6c54846f4524a3dca67e12a7290178823be8d395 Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 13:28:17 +0000 Subject: [PATCH 05/10] Store only what was captured with storage on The S2 writer read the ring from its oldest event, so a session with storage off followed by one with it on would have written the storage-off events to S2 when the sink opened. The session now records the last seq published before storage was turned on, and the controller opens the writer after it. The first storing session on a fresh process still stores from seq 0, since nothing is published before a session. The controller's Start takes the floor, so the controller tests pass 0. Co-Authored-By: Claude Opus 5.5 --- server/cmd/api/api/api.go | 2 +- server/cmd/api/api/telemetry.go | 9 ++-- server/cmd/api/api/telemetry_test.go | 62 ++++++++++++++++++++++++-- server/lib/events/s2storage.go | 19 +++++--- server/lib/events/s2storage_test.go | 46 +++++++++++++------ server/lib/telemetry/telemetry.go | 26 ++++++++++- server/lib/telemetry/telemetry_test.go | 31 +++++++++++++ 7 files changed, 166 insertions(+), 29 deletions(-) diff --git a/server/cmd/api/api/api.go b/server/cmd/api/api/api.go index d322ba6d..7d8d71c6 100644 --- a/server/cmd/api/api/api.go +++ b/server/cmd/api/api/api.go @@ -46,7 +46,7 @@ var _ OTLPExporter = (*events.OTLPExportController)(nil) // S2Storage controls the optional S2 storage sink, which no-ops when the VM // has no S2 credentials. Implemented by *events.S2StorageController. type S2Storage interface { - Start(ctx context.Context) error + Start(ctx context.Context, afterSeq uint64) error Stop(ctx context.Context) error Running() bool EverStarted() bool diff --git a/server/cmd/api/api/telemetry.go b/server/cmd/api/api/telemetry.go index 513a1a0d..2b11b012 100644 --- a/server/cmd/api/api/telemetry.go +++ b/server/cmd/api/api/telemetry.go @@ -206,7 +206,9 @@ func (s *ApiService) reconcileExport(ctx context.Context) { } // reconcileStorage opens the S2 storage sink once the committed telemetry -// config calls for it: a capture session is active and storage is on. It never +// config calls for it: a capture session is active and storage is on. The sink +// stores only what that config captured, not what the ring still holds from +// earlier storage-off capture. It never // closes the sink. The writer is single-use and binds its stream for the life // of the instance, so it stops only at shutdown, and the storage-off guard in // PUT and PATCH is what keeps a storage-off config from ever coexisting with an @@ -221,12 +223,13 @@ func (s *ApiService) reconcileStorage(ctx context.Context) { s.storageMu.Lock() defer s.storageMu.Unlock() - if !s.telemetrySession.Active() || !s.telemetrySession.Config().StoreS2 || s.s2Storage.EverStarted() { + afterSeq, store := s.telemetrySession.StoreS2After() + if !store || s.s2Storage.EverStarted() { return } // Root the sink on the app lifecycle, not this request; only its logs // carry the request context. - if err := s.s2Storage.Start(s.lifecycleCtx); err != nil { + if err := s.s2Storage.Start(s.lifecycleCtx, afterSeq); err != nil { logger.FromContext(ctx).Error("s2 storage failed to start", "err", err) } } diff --git a/server/cmd/api/api/telemetry_test.go b/server/cmd/api/api/telemetry_test.go index fac13733..bfa2de27 100644 --- a/server/cmd/api/api/telemetry_test.go +++ b/server/cmd/api/api/telemetry_test.go @@ -856,15 +856,17 @@ type stubS2Storage struct { running bool everStarted bool startErr error + afterSeq uint64 } -func (s *stubS2Storage) Start(context.Context) error { +func (s *stubS2Storage) Start(_ context.Context, afterSeq uint64) error { s.mu.Lock() defer s.mu.Unlock() if s.startErr != nil { return s.startErr } s.starts++ + s.afterSeq = afterSeq s.running, s.everStarted = true, true return nil } @@ -1049,17 +1051,71 @@ func TestTelemetryStorageStart(t *testing.T) { assert.False(t, st.EverStarted()) }) - t.Run("a session that never stored can start storing", func(t *testing.T) { + t.Run("the first storing session stores from its start", func(t *testing.T) { + svc, st := newStorageService(t) + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + assert.Zero(t, st.afterSeq, "nothing precedes the first session, so nothing is skipped") + }) + + t.Run("a session that never stored can start storing, without what it captured", func(t *testing.T) { svc, st := newStorageService(t) _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(&fa)}) require.NoError(t, err) publishNetwork(t, svc) + publishNetwork(t, svc) require.Equal(t, 0, st.startCount()) resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) require.NoError(t, err) require.IsType(t, oapi.PutTelemetry200JSONResponse{}, resp) assert.Equal(t, 1, st.startCount()) + assert.EqualValues(t, 2, st.afterSeq, "events captured with storage off must not be stored") + }) + + t.Run("a patch that turns storage on skips what was captured before it", func(t *testing.T) { + svc, st := newStorageService(t) + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(&fa)}) + require.NoError(t, err) + publishNetwork(t, svc) + + _, err = svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &tr}, + }}) + require.NoError(t, err) + assert.Equal(t, 1, st.startCount()) + assert.EqualValues(t, 1, st.afterSeq) + }) + + t.Run("a storing session after a cleared storage-off one skips it", func(t *testing.T) { + svc, st := newStorageService(t) + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(&fa)}) + require.NoError(t, err) + publishNetwork(t, svc) + publishNetwork(t, svc) + publishNetwork(t, svc) + _, err = svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: cleared(&fa)}) + require.NoError(t, err) + + resp, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + require.IsType(t, oapi.PutTelemetry201JSONResponse{}, resp) + assert.EqualValues(t, 3, st.afterSeq) + }) + + t.Run("a retried start keeps the session's floor", func(t *testing.T) { + svc, st := newStorageService(t) + st.startErr = errors.New("basin unreachable") + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + publishNetwork(t, svc) + + st.mu.Lock() + st.startErr = nil + st.mu.Unlock() + _, err = svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: networkOn(nil)}) + require.NoError(t, err) + assert.Zero(t, st.afterSeq, "events captured while storage was on but failing to open are still stored") }) t.Run("a failed start is retried by the next request", func(t *testing.T) { @@ -1137,7 +1193,7 @@ type blockingStartS2Storage struct { everStarted bool } -func (s *blockingStartS2Storage) Start(context.Context) error { +func (s *blockingStartS2Storage) Start(context.Context, uint64) error { close(s.entered) <-s.release s.mu.Lock() diff --git a/server/lib/events/s2storage.go b/server/lib/events/s2storage.go index 701b7c57..7cd08ea3 100644 --- a/server/lib/events/s2storage.go +++ b/server/lib/events/s2storage.go @@ -152,13 +152,15 @@ func (s *s2Storage) Close(ctx context.Context) error { return err } -// S2StorageWriter reads from an EventStream and forwards each event to S2. -// Construct with NewS2StorageWriter, call Start to begin, Stop to drain and shut down. +// S2StorageWriter reads from an EventStream and forwards each event after +// afterSeq to S2. Construct with NewS2StorageWriter, call Start to begin, Stop +// to drain and shut down. type S2StorageWriter struct { es *EventStream basin string accessToken string streamName string + afterSeq uint64 cfg S2Config log *slog.Logger @@ -169,12 +171,13 @@ type S2StorageWriter struct { done chan struct{} } -func NewS2StorageWriter(es *EventStream, basin, accessToken, streamName string, cfg S2Config, log *slog.Logger) *S2StorageWriter { +func NewS2StorageWriter(es *EventStream, basin, accessToken, streamName string, afterSeq uint64, cfg S2Config, log *slog.Logger) *S2StorageWriter { return &S2StorageWriter{ es: es, basin: basin, accessToken: accessToken, streamName: streamName, + afterSeq: afterSeq, cfg: cfg, log: log, } @@ -194,7 +197,7 @@ func (w *S2StorageWriter) Start(ctx context.Context) error { return err } w.storage = storage - w.writer = NewStorageWriter(w.es, storage, w.log) + w.writer = NewStorageWriterAfter(w.es, storage, w.log, w.afterSeq) w.done = make(chan struct{}) w.started = true go func() { @@ -256,7 +259,11 @@ func NewS2StorageController(es *EventStream, basin, token string, streamFn func( return &S2StorageController{es: es, basin: basin, token: token, streamFn: streamFn, cfg: cfg, log: log} } -func (c *S2StorageController) Start(parent context.Context) (err error) { +// Start opens the writer, which stores only events published after afterSeq: +// the ring still holds whatever was captured before storage was wanted, and +// that must not be persisted. afterSeq applies to the call that opens the +// writer; once one has, later calls are no-ops. +func (c *S2StorageController) Start(parent context.Context, afterSeq uint64) (err error) { c.mu.Lock() if c.everStarted { c.mu.Unlock() @@ -290,7 +297,7 @@ func (c *S2StorageController) Start(parent context.Context) (err error) { return nil } runCtx, cancel := context.WithCancel(parent) - w := NewS2StorageWriter(c.es, c.basin, c.token, stream, c.cfg, c.log) + w := NewS2StorageWriter(c.es, c.basin, c.token, stream, afterSeq, c.cfg, c.log) if err = w.Start(runCtx); err != nil { cancel() return err diff --git a/server/lib/events/s2storage_test.go b/server/lib/events/s2storage_test.go index f7e63aac..0516f045 100644 --- a/server/lib/events/s2storage_test.go +++ b/server/lib/events/s2storage_test.go @@ -41,11 +41,11 @@ func TestS2StorageController_OpensNothingUntilStart(t *testing.T) { func TestS2StorageController_StartIsIdempotent(t *testing.T) { c, resolved := newTestController(t, "test-stream") - require.NoError(t, c.Start(context.Background())) + require.NoError(t, c.Start(context.Background(), 0)) first := c.writer require.NotNil(t, first) - require.NoError(t, c.Start(context.Background())) + require.NoError(t, c.Start(context.Background(), 0)) assert.Same(t, first, c.writer, "second Start must not replace the writer") assert.Equal(t, int32(1), resolved.Load(), "second Start must not re-resolve the stream") @@ -61,7 +61,7 @@ func TestS2StorageController_ConcurrentStartOpensOneWriter(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - errs <- c.Start(context.Background()) + errs <- c.Start(context.Background(), 0) }() } wg.Wait() @@ -89,11 +89,11 @@ func TestS2StorageController_ConcurrentStartReturnsFailure(t *testing.T) { cancel() firstDone := make(chan error, 1) - go func() { firstDone <- c.Start(ctx) }() + go func() { firstDone <- c.Start(ctx, 0) }() <-entered secondDone := make(chan error, 1) - go func() { secondDone <- c.Start(context.Background()) }() + go func() { secondDone <- c.Start(context.Background(), 0) }() select { case err := <-secondDone: t.Fatalf("concurrent Start returned before the in-flight start finished: %v", err) @@ -112,12 +112,12 @@ func TestS2StorageController_StartFailureRollsBack(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() - require.ErrorIs(t, c.Start(ctx), context.Canceled) + require.ErrorIs(t, c.Start(ctx, 0), context.Canceled) assert.False(t, c.Running()) assert.False(t, c.EverStarted()) assert.Equal(t, int32(1), resolved.Load()) - require.NoError(t, c.Start(context.Background())) + require.NoError(t, c.Start(context.Background(), 0)) assert.True(t, c.Running()) assert.True(t, c.EverStarted()) assert.Equal(t, int32(2), resolved.Load()) @@ -133,7 +133,7 @@ func TestS2StorageController_FailedStartDoesNotLogEnabled(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() - require.ErrorIs(t, c.Start(ctx), context.Canceled) + require.ErrorIs(t, c.Start(ctx, 0), context.Canceled) assert.NotContains(t, logs.String(), "S2 storage enabled") } @@ -143,7 +143,7 @@ func TestS2StorageController_SuccessfulStartLogsEnabled(t *testing.T) { return "test-stream" }, S2Config{}, slog.New(slog.NewTextHandler(&logs, nil))) - require.NoError(t, c.Start(context.Background())) + require.NoError(t, c.Start(context.Background(), 0)) assert.Contains(t, logs.String(), "S2 storage enabled") require.NoError(t, stopController(t, c)) @@ -152,7 +152,7 @@ func TestS2StorageController_SuccessfulStartLogsEnabled(t *testing.T) { func TestS2StorageController_EmptyStreamDoesNotStart(t *testing.T) { c, resolved := newTestController(t, "") - require.NoError(t, c.Start(context.Background())) + require.NoError(t, c.Start(context.Background(), 0)) assert.Equal(t, int32(1), resolved.Load()) assert.False(t, c.Running()) assert.False(t, c.EverStarted()) @@ -165,7 +165,7 @@ func TestS2StorageController_MissingCredentialsDoesNotResolveStream(t *testing.T return "test-stream" }, S2Config{}, slog.Default()) - require.NoError(t, c.Start(context.Background())) + require.NoError(t, c.Start(context.Background(), 0)) assert.Zero(t, resolved.Load()) assert.False(t, c.Running()) assert.False(t, c.EverStarted()) @@ -208,7 +208,7 @@ func TestS2StorageController_StopHonorsContextDuringStart(t *testing.T) { cancelParent() startDone := make(chan error, 1) - go func() { startDone <- c.Start(parent) }() + go func() { startDone <- c.Start(parent, 0) }() <-entered ctx, cancel := context.WithCancel(context.Background()) @@ -298,13 +298,31 @@ func TestS2StorageController_StopHonorsContextDuringStop(t *testing.T) { func TestS2StorageController_EverStartedSurvivesStop(t *testing.T) { c, resolved := newTestController(t, "test-stream") - require.NoError(t, c.Start(context.Background())) + require.NoError(t, c.Start(context.Background(), 0)) require.NoError(t, stopController(t, c)) assert.False(t, c.Running()) assert.True(t, c.EverStarted()) - require.NoError(t, c.Start(context.Background())) + require.NoError(t, c.Start(context.Background(), 0)) assert.False(t, c.Running(), "a stopped controller must not reopen the sink") assert.Equal(t, int32(1), resolved.Load()) } + +// The ring can still hold events captured before storage was wanted, and the +// writer must not replay them. A ring of four holding seqs 7..10 makes a +// replay observable without submitting anything: a writer after seq 10 has +// nothing to read, while one reading from seq 0 finds six evicted events. +func TestS2StorageController_StartSkipsEventsAtOrBeforeAfterSeq(t *testing.T) { + es := newTestStream(t, 4) + for range 10 { + es.Publish(Envelope{Event: makeEvent("captured with storage off")}) + } + c := NewS2StorageController(es, "test-basin", "test-token", func() string { return "test-stream" }, S2Config{}, slog.Default()) + + require.NoError(t, c.Start(context.Background(), 10)) + require.True(t, c.Running()) + assert.Never(t, func() bool { return es.DroppedEvents() > 0 }, 200*time.Millisecond, time.Millisecond, "the writer read events at or before afterSeq") + + require.NoError(t, stopController(t, c)) +} diff --git a/server/lib/telemetry/telemetry.go b/server/lib/telemetry/telemetry.go index d638e368..99976447 100644 --- a/server/lib/telemetry/telemetry.go +++ b/server/lib/telemetry/telemetry.go @@ -47,8 +47,12 @@ type TelemetrySession struct { categories map[oapi.TelemetryEventCategory]struct{} exportOTLP bool storeS2 bool - appliedAt time.Time - excludedCdp map[string]struct{} + // storeS2After is the last seq published before storage was turned on for + // the current session. Everything at or below it was captured with storage + // off, so the S2 sink must start after it. + storeS2After uint64 + appliedAt time.Time + excludedCdp map[string]struct{} // active mirrors "a session is running with these categories" for callers // on a hot path, who must decide whether to do any work at all before they // reach Publish and its mutex. nil means no session. Written under mu; @@ -121,6 +125,7 @@ func (s *TelemetrySession) Start(telemetrySessionID string, cfg TelemetryConfig) s.categories = categorySet(cfg.Categories) s.exportOTLP = cfg.ExportOTLP s.storeS2 = cfg.StoreS2 + s.storeS2After = s.sessionStartSeq s.excludedCdp = excludedSet(cfg.ExcludedCdpMethods) s.setActiveLocked() } @@ -220,11 +225,28 @@ func (s *TelemetrySession) UpdateConfig(cfg TelemetryConfig) { defer s.mu.Unlock() s.categories = categorySet(cfg.Categories) s.exportOTLP = cfg.ExportOTLP + // Publish holds mu, so the seq read here is exactly the boundary between + // events captured with storage off and those captured with it on. + if cfg.StoreS2 && !s.storeS2 { + s.storeS2After = s.es.Seq() + } s.storeS2 = cfg.StoreS2 s.excludedCdp = excludedSet(cfg.ExcludedCdpMethods) s.setActiveLocked() } +// StoreS2After reports whether the current session stores to S2 and, if it +// does, the seq the sink must start after. False when no session is active, +// since Stop clears storeS2. +func (s *TelemetrySession) StoreS2After() (uint64, bool) { + s.mu.Lock() + defer s.mu.Unlock() + if !s.storeS2 { + return 0, false + } + return s.storeS2After, true +} + // CategoryEnabled reports whether events in category c are currently captured. // It returns false when no session is active. Lock-free, so a caller on the // CDP forwarding path can check it per frame; Publish re-checks under mu. diff --git a/server/lib/telemetry/telemetry_test.go b/server/lib/telemetry/telemetry_test.go index 63a03974..23cbb280 100644 --- a/server/lib/telemetry/telemetry_test.go +++ b/server/lib/telemetry/telemetry_test.go @@ -248,6 +248,37 @@ func TestTelemetrySessionStoreS2(t *testing.T) { assert.False(t, ts.Config().StoreS2, "a clear must leave the desired storage state off") } +func TestTelemetrySessionStoreS2After(t *testing.T) { + ts := newTestTelemetrySession(t) + _, store := ts.StoreS2After() + assert.False(t, store, "no session, nothing to store") + + ts.Start("off", TelemetryConfig{Categories: events.UserCategories}) + ts.Publish(cdpEvent("ev.one", events.Network)) + ts.Publish(cdpEvent("ev.two", events.Network)) + _, store = ts.StoreS2After() + assert.False(t, store) + + ts.UpdateConfig(TelemetryConfig{Categories: events.UserCategories, StoreS2: true}) + after, store := ts.StoreS2After() + assert.True(t, store) + assert.EqualValues(t, 2, after, "turning storage on mid-session starts after what was captured with it off") + + ts.Publish(cdpEvent("ev.three", events.Network)) + ts.UpdateConfig(TelemetryConfig{Categories: events.UserCategories, StoreS2: true}) + after, _ = ts.StoreS2After() + assert.EqualValues(t, 2, after, "a config that keeps storage on keeps its floor") + + ts.Stop() + _, store = ts.StoreS2After() + assert.False(t, store) + + ts.Start("on", TelemetryConfig{Categories: events.UserCategories, StoreS2: true}) + after, store = ts.StoreS2After() + assert.True(t, store) + assert.EqualValues(t, 3, after, "a storing session starts after what earlier sessions captured") +} + // The S2 sink opens with the first storing session and reads the ring from // its oldest event, so this is what makes deferring it lossless: with no // session there is no publisher (TelemetrySession is the ring's only one), so From 34f85a097f76f75c01539172cb2c37778b8b64d3 Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 13:31:57 +0000 Subject: [PATCH 06/10] Document that storage only covers events captured while enabled Co-Authored-By: Claude Opus 5.5 --- server/cmd/api/api/telemetry.go | 19 +- server/lib/oapi/oapi.go | 563 ++++++++++++++++---------------- server/openapi.yaml | 7 +- 3 files changed, 295 insertions(+), 294 deletions(-) diff --git a/server/cmd/api/api/telemetry.go b/server/cmd/api/api/telemetry.go index 2b11b012..ca6614b8 100644 --- a/server/cmd/api/api/telemetry.go +++ b/server/cmd/api/api/telemetry.go @@ -206,16 +206,15 @@ func (s *ApiService) reconcileExport(ctx context.Context) { } // reconcileStorage opens the S2 storage sink once the committed telemetry -// config calls for it: a capture session is active and storage is on. The sink -// stores only what that config captured, not what the ring still holds from -// earlier storage-off capture. It never -// closes the sink. The writer is single-use and binds its stream for the life -// of the instance, so it stops only at shutdown, and the storage-off guard in -// PUT and PATCH is what keeps a storage-off config from ever coexisting with an -// open sink. Like reconcileExport it reads the desired state from the session, -// runs after monitorMu is released, holds its own lock, and is best-effort: a -// failed start is logged, never surfaced, and retried by the next request. -// No-op when the VM has no storage controller. +// config calls for it: a capture session is active and storage is on. The +// sink stores only events captured under that config, not what the ring still +// holds from earlier storage-off capture. It never closes the sink: the writer +// is single-use and binds its stream for the life of the instance, so it stops +// only at shutdown, and the storage-off guard in PUT and PATCH keeps a +// storage-off config from coexisting with an open sink. Like reconcileExport +// it reads the desired state from the session, runs after monitorMu is +// released, and is best-effort: a failed start is logged, never surfaced, and +// retried by the next request. No-op when the VM has no storage controller. func (s *ApiService) reconcileStorage(ctx context.Context) { if s.s2Storage == nil { return diff --git a/server/lib/oapi/oapi.go b/server/lib/oapi/oapi.go index e405df8e..6cc696fa 100644 --- a/server/lib/oapi/oapi.go +++ b/server/lib/oapi/oapi.go @@ -6155,7 +6155,7 @@ type BrowserTelemetryConfig struct { // Export Forwarding of captured telemetry to an external destination. Independent of what is captured: export is off unless explicitly enabled here, even when an export destination is configured. In a PUT (full replace) an omitted export block resets export to off, the same as omitted categories turn off; in a PATCH an omitted field leaves the current setting unchanged. Export *BrowserTelemetryExportConfig `json:"export,omitempty"` - // Storage Durable storage of captured telemetry in Kernel's event store. On by default, so a caller that omits this block keeps today's behavior: in a PUT (full replace) an omitted block means enabled, unlike `export`, whose omitted block means off; in a PATCH an omitted field leaves the current setting unchanged. Storage opens with the first capture session that has it enabled and stays open for the life of the instance, so once it has started a request that disables it is rejected with 409. + // Storage Durable storage of captured telemetry in Kernel's event store. On by default, so a caller that omits this block keeps today's behavior: in a PUT (full replace) an omitted block means enabled, unlike `export`, whose omitted block means off; in a PATCH an omitted field leaves the current setting unchanged. Only events captured while storage is enabled are stored. Storage opens with the first capture session that has it enabled and stays open for the life of the instance, so once it has started a request that disables it is rejected with 409. Storage *BrowserTelemetryStorageConfig `json:"storage,omitempty"` } @@ -6180,7 +6180,7 @@ type BrowserTelemetryOTLPExportConfig struct { Enabled *bool `json:"enabled,omitempty"` } -// BrowserTelemetryStorageConfig Durable storage of captured telemetry in Kernel's event store. On by default, so a caller that omits this block keeps today's behavior: in a PUT (full replace) an omitted block means enabled, unlike `export`, whose omitted block means off; in a PATCH an omitted field leaves the current setting unchanged. Storage opens with the first capture session that has it enabled and stays open for the life of the instance, so once it has started a request that disables it is rejected with 409. +// BrowserTelemetryStorageConfig Durable storage of captured telemetry in Kernel's event store. On by default, so a caller that omits this block keeps today's behavior: in a PUT (full replace) an omitted block means enabled, unlike `export`, whose omitted block means off; in a PATCH an omitted field leaves the current setting unchanged. Only events captured while storage is enabled are stored. Storage opens with the first capture session that has it enabled and stays open for the life of the instance, so once it has started a request that disables it is rejected with 409. type BrowserTelemetryStorageConfig struct { // Enabled Whether captured telemetry is written to Kernel's event store. Defaults to true. Set false to keep events on the live stream and any enabled export destination only. Cannot be set false on an instance that has already started storage (409). Enabled *bool `json:"enabled,omitempty"` @@ -25242,285 +25242,286 @@ var swaggerSpec = []string{ "OsSGg26rZE1+EAqR85m//TenCfzqho3QrQZ0INFAw+cUe0kwV5uBwKwO3AFUvGBYindtiK5dujOmvzt/", "fdokw31AZK3XbmAC3Q9QAeSPL1C9W7wfW4BMIvUEQKzk4+qqGczehLx3DYlgxH7gJCrPZoDZe2GRji8t", "kwoEjSuxXwb7bIWtW2Nik7HtdsbHXnDwPLUDH8FwEqxG5BMO7cWIvVO1E/FkFYQN0jk5hFifCZ/w4VKI", - "3DKnE778yrKpWPArqc0zJrfjFQ1A3jv+viNAb3kJ/BNPdxJ582Nbn/tBKHYWTioXylaJU2bSWBfOrsyW", - "i4ew4BbdZz3dIe9UABIYouTgoGIMz0qprOMqFt7FOMZHGAwTShbw0qqKM3h2gNNglAzFjdLqvjn8SxsZ", - "uCXKQEwF2mZ1B0j46EBbsc0z4RgCH3wCAAjvdF9NHS0V9HbGwwGpJxxWC9bAGwIs+hhOOxXMlsNjjHJ5", - "eNXhh9xf4fQCsO99c/iX/f54F8KqgmQnXoaosV14n8/JhubYqU+0F9xgK3KAL1zv/WS9zxj5cfu8P2v3", - "6aPUWmNYOlzEy9nGNHTGETeDp/BBpRP2vm4HwJIVQPaBz/J5AI/9lC8ZPLSel7nk/YAyxKj7CDbgNNxJ", - "X7K2ZsxcWQmaWOsjtdomrRP5hljN6iyhIUFDdXiVv7bOx+H8KWuIcfUP+Kcgvzo46mhQHoKlXB+w/9BQ", - "Ftl4lvK5pfuBI9ruvRn2HK6wzaB8BIYY1Kj0TRax8oornGsriolDMvqVHDLokYy0o3ZOqZi5QTRA4xcs", - "FRMqemszObkCJ229J7QhdSScOfeWb2zj7XK1WcHmhFmaBn6Y1gkgbHJ8KZZtyjudULYc+Bn2B22DNgop", - "PY5a0xB1BIBV7juqyMbYyzZCqZ+sYvpbzLaJJF1mwiNWLrz3QZh33Z/hZn0X/8VijYYaXtWDoxPLNYVY", - "tY60XB/pv28z0gq43gxg6A4gJbvn7WIEQwzeykPa8+LKqArtQnqC7fmduwLvjryR90VlXL2Fk00wFXvY", - "rSdj4Zbl3OArhROp9yoeWEpwkqU3rifxF6oaJafqaGWcP8a3ogEUH07UGw4BH4zQwPfNueGZ8DmpXvpn", - "rVbl79SzkT0KFlRqt3xitvb4AETlDGjGtifEOsGCgAHD5/26Hxs+X+2d6SvRr/cbfSVWe6NXL5CJbZ1P", - "oeGPYlnrS0bvbR3PsFW9m3BjUnNv7SrcETas906F2PpSO4NGHoRrkQTrcSzBx2gNwhp8uHa/jfOmkceI", - "TPWjLI+mcbeNnYeN/NKRamkc0H7TNoFPQPBxeTxt8batWG4Ed+JYGlSeLm/HPLPWbEmlpJGE0Rk0ZHs6", - "Rg9u3GXEMNLpP779dr8pG//Ht9+iEFdLEXc4/I9ffvs6+ubDv7UXRnKLlpDgqdUpUJtqEdAQZohx6yuT", - "HIz+fbvjIszUdpjHIhVOnHK3uN05btlCWHiC09z/wsvc07dbfZuT4slaAYcqB3/5CAw7ioglWEsKh4Oy", - "6QFKnSP2Is0XXBWZMDJm2rDFMl8INWI/L0T5WI0a9pr12aT1syWr4MWHv74Y/v1w+JfhL//j3/qVDD0m", - "6banaqF5XAs0IHXz8/ByoHZVxdSO4rCYi2FsuBPbh/StGbSGgX/4FdxTMcGQAvWCnKHpJBFOxOghvt86", - "6bVM3GL7bNhs4/pbj3aVwT2MPA9UuUOWL2V4EupbA/zAfNwQc9cSBh1Dk7XC+SGli18IyPFB8UEJrJ1m", - "wF4YT3VZW8thNcQyf9Bh251sTALjq6pgbE2VH391bUHjAphrBJ0QrCUr42ptprVbfEfqCzSsQp/SmgYC", - "PexhygGTtfITIvlKMf1nIyvSk8PDRl6kb1s3dpdHDGxhpzdMOyEOCS/RbUHP2D9uIrb8pf5iyLk0trw7", - "tzC6mC98UnRYxBwDOd6AJOlFU8YdSwW3jj1luZbek7dc6eqS61FSZQzFUzy86h+ru9n4I91lA4bhXls8", - "IMk3YYgKxe/Fr3DgcYF57wM04w1f8yVtBDVNgmOy21Qqwb0LZa5TrzFGuo2zoQ7CjnNhxlbMEdIIHUQ+", - "RiQbZ5S6Tc6VbpZRbqSWqTVvbOnbHfGyrOuK61q7wRNaxTo2bMXPtX02H8mH3a/kckkIW7SuXBgWzsvH", - "ryGZ6F4ge0PLY09Gg51ykXXKDqWWr6++bWXgTVqdl/RUrPyK7y0T6Iqrcs8EoCBmUwLQg1ouUGhbG5te", - "sfgRtavo4gy/f5XzufgqYl/5rJtf0eP1K2+c/opdcSNRUU0v0yxPxTN2MeDXXDp00hjNtdN7Xy2cy+2z", - "gwNBbUaxzr7af+5TGrJacywbtbf//GLQno7qc8t71wIPd8p+1+mwvgYP95sBLSx6/RlKobplckofHISL", - "26MKZ/uDD2WmprYsWhTZhuutgprqG2tRFGP+p+7BfMxCz9E+VlaudgDxuuef8lTz5E2ROplz8qlZdWws", - "tdQtuWGIwVdtAH0LHJJMMGC85Jg8q+TQfQLDXlGwO/wII6IRz5+on8l78x0sdCYOKCassirYg4vi8PDr", - "GPrjX2LlCfNi+HfKoz4aD3/57Un09Ntv2x/Lv8p8jMr3tSX+XeaMm3gRsgNzqbyjRqFyDpn7q/x51ar3", - "PK6zbw8hM+hz0paF8HRwaZwJ60b/tFrt13M+TKXiZrn14Vou18eWtV19TR46rMs8T1rcE+tj1wChbdhX", - "MhUQrr1+xdKOE2k2wzlKROjOUuof2kWXTCdYjaEFGLl1oDiRM+kjRkOh+PIUE+7EEHu3XHW7cga2ReqY", - "qXQ+AVrELgaJub4xQ/j/iwHThl0MhuZ6aIbw/xeD9vDEdlj/nlvRyHEDF0jOOesn0VuNE15Ba/0ggnE8", - "XTrRgs9nProRfx6xQzarLUMK2yOwMQSpcnwp1iaLAhzU7tAfehc4UQRrR06dV1U5QrKpV6GNu4MfR98L", - "kfSHw9veZTnVbS91Nyhp1+P6lDOQOLv2nD96//LF+ctBNPj5/Qn+9/jl65f4x/uXb1+8edk7W2GnCPyj", - "0tdqzQGs/X6P26sllDWKQ/fgBCCCqwZJAuRUQGloq+wGvMyPwlPm+I1WOkPXdz9McCWoRvf+BOQOMkm4", - "4+Sfq02GzE6r8q5RKoWlTEWqr9kemWRoSWSr8R57k+5zmETMiDk3CXqboV+aZnkxTSWmvZIOPBbSVJhh", - "9dEfADruvTs7Zwfl6g/8TyFpU5khJ3gqYSETzGpjhWCTlbWUGo5raQSzC54LrJIkk7JgoHfS8akP6pGQ", - "0pYHHPJKxL668lc2ZPwNJvwLtaXcRVktcrOjWaOGahRCe8fxApap5mIcRMrNnvvU7Sj0Ijl4dVCM5t1p", - "wDPosWkw71iyw2hn1KMcrgoj6R2d0OyLfvh9+mLDel+4vr7dj8u25QjkbO9rnW0ZgNrWChlW/VM979f7", - "tZ6HvjWHfrLIbxnhpGqP1sm2cdA+2HeUH8WybQwyiZUl4nsPR/bDM+oWBgbvqDGEK/a85NfySvxNiuuV", - "m66G6X3fYaT1S/cxCrWhtm7zDXU5rvVYHU0qWdbf6jUYlH2mWlWrQ5WJr3ca733otWXQncdbH6se/Npn", - "qCoeKozkg1vGMkm31RPyFZ1OklSs9gbqL9W83zH5cV5Tn+YhhQFNUGD1GcnrrdbHQCYj+g5CrcMoWCQ+", - "pLLdXny/kXHZ9050Nvb+JXhCvQY61pl3e3mNXRojUnB4T5IAo73GDiu0oDEUxJn3HwhaN4eJ8z6947zZ", - "S/Neq9e8uegqXL5H77dl444xdjjHaqy2s3R8Oqbq9z2GOufTd9i2HGKtJvbuJcfLAod9GOhqHeBoLXXz", - "zmmxB9FatsldE3neV6WxVQb/IdqlW+1YenZsI0K7dq2Tnt36tlDR3QaoyHnPfqvQ07dbC0bu0LWdLO4w", - "QEVLdui0gqs79Gwgxy7LXKWzu/SN8937rDOIW13obUZoF6R371zKz7t3bZGVew7SIVHt1ntdjt2t/3tx", - "P91vQT46hOeevRu8qy/AtfG9vtR95b27S7fam6V/t9XXTs+erc+uHfvecupOvcIt+te1HLt1b9W69Byi", - "Vaa4baEPqjQKJi5UNbeoZQ0WoZq1KHmlIpsDpsCiPKGjvukjSkNKi79NKdOsL4aler6aopHnEK1KTiSb", - "An1WDCl6Xlpqwfw+6rKIY77yFvOszMhYV62oXpqsr0Wmw/2hPnWbjvkNB3nqUzloZhzyRNybeyYMJwxq", - "jZNaeGmn1+aOrppdZoy3NQsGLSGi8mGcFLlvTrFkde6EYeg6MWrWrH7q/RjCv59su9xOY+XKbfZyYuhj", - "YK7vkE5RJH6rreCuZzNwRW9zFsSK69bX9cNmzaOr0LF2XVQsbcWrKmKZ4BZjJesZBbExuZFgYjZzif8g", - "9xleuIU20pHLk58/6Nv9FdEAIeISwtekwtKhvcoKtBv4qgNpvTZdWHHqI4Hel2qYVctw3xClEABw+9Ck", - "rhF6hyStRYLsBoX36G6KoRF3dDRNJMW2NryPvn1o91JY807upXf3ufQG3crBUmJUr1s5xXYb7zbwrPxX", - "A4Qxp28Fpn1H2glcbx9fkQjrxtviRGqh1MHZYFuYRTSwJt42MBUb6T3mypGUE0S1XbSd0LvLOl3awSvu", - "r0Ih4373Y1m3dF240pdbofZEJSCbCRvcukbbXbr0ZeteTiEIz8dY3O7Gu4IsjruDK0pC8fSbw91DLY47", - "QyxG7GRWSUGFFbaeL66qbEZdAlU0AsHHy0DepeFPh9HXh9HTb6Mnh7+0LxGP1ts+tt3XzLtgGzErbKhb", - "Cx4zSILLPMlU/DuIfJiBAi3glMijndIYsRIv/uy37tmxaeVcRgW6qv0HdxinmVC2oJprPOE5xYtB5VFf", - "HaXyQ0WYwLNcCJ7MihQTr1df0g7w7IxtOe6MaSnB5uunh/0iXFbjKG/HebdEn/hWJduiVPNLSyEnK7y4", - "DqJw3YcRteVGMIclIrY7uG9gpGVAYLaNo0JuPgyiZBYOx3P0/gy2ff7g1gmj22U21SlOjhON2EvIGg5T", - "MLvQRQqV/Rivta1loJwu2U2indbphdqzQrD/evIE97LM4A2D5UO1gvIj3ovblq6QF4P36Nt7MQBvO1SH", - "0p9HzqT014vUf3r17cVgdEF+jOTejxXdMXgEFshTq2GVVDYe79n6eEoa73+44MSH/8LZ/sc5n+KwP1la", - "Nwi+JIXlhYpdUUppzWFDcl0/ViZVYRujQ+I1HPgFS6UT4IlED0AkErBUHscCUwNi6jbGU8mpTpEfYXgx", - "YJi1z2QoxuO7sDnfSrrKLYCwwmUQKlr5DCV0Bu/yewsw4GWyUbtUQP8UlnhcZ6nczJuxKv9oyR1PI3Ez", - "LzKxGiO0FRu4HRute1TYf180ayZifhzoynIjr2Qq5qKDXHI7LnwSxM1Dcp/uCFrDUBBvCFwv8Ka1zZRu", - "P2vOfnjQIeObXYi0TOuHPKxQrS/e+Lotp482WNix0nTt8bpz4r4f0bt70SRStW1gu6wo1FU3eLVcZ3ln", - "v31YvbCX6koarfDBVAaPwFox6Y829aMfDVogfy0AZLeYj+4L7A7toOvcioZ3iuvgdaQrL6wqDT/Y6R37", - "stx/1yO2vfKKuJFu3B5I5LeKdaIxGKJ9BArzGE//9E27T24tYzs1ZdMC6vWMusM8+g6mC9c92Ifu2wMV", - "9e2I6BkVHkboVaVOsAa9zSujbLsNojY4f/n+zWDzuHXPYN/8x5PXrwfR4OTt+SAa/PDT6XaHYD/3BiB+", - "jyL0bbkJVQdjp+f/PZxSzEXnMcQ6bQHZt+K6qjweQypqZbcF/EUDsBlsGQua7Bg5iKNGtNANJ3aW82tV", - "P7BedQNaWDeYRlZYLFXbEmPnltu54AvfmnGWW1Ekeljufu/0/L/3VwkrvUiQEZVejleCOFIHu2y/tBMs", - "O5+uXZzPv1nbBGpCV+NNd7jStZmg2e2nWScHv6zd6y3o+UnN2sSnQJA4szDaJnxorZX17qy8rK6azf73", - "cVt3sKIJM+QW8F4kvog5vmBamGypeS4KmbQTYjRCjrlrNzJRvdy1Cta+2w52pk5Uc9wVdteEzbV8u4Ul", - "LttNlfJinMct+3tpncww9OHo9CdWoDEuFyYWykFEQ7UNhYHPW9hoVbleNqutQeAt9BNJHxmFSo52BA9V", - "Kw4FHEP9SFp9GVfUwcFb1USn1Z26RrBKVRWdlt/Oi7ovNpHqdkwH6hoDJQNzilhhvlXBRIkVDNbFJ+54", - "L8Eiqc+yvWh5Oe4vW/d8J3kRluOzblgYbn2H3srUBSRVmD42CEap0aCvKshvxQheBYbtIjudvSzrdBqR", - "G2GFcrXKmCGEV5u1Wk13vc3SDFgBC5b5aH36tBv5XzeXtBbBBajQmn+lF2koCSkNLkGHAR0vBl0oC+tv", - "4QKkwKefgwUOjyBeFOqymTUTI6rLOO2eSEyhT3j/d9NDTHWy9CodHDKkWqcDUB67V6PBRhvr3beF2lVp", - "+kvdHuopkitptVk+85U5LiEuzM/us/vB/BbZKiO2upKGvmH/TanAFuX+sLVc8iN2gheKdTPQkg8TFoom", - "jAvrADaXubCQ+ViQzlhaFmhMs3R4KAJYFW6LyjKStTJzVTW+WvGyRqnDsvxVo4pXGRVVxTm0AnXiK8x3", - "1T6hc/TYTsW2EDJ7Ji3HmyNY7hNJWRN2ttPrzjRz5OsgTHskNWhM7aKfRFQ5G4ReXfLQVtUSiXrrn23p", - "mVH7vZFmprf8tuIacevFrpwzypX1dbadeeXB+V7M+6Tw7Gc6+wG/V04mc68P2ZCdrMOY8jN83mmgno4V", - "NNZXljmdD1MxA0ZglLiTq8UOY7Zas8MpROFgt13ZbYxCprzoLXk4m4DRyo2a2Tp3NbSnjo9vNtumftBG", - "/qoV5oLEuRjPdAFltcjD5kr475ZhipaIKTHnje9wD+1MnFawJTfb32DFcY/5wVjWMn2Rt09+F2eSMl9o", - "f/3+NqzgzmdIr5KaNqfaHSl2HrK3h8daptcdqZZMEqG2JJ/B8WtmPt9pq5uCb9exbHBwPRUmk+iyaG+3", - "fqhMnbfr4PAnn4XBsL82FBm7pvtoScH6p2++2d8t46q+VsK0rxV/QiNPWO9PHevtkxqCshTk1dmSRZqM", - "n77wxC2zoW5I1VFPHbxjGW9eWFFPBUX1PnMRA+4npRlhRztE3ZiPOYPbzBD1pFuHh5ut9auv7drkrQfi", - "uHGv7M/glXOfCW7L7MOoGYDRR+1pswBx5ZXYrsItsd2Px8q+6bKHO1KncxWewB29sLEgfbvz0PtKtg2N", - "4IpnOWDslTBGJsKGZ5M/gf36nT893KYPbtWOhrfbml4Tn0orvtjeZdrpUJ1f1jKDUTW2yjWcCZX4bJB7", - "1uk88p7kwFCpLDQl46Xq56B7voZeGebtwvTxKtSaKce095YIuKZR3cm7POM3ARdP1BnhXrf5tJq6bj4M", - "7q+bL3bjXWb8BtMJyV/FiXrzffcKMJDD+iRIb77vCUyreVmfdLjDwe5eFInU2/HyyNf/4dCccttamYB/", - "WSL0iL0nHLR17QCISFBVlivfy/tRArycFqkVL/zX+FK4eoGqPRgE8+QwKyB7jXaLWjWmfQ8tvvJOw41d", - "WlrREGvp9Cx/c+Z0flfSoE0sYJztJ3mSZSKR3IFuBBCrLPc6NzwWsyJldlE4QDOfJShDp0RUeGKRp1gb", - "U6A3Dm4VYaTdWHWHsBFC+Y+T1Rvmyu8lq3eVLkhdiVTnu3rSnmPyZOrKSqOR04wHl1jMdMhWUh2tSwOl", - "unRj6v9mwiksq/CvTovDMNNKO61kXLrWMTK1VCvlsdHWllW30OlDz2pISYWP0TsIstMNcebhybH3HS18", - "nBQopb221DMIaSnJMend1kI0djAqwx6DPvmXjXfYFVe2kmmLwk6upRHDVFyJlL5SdqjKc81n4fI3V3I3", - "pEYhU5dWK7sfsRdmKp3hJiTM8pI3laX32beqXFNAIBMabMReaVMmB9ueEixqy+WFKxZmCFMzAhuW6Bhd", - "ybBQL9Xq9vrBf/dJsg5WvhzjuDX3xoitZwJrLYrSV4n8uahiq9v8z7N3b0tNbNtVpdL6I96cHA2viMZZ", - "u7pmYZu2S6E7hbO/qzLYFAquo9UG7gLAec5c2lXIDIRlcyAgshwENjDzVbdR+khlJjtiUlyLAPWTkjes", - "jIqkxw6QppWEw9VBeUkRurDrGvfoFQ/2sVThtbqU3O3KWoIRvqtG9rp3KYTKduiqf+ZpOoyxBGSIwvNK", - "ndphNsbH+/VDUkCWC0nGG1UQ64W3+3ssRL7O3c51lsvqyolBGWBM2NdWmiIrfBZ1VVls0cutSjjIy4R+", - "LJMotkxFjC96eOmAm+lULKSvOkUKFFtkWcU4Q3ci780DJHUFPGGYkRYQOgado6/BiZhCHBNKggpvwcX4", - "Yjbj1lHhUOXNWNTACA4l4BnGglEpKxot1FgHZ4ipEIql2qK8dc2XlnkjMbArZB2WSgBSCWwm3XPGp6EB", - "922gU8Jd0FUizkceaPy112v3/iqMHm1k9O058m8nv3gRJeXWrYlW7FgLWh/s2tVuquVudl3xmosrDDqg", - "fbRSgJViTTvr1u9WcwQ0z87oS2Fb6wS0On2139OtwhiDn3K1jhDGWQtnBH5yIxKGmx1dqNWqqWwvwFgW", - "AlgPklAxZp9qqgL3CfE/F8oHbAAhh7lQeOWK6aD7qM3XOCm2h9++O4Rz8VGWUBS1VrsC6+3BqS1z4vXX", - "2iRDixEM6BrgPenLnUvlDB9CK5rQXiigFIpTAleUcOjnHOiOJdmU1kZ8Ftay4epaa7ZGHQUEARTxXIHF", - "eeF1oa0ra/d1JODVkH9UxWIzLJ5C1f0FB4lNGJhDM6n+6evWG+7Ec6Cyjl8KknxR2qmq84L7q815LCog", - "YIdQWDldekZk206A7VmZCgWl/erndKGqZggbvrxtqfM4HD1phfrgjda3eOLPYvrm6PREXWlKU+HL2u6I", - "6sGzJUjFunAxFFv1Dg6tIqss5xx32Ld7V+bwhTE2FehY3eetUhkIY7Qpy9zdYkfk3NQmQDpTWMp/PRfD", - "ULnRO0OFlMOWktU7IzgqM0FdoZ1QTnJ4pUMsUix1YYPzm/fqK1rkCyy9AfkibTH1tgrPizlTWg154TT+", - "5Fgi4pQbkkXQfIa5RHQO8gmIHIVDdkWtXbMoLyAmljDDh4yKBRWawHMcRG2r2O7S3jzlcoubL/3ylmkD", - "8CS7+7RxkXMg3tgvoncEvS+eQLkBHyuKrzErjITosVIe3h7zUit6Uik/t6vSgZ2MUUz9rZ4k5MnTP++W", - "JKQcJ/Ln0n3mcAg7HjXWAcfD2Jqhp5rjRa3TatBRK4bmcJ44zLZbXdtZSGSyNmq/h2y16NoztnYzq6YO", - "/i+srzITBmVHsHMA6F+STCvBbZjHjsKejZhL6/zTClzNpgLoL1CCK55Kz3uls6U6hdVUAMEfEo0oWOoj", - "6fFsrIDBZySpb2DlqMsz2gwxL5ogsJMhs042p2LBr6TGyE6sVAZiifU1a4h7FyXFpXhFys8uFGq2UU9E", - "2qqWh2pJGtudruBRhQI/kOX2JkbwZAwq+/afy7WF3LVtzVauoxqyrf/qqqL6LjbfySvjwX5Xy2FrgMKb", - "8ChCjiVVbATHx2WbRU9kU4FZl3C8RrFv/+ZfgeDtUSaFSbvrQNI0P71/TRIdPhwNp6JlNQXNZrwo906T", - "bT7cs5Jy7Hq6/QOPVq/yw1rU7svmOfvXNVAU1DbAOQC2R0AzsOxmqVAjFzNQQoPcUu9E6rOms+CHkKxX", - "unRD8U/8OTySmzN0OGbMxXjjxcKVto6300VHA8gyfDeoFszx6b1A8rVUib6+83LCvDTcPaxsBR2qZZbH", - "14CC2vVFHrI3o4ztnTWmiTUAwc1Klf2QZmuwPg3cumgjnShL6d9OAN38Em7EwIRiPGHC21bU/4CCErk/", - "e1QdeNPNCenfXpyeDKLBlTCWlnM4ejI6hB3rXCiey8Gzwdejw9HXvhQNbuQgpFY5mKV8Hpxs4hYvmzfC", - "zAWmScGWhKPiRlpU52klbMSKPOFOsJVBW5KzQFEWW+TCoKN/EpECAwsPFsrJFE+ubH0srhDG2MUADSIQ", - "4XQxwDyKqVQCPfinaFUAIWOmTaiABysLWYTwoQ53SH4XCYonLl6EWV7h/ukqhHXf62RJb+iS19fSRh5A", - "JTL4VgmtK9wgnOYK6QtbojN0mmV4rL5+1j8uBsPhpdT2kjJ4DIeJtECph/O8uBj8sn/75BW0oHawqtp5", - "fhASOOE8Tw8PWxwCcf103ySslVvzl71al+9DNPjm8LALw8sZD77nASepMuiHaPBtn36YvFjx1PfCSoJZ", - "xs0SHvIEl+USU16oeOEvARbv1zyIBjfD0hIxrCyPlXUQBq7gO9fwuBfb8aawwlSScLkQAYvOjbSC4VBL", - "VrnWlHE2U17+jBXwogu1FaHY7vh0oXZFqCNhsAZxOAUo1MfnJKdfequymhkeikt5OGdllcUz4YB62OhC", - "YZb+IRapFUk5Iu2jHD8AKvLJo+PTg5DKT6t9fC1MwRolkguFDgPhLLfi/mm4xtujf39NRJ/LH7EfQ+Ik", - "/xOm2blQez49j9dlHml9KYX153gxID+42oPKLcoR6OvoQp0JwUIJWIRkUa1kNNd6nooSsA/wqKvkYuE7", - "HakvIAv7/55bGb8o3OLdlTA/OJe/xJD2JJxB64JRVIHG9qd8bngibNnLs903/OaotMbbU59lH7JkRYNT", - "nRe5hXD7a5G80uYnA6LEPwYt5W0Hv3y4L8oXYOWzJX6rYAd7uQsNpLqmw2ZB1FzbNoUqNqXicIZl2tQr", - "l/5aVQ6lBYkbZ0CX4hYio7qmF6pvYdMRe4exBmZZ1R2tmpOPjC/CmjBZc4YDFLxQR8enpUecPxcgfeEM", - "I1/R2y2ENMwAic1EYCcGvWUseW4A9swKpH04CpJNoimMTsYvhozilAHKy1Q5SnWkm6SZFAiYVZ0WSqmH", - "ziNQ8LncnX8qImi3UBnrZJq2JMwLHAPWHFgEsBqeSCWs3Um0opuu1rSRsmahzO4BgNcweM1UxHXTm6Cz", - "ZG8vBH/SFvlbHiSBtmgW7U0+MTavVRFu4FMLtN8do4dcJcNAH+6O3VELavcuWRxdKCtciXTVDIR+Ut3i", - "+VHC/oX6iM+PVRx5oZL3JQ3+jLElamGHdMTlSaJOmyfL3wMqbcEetgeeKDK3+3UuWW6xN3J5Y/jBNDwT", - "2pHoZcj/B9Q9QaVd6vNOhiEYeS9acsQGFVIq4PGPVUdH7IX/1TMiWAJIxJWeOV169gWxgyG0/yZOCwtG", - "C5CgMaui0j4cA20GrIRdy2KuyMkgFfxKIO8JoUrW6dwGL4CZNNb5UvI8ODz5q2GyzPNL/j88rpW9H12o", - "UJu2sOiODkwpXvhq4omgzEPSupojDyaVoQTWMNulWKLCJRzXhQocPedLGMW7hjKjC5UMnZE5g9eHiin3", - "gcCEniqRVzIpeOqHaUPk7/Et4W/nRXAcve1LYqPr2vpMZdqqW8qzOGRHLf1PiZ0lIjDEmFYEqMN0NyIG", - "H98mHmJF0zGCSx0bmzeL5ZfQKeiBLrSa4K73+IYAn7CoxPtPeoVnEt0l4Q4JLfHMwxo7XIV2vUTSqh4A", - "O+m+x/eCJ0c1DWzbcd7XfdIkXsin61xRAIQ2zE+JvHAN8+58/LBpci4r4+talNG3PG/UcXcfeFPJ/kDI", - "067Jvy0CofY+VANxujqk3w9N/JkMC8Hh7j4ulCqAdN5jGU7/QFe4Fq7f//buZf5auYM2TMWlsSsZKrKX", - "Sp/fDUj8IBOfwFhfN2u67AQH4Py6zgxXXagxA7NKKOlEIOrTwjkI6w2usOmyUiNwWJdx5HuKYSqKKnpg", - "7Caudy6vBJXK8PJ1KrgVKACGMiWW8VII/sdNxJa/1HNJ5Fya1vfVcXDofSDYLce/K+WBgX4nLBuXUpXT", - "oWvizOc62Amk5lAHCUYZ577iUTeZ+atwjdpID8mi24swtWM/mtrpKMpN3Mcx/1W4hjWfpiDULWe6FwkJ", - "sG2blFsWcXogRFkrEnU3GdcfE+zs0yLLm1CbqHF9gTOX6ToqWmXv5UpzI6yF/EBbSLWwKwvBeAQky7XA", - "hTKZCJmcqqw2tTIXF6qteAVFLGKhgtyIhVCkP1ivkhExK8SFcguqGLFe6YJxV1mk5tKNZkaIRNhLp/OR", - "NvODG/if3GinD26ePKE/8pRLdUCDJWI2WhDL8NGFC620sfUIFu9gFPYLmgWfKiP2R4FJUazXR9I16aTV", - "eOhLrzwQvqxWdrktuuCFIrT8niQWEiPqWjeEy/vAjFqIbiexO+eXospg9lBi7Voitg/+EjcyNQySO8gp", - "cWA1UxlNNkWLVosH0RrvqhZAkXef9MbLtB2suqDg+XfX+9Zp2k0GKQcdu/J52igP6IEG6hByx8E3VxNE", - "a8S6KdI2NKaNCkReVm0kgSP1q1RgJYCpmZPxpWV7SjufoNCnrKlArPSPxlwbV9wsnzNXoL4zw6CyetpR", - "DB/DlCTVVsj27/fKMIMdLSP4nUSNtKk++glNMA3l8F45Bsrr1QT75KaF+jiKmwp5DgIxnYQwOdL0DIdG", - "5II79pYNhxR/dsjIoEOvBvw7hP2vvDxDKrgHws9acsLb0lcPXr8TZRstphJH6Hq4Y/x+JcoQ5t5BXn1w", - "6gNd3Grs652UPRRw+bthjLA3Uu7c6Zp82Hw3VazqqAXrH4P/ocj8ZelZDKge8uM0A52lQvYdQqUwtT2e", - "xehCnRoNqYBsxJRWIsvdsubMVX7yhlnv5VEaEC3ZskvzoXU6P8BVUbKfC0Vpvqs0TCPmS+phriVaM7QE", - "12X65JeG2bqWGJeD4b0XalLOPAY74BgjdcR8+V2O4T3jOMknmHXHOVg0dgWns2B3x3wGQCBX/Ep8YHxl", - "bsI6B3AorWeizcqxjNjL0mVj6F026lOAu9Hx6YWqLWNG4aEYlJpizCssHI4ymCthLT5RC0Y+hwvDyOB/", - "FcIsAQZ4JhzW1b5QIex1umQ6BXmYgvxDtL4RjvvxqqxKNFVgY6MLVULapLyUCUukzT0H4WwqrBuK2Uyb", - "hmMLOb00oY60Q94ZpTpdH6xI6coheICSqXzPDSGQ9WFE9aJwk/DYmPiywFzh/h1b6oIl+kIp7ZgSkKXi", - "hWOgkXJ4nP6pgJ5w0BwjP6flnZcpyFbTNlgncosVwKSCh5C0ZN19VgOE6o4jPCPUmHlEQUbsoSi4UdDd", - "lSmEKH/ChXKGKxueNM+YnIHyjFMtTL82WA3CDMzKTSqFqVFBhinVxGwmYhfyfmUccZ7ecBTFHovKCQqD", - "U5/e3Hhbb250zufcoZvgKWIThQ6BcxWzAiDNCTapHDX+fUKpjA78xidoy/ah2WU2Pw9hYKqdzwWIvheK", - "TpYoV0mXmkSr1f8z0Jij0Ai94j0GWAzf6XB0qON/oBkejDTmLGUTv9BJKA8JEhcrFLxCvZPoGrYg/Ja0", - "Cki6t3VXYDFikzpp8nTJEmGqUwNtmEjlXE7Tdo8GOOoZnm8rqaDE417UxJjBwbMB0ogQVfhs0EE7MU1S", - "4ONVXa3KtbCsU1J+qbbUFmT8y508YVbC4eHKxThgXIsD0/mr4Z99UqamQy7LeM7+7//+P0Q8rci4cjLG", - "coSnL86PfmDrLuHt1QN9q3FHfEBtBeSmyia/XZDv/sXgWT084JcPk54LIqbSthqPbH2WkQHFRgm/XWOx", - "Xml5wvYwY/kB5Ss/EC4ehaSJVBo05GhYR2vKUkF0L1QTlmXmIE93SimhSt7X9MWtMnQyDeTKv/N8EbeW", - "YiB1B9Yu5AdPIDQ5hNVjCCd4v1yJOq4CnvhtVMlGNjrW7TeqcjZBNwQ51zMTvhj+nQ9/PRz+ZTQe/vLb", - "k+jpt9+251n+VeZjYBz9VAnNsJGyr8f8toCq1Xzink+NPZ9aP03HzehX6wIjq1M7EigsHu+k4RKIERQ+", - "1R1NEMzndsQ8kyndhynjs9EYPOyMrHvD+87wP/YgVOwML2ErUui/hzSU/MfZxPuuH5yWcd92sk9JDCdw", - "bvm4QokJFRNBIkrX7T2swmbROdeX87UgWmCDa8PzXBhWW08jj1DXdUWDUrJqQeP3r0tjsReuxIpoJbZI", - "SkFQiliK+QgAqWJOuObY08Nv/kwVi6IK9eACY4xgIVERaYS/AFrFNBUdFSabZ7nh6VLlbAoniKbCqi+l", - "DzUyJ+eHFZgsoWIPJJcyMb8PlwRUhXPb71W68ndlsG5KzEQvn1fK/hIKyhQgjefv6C7v328O/7K9Hyww", - "lfHaq/l+nG9WZbrwyu48JxGeTkTLy0ClhOULbsXKA/0FvY/x8VK9jVEl5t/MTakfSlqvnT1ZN3v5jNb4", - "cxlc1hLF5PnuQxkj1ln7x4Z5P3vI07d+nT95rwx/YM1r+GQwfeeQnfbt9ASemT2IjYBKnGVVagSkos3N", - "ERuWefQfytexOctOwPRkU9p/2ufvSJNHO2Ucw6WT2rH2vTnKat/j5o6x4UPfHM1yyt3izq4u5aXRFpO7", - "Yec32/u91e4VOHjfo48Mrpzxu9xskMc3XOorErt/3/cJi/wSrtK/cXrfoq8/ARg6/lViwv25cG0lOVxh", - "MH/b309OWflqqb12wiOmTJFelXkJ4DVad23z8x9L83eZb1NdldVwyhFJWna6fJWAEBM21aXz8U5gTSip", - "K3y2FtD5ZSchwZ/rnezgcOphj2WlAQS9+gF/jpDrL6tOhhgPgOa3fGuIti7pAdLhHb/nuKk95rPgcoIy", - "NYy1vxHyL9QG0Gd/ty5hejYTxjIr50rOZMwxM6dPaBwm9LL4hUpE/RP8zQ29ZiEIkZRHPF5IcQUrmQq3", - "OgoiWrtLaQ3v4Iw+F8SL1hKR1LaLflEj9oOcL4Shf9mQNprZDJNcVqoVyCwJ6VYZuIYKsPIM6Sase8b+", - "F9w2DcGeRMynQ4SLhYoq/+vrw8Pht4eH7M33B3YfOnoVcbPj1xGb8pSrWCTU8wBvgO39ryff1vrSxTW7", - "/kfkP7PQ5dvD4Z8bndaW+STCr2WPp4fDb8oeHTdSg5YxDtOh+A5/VYpvf1SDqPYbLRn/sK5TC96fbnrs", - "vRPhPF/R0f1BiOeKanIHAorqpZCgyRPOJvEAWQkL2PalGkgr/MHD8EybplDwe+DSu0me5Rm0gBz8xqQi", - "YL3zw/2TABb4ddd2wPiUHADWbm8HwEqldfhesJ2Q9VpaLB9pb8mQPk9YqnbdAkzVQzOldBqfITTBBslO", - "QaHet4Ee8JLvfGiCA/tpdccP4fd/H49MGKem3PkMbxJ3gAZ+tAvejSBgUtmgQGilBxD56dUH/cgBLieI", - "pjD+74Ui6NgJN6SaJneWaZDBtMbafmbgBPfLGibQHcDHCmIn41pB3E4KsV6X+OECQTsKIN86UVc1VAjb", - "/AyvGiqRrBGLei3jA6yVbBcy3wEGyDLd7SKKSdVszYDts4xoU3ljEWPy0U5GZNrTEQpJHnWkuwliyr15", - "9ZSSUYfrRCKsG2+pEg1tpPJGO08FfRJXL3r3qQ8dDW7rZeG1j9VSt7tZtIxw2/SeT9rVurX0V585uWxJ", - "9DPzYLgbwgRV78b8VxzVTOSpWctiJ71bX3BOWFF4rUBgF/qQtvfekGdX5EjqpbZrSbwq7xbdD1PuySdp", - "E8bcEvT/LvNm3je/zS8GDXg9F9sKiN4CI7yyaQtK7Koq7sKcC7UddbarjBsa4gu1oiLuztXmdb73hn6d", - "HnLnC1EeWTitwIZ6+IR9MrRu9+Dqqu31tr8Tl8+A79cGa97DanAATsMhthlW/fZHu5Xcq7R9D0BQXvgz", - "/MKJyiq43pqwXK8myFt5kThu3Cv7M7Z6oLdIbYrdvVRumTEet91aOOInJaHoUEuZiApvr/1x9PJWXC3j", - "6uIFu++0xZ8IHGkzdbW+Txyo5jvJe3ieB7+FS/lAt5IKynm1CpE6rwByReGCShSvNfE6lPKmN+lRtqtN", - "vmmryEtXSc7wn/lVwrESXKMH9a1UZavXeFBV9m1VnJ2houmVfXnllSof7TZXlWDgf0yrbdV+bbOxnOEj", - "3Jf0b0kPUJXW17Paq91Hcw+iwULwBHf92+C/hmdnL4c+od3wvLXK9RuRSO5LgM6wdj1W9abh2N4qIdxv", - "2EuDbXS1VZsp9MPnCMh40Gun7DNkBdLdG6aN3OZAhnni+iiAj2tCIF9TBn9Ef4R3VR3dVLBMJ4Lt6djx", - "lFGfiGHhgz99881+s3D7n775pmuZGdUfbV3WPw6H//HLb19H37SFzGyOOrtH9fQtNTNllsLPnVmjig34", - "c/CX3cUNL9Vze1AdfbthVM8toV8HLV8BGV8PcRNsB2LlkaBKI95aI7V9mpkG/Wq7z0ijzGWtruAqIJTB", - "7RILu80YrZ1JG7K1bUDdbs60yzy1vbfPVjUY+zplg0/GFV/reU92CID1u+aAbdwFFk3x1WdnL/uiEEQX", - "XBsKz6R0yz0Sk5updIabJTste7MYCDbaqGdG2JBO2gdhw6UxPudSWdeobmcKhbn0lVYs1TFPF9q6Z395", - "+vQpxbbjqAtuGUcyx5xmX0GI/1cR+8qPC3/64b6iGLSvrsU0i/OvLlSol25H4eMoldZhBvq9/a98kn5b", - "X9LwWiaCUZk5rK7IrOK5XWgXkW9hGAhrvgoYag+avReziPKk/8+I/cZ8ieAzEf9P9mH/K6oQi1VNfHnY", - "emVY5hZGF/OFD66HNAtfWWaXKl4YrXRhw3penJ6Mwt+ePVWZH2CQa8b973UCj7q1C0UFmY90IiI82IhV", - "JZtPfH7+qU58hXhfM95gPe7gg4T3UV2ttP4IIb28TwYR8Hd0oS4UXRa0mwLjgPvjPnyeKi4aUSWVo9jB", - "ETtR3tg09MUPfZwVRgNjSng6qJk2Ym5oXD71gcWlcapZQJGCD3UulK9NIPzUtszqQCu6UHnZqUxZb0Ua", - "Ksrjd2lZoUr946iCRfgFOnxPkx/RZ4r41NfKL7wcDktnspOZn39IJ4JCGHmhxsKX2UPtylw4/5CNapdQ", - "xfGjahQhrFY/hqJUA4qM/EoR/J32S8EUfrTUkEND3AAdki5dtilDPSmo8P+IJK2H0MWszfWJYtBa1gGo", - "0R5cWKLJ7zGhfrUFzKZ0hisn3G4h0j3TDnn2jmykW3d3Sq1gJQ+WOrGc4RMBSmMFXSBSFcwwvs3votJC", - "rLMMqF6N+aS91S0BBGzOr9VWGDjDVg8KBDjFp4UCv4QuMMCfRfI7u31+p+v/zf+B6rZLmaZbQeFHmaYd", - "z7Omqq0aeeMLrXx6F4VM7vK6v9WVw25+l8ns3/34Wbo/ATmSc1ANYTKl8Iq8PUxSPpmtUPmemn0xcEn7", - "eYTM+/PBhPNknJ2e//dwSjm27gM86Z3WqdEKjIVafWzofGBuSZtqY5T+l88yIMRfALPhzu4CHInsIVth", - "qy+GcuF2PrEcR0vokuO+X2IdO9LKf7aK+Iq/Mush6E6Qqgu3TT9fHS+oyzYp6j8RTbuDwrncG3TrqXoO", - "568LlxcONVCpnAnKevtom30w22wN7nXhdtajGxFj1vj5QeUj0k6hKeHE+9D+QfN7lLNsr0GwGuHvO366", - "zB6fKPFSmQ8kN+JK4vuX0eWKhEEOfb2TibIGFz7iuJMShpDkOmhsNN2fVO5gZWx2uLaQmszpMrdAxLhl", - "OUdnW6dZbWno+eX15zoDFuYLBVSJnVfHlbYctztFLFLcduM7H/76Yvj3w+Ffhr/8j3+7FV3GuzjI8m/u", - "HBRWAbu/2QZ1LX8dvpJK2oVIhi9ajGPnMhPW8SyHu8Dcj80LmfnOI/bXghuunKBrmAr2/tXR119//ZfR", - "ZqtsYyln5Kt3q5V4P7/bLgSW8vTw6SaaIa2vMC8xZfXcCGsjlmNZN+bMkrTMlJO6edzvEZtezOCH9WIL", - "xXxOmQewuhwW/5aKUW2fenF6syTsqTZRegI/afEE/vAZpy+gYg8WUVSgg/u9ECuwkm6MNafLhlu7o+hd", - "xmxt4mZhNsobsBYItYbRr30FKlOu8t6CsSG9vqltfseDzbi57Law0z4t4wwoaMJ8XndFsO494CsDajks", - "5qifSYVZWwkmuLkUJtSg+SeZG2UInfDC5ZvTb4AnxAueO2FCn/XAozfcXD60wNKY4wFdrndYQ9db7w2e", - "U4lofxjR6EWSlJBJsOLt+VINA5mvYHJ33EDGtMXt/6HBsDnJRrH5ySYW6JnsZ5h5FE+gLNRVpzHvwA+M", - "6gSEbebCsJNjFnNF1anAp0UYSg3NkWqNbgMHOt8EBjp/eCiozXH7t5N3w/+0RaGczpsCYP8LydPtzmD/", - "ya+4dyBA769cGAtAoBx7qxMx+qcNzjDs/cvT1yN2VlajobIVC5Hmz8BXaDKZ/NNeKJh2BB/39p+zrv87", - "OGDIjTPhFjpp9LoYYOWxi0Fb94MDdgamJFcYEZWVN6Lw0CkLEmHa9+aoa25fMAOuGhb/4orLFKvC+CU9", - "u6DSZvH/Mxyy71/+9eQt++vLty/fvzh/eYwnwd68PP/h3TF7fXJ2zoZDbCwgQRn8+IxNyrknkf8Hun2X", - "/xKZdCfgKjaBTt9X6aed0ekzNoEKIRGbJIZLRcEM8E+QnF9pgx/g33Pt9E8mhT/B7QcELPib3O18yesz", - "7wAHP+DZwh/Ol+GCv2cyTU9UXuA/cl+6Ev6mgnjYjwoAVkUJ4SP64vEpLszXwT3nU+x4LV288P9Q4tr/", - "FafaCv+3ULYw4r3gqf8gZ/BWPkc3qbDVN/VNv9Y8qZ8BYIBytS9vhbvW5vIkSfGY/4mdizJpAfxr4Vz+", - "V+HwzMnR7hmbrLoWTqLyWwUukzpAvHx73A8cLpS/2aG/2QBfKNnxEuqwECDFx/giWFqxiffgmZArH9ag", - "mBn9q1AXqs3dMU6loDpC1cDchr34Aj2+48h/HLEjnWVaMTi5GeSMqCMzx5eaB7K9i0EoJuAxbBTrjNCI", - "GtYuag++xhp9kYwQ7DtGTVohs9Y4leqSfYd9Rkonwo5mUiV78Cf7jk6VwT9GRqeCfffdd+xiAH0uBliW", - "8Omf6H+pDabqoTZvtGmkJhuNRrRyOWN7/w+MsO89MJW4ZkiJ92hkprRjMxDg6ltFRNrDfs8vVFg9Rr+G", - "ra7hzN7F4MBl+QG69eVqfjGIGCq82ZM/HR5WYzfpw95vMOqHGrE617kvhTuVClgCFQRKlopnvkqmzLxf", - "ZqaTIhU20HVWKCexdpEgX0FSmxKp5DFi1Ii9vClTS17xtPClH3xBsedMYKUkeoMgI6jRt73RaLQ/iYCQ", - "WQ002MM7lklboXzUdsROpVJQLQRT5KNfm4fVyrt5GGsjJgwqIfE5redCVVDuHXDDEbAJ7X8PVoIjxUm+", - "tz8JdTQtK5QR1hmJ76pjcYV474ETPV8B4QwcViZIGLQs5b9Kj5zSgjsoub0Cc35xehKOEiqIWeEi/OYL", - "w0TBnzi6ULHhdhGxd+/eRP4CnI51WpYxSGBdemkxaN46jKpQSQiAxK9HP50cP6XDHMsEam+W3mh0U1Vd", - "P6Ac0jZqjDW2vuoQrLB0WM178EL97U3E4Al3xVPhX7OmAExFCPQvUr95XGrNq7wa+cXpiX3OZKhyxixX", - "yVTfiGSDe6onne9BkHkYQbE2Q+PN2pSVsIySnx48rEMxmlRm0pH27c/sjfw+qLDodDFHAUne5x5EjPgn", - "lmTj8P6yC56KhCVcZFqVw6PhAnW3+P0r64dW4jqVSkANVj+r7zGEz7QUSoCptBoiEBWkZfjm8HA0+JgW", - "18ah9nOx3fM+toARtRIeHif27/QMe/L1p3XLa0rYNe9ylBt6eufamKfC6V+F0VBUBIjextrxZBmEyf72", - "hurnwAiYt1kzGCWC1x43SYqnPmM/nJ+fMmf4bCZjBpTAjdgRT9OQ6hnAFyMdpIUhr0E9fA1JhKVjUxHz", - "wgr2k5KXhs8c/coLp4HXEkPCtlS5vqzoGYjH3960ZmqmbZ7Bzs/134XRgz4R1Nh+6PQQdsn8WSX3cqMn", - "ichy7UhP60fGcxXhVGtH1PvhXL9aoTbf7HthnTbC+hpPzDY2W1YirFYRgcJTX6NWH8+7uVxS5KORQSap", - "oCunvqXl4W9vmNI+VzRW1LTe3LAQaQKizmVrecaX6u63J9QDXR4NfPe7K5tszbUOJ+nfSKzs1awLM2Kh", - "8TeH3zA5q7XzTDM0b+eafxXuvFzPA9L3chLw6Wp1Bzxv3+BtNaZr/lgdB9jn1qKqENMK0eTGV0+nVIN0", - "ZZ1Xhco0P4MUthZvw6woKX1NaFiiyEBiXPI82GnrQ1QVeaUpYcUKB6FAdifgYGfUCzxE6ksHmA+nAmDv", - "8esZxCBZweJUcGNDZv92wPwLEYaJddrAM8YPMYFV0CiYxL8qMYuxUxgCmBrBk2WVp4RGeL4+H4yVihk8", - "Vvx5tYE7lrVqAvyDCYjlNPUKVh9Poro1xn26tJmftu7W3QhE0ULHz4TbQhECjjw9fNLEz2tOCFrzSKlw", - "9XkZxPr08BD6oRrFAgqnIg7YoHM3lOoZ45XoBGhFyAej1+nIHl+pZkePdKXdglxASPBCxYM2gUYEshAk", - "pv1OcvA8hHEyWfJULy5sokm/SxpSuE9HQX73FOM+bbO3X5AV7nM0w91NTGkIl7WcR+3PghPl9QqKfEIr", - "T4FqCeSiGrE5d5XeKsRNryy0TswOiXpgawtxPCJhQl2JVOeieiT4aS3jSXBAe3r4TcvvM5mShXFP6TB9", - "cErTpmr7la1IkrQVVUKS9c3hISPdpEx8xXTSFLTj+DSVtpIUyJH3gfzdaS6c4hP5u1f79JfUGr2K15HT", - "alGlG2405iaUUq7u28JWVCxGRBVa3m00II9jkSN4Fa666c2w9px4Y1jKHQrYNvDP30QPlNgdHddc4lcz", - "IQksroXm0aZ3eDU3ofSIveTxgqHlCxmcz4uQsYlMnrHfrPjXh4sLBd7ez9hv4ZKGABHw/eJCTUBSoNvx", - "JZVJN+kVssNMK+20kjGqZoMVgMdGW7tCaL2K+Tnj7DW3boh3Ojw5Jv0R6G2CBAMdVSWdIB7CsjEWOgsq", - "I9r2iB0bndOiKAyQQGLOcxueSROZTChrxTMUncjcLeSVSOg3aSnps1twxZ4wDi6HwWk2hbVaAQKFBPsg", - "nSy7FgZICam5cQfQeFrMZsKM2BGayiyzC12kCXOGx5cto6H/rXAidrjeEXuFyVGq7dsgW60cGQoo1bTV", - "a85fFVn48LEo0OJEq36ODr5s8j/RHLP8jqfphFKoNobTaSKs8w9GkZQQbh0UfkB187WE817wXIScFnOh", - "hAHbSJMSTkbslTalxOhPT/jnqcfdH4VRIqXUJmwPmoPEmKbCWFZYn91Px0UmFPRC6/JkP2qQ8wmVfgeY", - "0yYrM2hnIT/gxEtK/47LOsbGRNSiKuPGdOkHb6P0FArQ3N7Wgjqgos5CUXUUbG0Tn0bsHdq7DLNCJeyw", - "5T7C9ebaSnoM9MPJiFndRCw0txEaCUAz4y3CfiruyKdwxM75pbDQLxYJToSGgwnBzYQYLxqVaWJhhXI4", - "HRAkUM0OjfBgXE2XCg4w6QGJPDCHNCTc0EJarFtVFVUj19/KY7yBBLtlqTpFwN8F4EfsPayKUBqsrZZx", - "x54cPv3mOXYogZnXKAEgni3MjMeCzCUzaawjZJ8bwQkKgMqMOmvH0Ym0B9mk6eCXjxym1Ivjv+7BjD67", - "lFmrO4AbPRPmSpjhmVCOlRSgF4Mnj4gDcvnYJGxfYSoopG2YCyqVV8F5Ljw+Q2gHUVCt07ERsxF7q9UQ", - "kM8WU6ApiYhTDl2uiOtfKId2aFIJlDRJSEPc0ZMRnRcpdyHnOlfkbyDVfIzjkjBNsaoj9s4tYBAY90JB", - "O5+00gmTScVTn78kYlLFaYF+b146qMrdY46juj7TyUxgjJtfY5WI6kJNxVxSrifBLF5GlaqpcLHOxLhQ", - "l0pfU+F9JaiFK8VOWGvTetRG7OkayPMFrPcPJNHTBDTZBhMxugvwa7ZqKsbHS81O/ASNuXlaWPYN+1F+", - "D2hTyt5AwlGy8Xbk0oD8Uc231Y6p+wYb7sLoTBZZJffD9VWwgPcrJAJgBbRkoa5hAcq72lS5xNaAc/R5", - "RORCr28e7B5e0RO37SKqRmwq5lxF+ACTzlJQQcA7FqOwq7RjU8H0FLETXlxNQxnCOqZrtjGApEjq+fR6", - "Gqw9MYUetkch4pCkD/BBEUGszdlwaCPiVHNR8d5xYQSiY8JWxLT0ap4uvbZT50Jh/jrMmbdkIpuKJEF/", - "GEXqTAnKUuYW2mJaOXIKeqd8OSGDwgjCWRSEY+8llGklnTbhEVStkU/JPSYktENpDr0ASal5oXBV3Iiw", - "BZ/TD6aPQjf6tLZe6CoSCsnCIfBFI5I1OuodnQwVfIIHVqmjgfPQphqbXqW4zNoZuoXIGDpyoreGZxLC", - "AhNa4inhkxaJeLgK4FE655ADP/BCGrfkk+TY1MFOwYit1dynQVyvzukWwh9PBJugI9IhH3HbfrwfWIJu", - "Dj9Z/zWsDSDHZ3wsGRKZxoWxLNGIQcrH3WVc8Xl5zywR02I+h9uvPxK1YbaYAuhPYbjSfTNIXu3W3Iq5", - "2cGDE3ycZlOOlyP/yGnLrTn6lLF0nkytEIw1MtGHcH348P8OACh350IXmwMA", + "3DKnE778yrKpWPArqc0zJrfjFQ1A3jv+viNAb3kJ/BNPdxJ582Nbn/tBKPYORFj/0CyPitJChUOsCnWj", + "JAmfoae/J6ZzoWyVcmUmjXVhqDLPLh7fglt0vA2DqcSDFwxR8n5QToYHqVTWcRUL75wc4/MNhgnFDnhp", + "j8UZPCPBaTC+hiJOaXXfHP6ljYDcEtkgGgOturoDmHxcoa0Y7plwDMEWPgHohIP3ddjRxkGvbjwckJfC", + "YbXgG7w+wBcAA3GngtlyeIxuLg+vOvyQNSycXrjhvW8O/7LfH2NDQFaQCcXLEG+2C9f02dzQkDv1KfqC", + "A21FSPBt7P2mrPc2Iw9wnzFo7T59fFtr9EuHc3k525iGzjhidfAxPqi0yd5L7gCYuQLIPvD5QQ9ATZDy", + "JYMn2vMyC70fUIbodh/7BjyKO+mL3dbMoCsrQeNsfaRWq6Z1It8Q5VmdJTQkaKgOr/L01vk4nD/lGzGu", + "/gH/FOSRB0cdDcpDsJQlBPYfGsoiG89SPrd0P3BE2/0+w57DFbaZoo/AhIO6mL5pJlbef4VzbeU0cUhG", + "v5IrBz2vkXbUzikVMzeIBmg2g6ViKkZvpyb3WODBrfeE1qeOVDXn3maObbxFrzYrWKswv9PAD9M6AQRc", + "ji/Fsk3tpxPKswM/w/6gbdBjIY/AUWu6pY7QscrxRxXZGHvZRhD2k1VMf4t5OpGky0x4xMqF91sI8657", + "Qtys7+K/WKzRxMOrSnJ0Yrmm4KzWkZbrI/33bUZaAdebAQzdAaRkMb1ddGGI3lt5gnsuXpljoV1IbLA9", + "M3RXyN6RNw+/qMyyt3DPCUZmD7v1NC7cspwbfN9wIvVeOQRLCe619Dr2JP5CVaPkVFetzBCAkbFoOsUn", + "F/WGQ8CnJjTwfXNueCZ8NquX/kGsVfk79WzknYIFlXoxn9KtPbIAUTkDmrHt8bFOsCDUwPB5v+7Hhs9X", + "e2f6SvTr/UZfidXe6A8MZGJb51No+KNY1vqSuXxbxzNsVe8m3JgU5Fu7CneEDeu9UyG2vvHOoJEH4VoM", + "wnoETPBOWoOwBh+u3W/jvGnkMSJT/SjLo2ncbWPnYSO/dCRpGge037RN4BMQtlweT1ukbiuWG8GdOJYG", + "1a7L2zHPrDXPUilpJGF0Bg3Zno7R9xt3GTGMkfqPb7/db8rG//HttyjE1ZLLHQ7/45ffvo6++fBv7SWV", + "3KIlmHhqdQrUploENIQZYtz6yiQHo3/f7vIIM7Ud5rFIhROn3C1ud45bthAWnuA097/wMmv17Vbf5t54", + "slb6ocreXz4Cw44iYgnWkqrioGx6gFLniL1I8wVXRSaMjJk2bLHMF0KN2M8LUT5zo4alZ302af1sySp4", + "8eGvL4Z/Pxz+ZfjL//i3fsVGj0m67amUaB7XAk1P3fw8vByoXVVrtaOsLGZxGBvuxPYhfWsGrWHgH34F", + "x1ZMTaRAMSFnaHRJhBMx+pbvt056LRO32D4bNtu4/tajXWVwDyPPA1XukOVLGZ6E+tbQQDA8N8TctVRD", + "x9BkreR+SAbjFwJyfFB8UOprpxmwF8ZTXVblclhHscw8dNh2JxvTx/h6LBiVU2XWX11b0LgA5hpBJwRr", + "ycqIXJtp7RbfkfoCTbLQp7TDgUAPe5hywGSt/IRIvlJMHNrIp/Tk8LCRUenb1o3d5REDW9jpDdNOiEOq", + "THR40DP2j5uILX+pvxhyLo0t784tjC7mC683g0XMMQTkDUiSXjRl3LFUcOvYU5Zr6X2Ay5WuLrkeX1VG", + "XzzFw6v+sbqbjT/SXTZgGO61xXeSvBqGqIr8XvwKBx4XmDE/QDPe8DVf0kZQ0yQ4pslNpRLcO1/mOvW6", + "ZqTbOBvqIOw4F2ZsxRwhjdBB5GNEsnFGSd/kXOlmAeZGUppa88aWvt0RL8uKsLiutRs8oVWsY8NW/Fzb", + "Z/ORfNj9Si6XhLBF68qFYeG8fOQbkonuBbI3tDz2ZDTYKYtZp+xQavn66ttWBt6k1XlJT8XKI/necoiu", + "ODn3TB0KYjalDj2oZRGFtrWx6RWLH1G7is7R8PtXOZ+LryL2lc/X+RU9Xr/yZu2v2BU3EhXV9DLN8lQ8", + "YxcDfs2lQ/eO0Vw7vffVwrncPjs4ENRmFOvsq/3nPhkiqzXHglN7+88vBu2JrD63jHkt8HCnvHmdru5r", + "8HC/udPCotefoRTkW6a19GFFuLg9qo22P/hQ5nhqy79FMXG43iocqr6xFkUxZo7qHsxHO/Qc7WPl82oH", + "EK97/ilPNU/eFKmTOSdvnFWXyFJL3ZJVhhh81QbQt8AhyQQDZk+OabdKDt0npOwVhcnDjzAimv/8ifqZ", + "vB/gwUJn4oCiySqrgj24KA4Pv46hP/4lVp4wL4Z/pwzso/Hwl9+eRE+//bb9sfyrzMeofF9b4t9lzriJ", + "FyGvMJfKu3gUKueQ87/KvFetes/jOvv2EHKKPidtWQhsB2fImbBu9E+r1X49W8RUKm6WWx+u5XJ9VFrb", + "1dfkocO6zPOkxbGxPnYNENqGfSVTAYHe61cs7TiRZjOco0SEjjCl/qFddMl0gnUcWoCRWweKEzmTPtY0", + "lJgvTzHhTgyxd8tVtytnYFukjplK51OnRexikJjrGzOE/78YMG3YxWBorodmCP9/MWgPbGyH9e+5FY3s", + "OHCB5NazfhK91TjhFbTWD2Ifx9OlEy34fObjIvHnETtks9oypLA9QiJDeCvHl2JtsijAQe0O/aF3gRPF", + "vnZk43lVFTIka3wVFLk7+HH02hBJfzi87V2WU932UneDknY9rk9WAym3a8/5o/cvX5y/HESDn9+f4H+P", + "X75+iX+8f/n2xZuXvfMcdorAPyp9rdZcx9rv97i9zkJZ3Th0D04AIjh5kCRATgWUwLbKi8DLzCo8ZY7f", + "aKUzdJr3wwRXgmp0709AjiSThDtOnr3aZMjstCrvGqVSWMpUpPqa7ZFJhpZEthrv6zfpPodJxIyYc5Og", + "nxp6tGmWF9NUYsIs6cBjIU2FGVYf/QGgy9+7s3N2UK7+wP8U0j2VuXWCjxOWQMF8OFYINllZS6nhuJZG", + "MLvgucD6SjIpSw169x6fNKEeQyltecAhI0Xs6zJ/ZUOu4GDCv1BbCmWUdSY3u6g1qq9GISh4HC9gmWou", + "xkGk3OzzT92OQi+Sg1cHxTjgnQY8gx6bBvOOJTuMdkY9yuGqAJTecQ3NvujB36cvNqz3hevr2/24bFuO", + "QG76vkralgGoba0EYtU/1fN+vV/reehbCwUgi/yWEU6q9midbBsH7YN9R/lRLNvGIJNYWVy+93BkPzyj", + "bmFg8I4aQ6Bjz0t+La/E36S4Xrnpapje9x1GWr90H91QG2rrNt9Ql+Naj9XRpJJl5a5eg0HBaKpytTpU", + "mTJ7p/Heh15bBt15vPWx6mGzfYaqIqnCSD4sZiyTdFslIl8L6iRJxWpvoP5Szfsdkx/nNfVpHlIY0AQF", + "Vp+RvN5qfQxkMqLvINQ6jILl5UMS3O1l+xu5mn3vRGdj71+CJ9RroGOdebeX19ilMSKFlfckCTDaa+yw", + "QgsaQ0GEev+BoHVzmDjv0zvOm70077V6zZuLrgLte/R+WzbuGGOHc6zGajtLx6djqpvfY6hzPn2Hbcsh", + "1qpp716svCyN2IeBrlYQjtaSPu+cUHsQreWp3DUF6H3VKFtl8B+iXbrVjqVnxzYitGvXOunZrW8LFd1t", + "gIqc9+y3Cj19u7Vg5A5d28niDgNUtGSHTiu4ukPPBnLsssxVOrtL3zjfvc86g7jVhd5mhHZBevfOpfy8", + "e9cWWbnnIB0S1W691+XY3fq/F/fT/Rbko0N47tm7wbv6Alwb3+tL3Vfeu7t0q71Z+ndbfe307Nn67Nqx", + "7y2n7tQr3KJ/XcuxW/dWrUvPIVplituWCKEapWDiQlVzi1rWYPmqWYuSVyqyOWDyLMowOuqbeKI0pLT4", + "25QyzfpiWKrnq8kdeQ5xruREsinQZ8WQouelpRbM76MuizhmOm8xz8qMjHXViupFzfpaZDrcH+pTt+mY", + "33CQpz6Vg2bGIcPEvblnwnDCoNY4qQWmdnpt7uiq2WXGeFuzYNASIio8xkmR++YUi13nThiGrhOjZrXr", + "p96PIfz7ybbL7TRWrtxmLyeGPgbm+g7pFEXit9oK7no2A1f0NmdBrNVufUVAbNY8ugoda9dFZdZWvKoi", + "lgluMVaynosQG5MbCaZ0M5f4D3Kf4YVbaCMduTz5+YO+3V8RDRAiLiF8TSosOtqrIEG7ga86kNZr04UV", + "pz4S6H2phlm1DPcNUQoBALcPTeoaoXdI0lokyG5QeI/uphgacUdH00RSbGvD++jbh3YvhTXv5F56d59L", + "b9CtHCwlRvW6lVNst/FuA8/KfzVAGHP6VmDad6SdwPX28RWJsG68LU6kFkodnA22hVlEA2vibQNTmZLe", + "Y64cSTlBVNtF2wm9u6zTpR284v4qFDLudz+WFU/XhSt9uRVqT1QCspmwwa1rtN2lS1+27uUUgvB8jMXt", + "brwryOK4O7iiJBRPvzncPdTiuDPEYsROZpUUVFhh65nmqppo1CVQRSMQfLwM5F0a/nQYfX0YPf02enL4", + "S/sS8Wi97WPbfc28C7YRs8KGirfgMYMkuMywTGXDg8iHuSvQAk4pQNopjREr8eLPfuueHZtWzmVU2qva", + "f3CHcZoJZQuq1sYTnlO8GNQs9XVVKj9UhAk8y4XgyaxIMWV79SXtAM/O2JbjzpiWEmy+fnrYL8JlNY7y", + "dpx3S/SJb1WyLUpSv7QUcrLCi+sgCtd9GFFbbgRzWFxiu4P7BkZaBgRm2zgqZPXDIEpm4XA8R+/PYNvn", + "D26dMLpdZlOd4uQ40Yi9hHzjMAWzC12kUBOQ8VrbWu7K6ZLdJNppnV6oPSsE+68nT3AvywzeMFh4VCso", + "XOK9uG3pCnkxeI++vRcD8LZDdSj9eeRMSn+9SP2nV99eDEYX5MdI7v1YCx6DR2CBPLUaVkkF5/GerY+n", + "pPH+hwtOfPgvnO1/nPMpDvuTpXWD4EtSWF6o2BWllNYcNqTl9WNlUhW2MTqkbMOBX7BUOgGeSPQARCIB", + "S+VxLDCpICZ9YzyVnCoc+RGGFwOG+f5MhmI8vgub860kutwCCCtcBqGilc9QKmjwLr+3AANepim1SwX0", + "T2FxyHWWys28Gavyj5as8zQSN/MiE6sxQluxgdux0bpHbf73RbPaIubHga4sN/JKpmIuOsglt+PCp0/c", + "PCT3iZKgNQwF8YbA9QJvWttM6faz5uyHBx1yxdmFSMuEgMjDCtX64o2v23L6aIMlIStN1x6vOyfu+xG9", + "uxdNIlXbBrbLikJddYNXy3WWd/bbh9ULe6mupNEKH0xl8AisFZP+aFM/+tGgBfLXAkB2i/novsDu0A66", + "zq1oeKe4Dl5HuvLCqqLyg53esS/L/Xc9Yttrtogb6cbtgUR+q1hhGoMh2kegMI/x9E/ftPvk1nK9U1M2", + "LaDSz6g7zKPvYLpw3YN96L49UFHfjoieUclihF5V6gRr0Nu8MsrT2yBqg/OX798MNo9b9wz2zX88ef16", + "EA1O3p4PosEPP51udwj2c28A4vcoQt+Wm1BdMXZ6/t/DKcVcdB5DrNMWkH0rrqua5TEksVZ2W8BfNACb", + "wZaxoMmOkYM4akQL3XBiZzm/VvUD61VxoIV1g2lkhcVSnS4xdm65nQu+8K0ZZ7kVRaKH5e73Ts//e3+V", + "sNKLBBlR6eV4JYgjdbDL9ks7wYL16drF+cydtU2gJnQ13nSHK12bCZrdfpp1cvDL2r3egp6f1KxNfAoE", + "iTMLo23Ch9YqW+/Oysvqqvbsfx+3dQcrmjBDbgHvReLLn+MLpoXJlprnopBJOyFGI+SYu3YjE1XaXat9", + "7bvtYGfqRDXHXWF3TfVcy9RbWOKy3VQpL8Z53LK/l9bJDEMfjk5/YgUa43JhYqEcRDRU21AY+LyFjVY1", + "72WzThsE3kI/kfSRUahYaUfwULXiUPoxVJ6k1ZdxRR0cvFVNdFrdqWsEq1T11Gn57byo+2ITqW7HdKAi", + "MlAyMKeIFeZblVqUWPtgXXzijvcSLJL6LNvLnZfj/rJ1z3eSF2E5PuuGheHWd+itTF1AUoXpY4NglBoN", + "+qqC/FaM4FVg2C6y09nLssKnEbkRVihXq6kZQni1WavydNfbLM2AFbBggZDWp0+7kf91c0lrEVyACq35", + "V3qRhpKQ0uASdBjQ8WLQhbKw/hYuQAp8+jlY4PAI4kWhLptZMzGiuozT7onEFPqE9383PcRUJ0uv0sEh", + "Q5J2OgDlsXs1Gmy0sVJ+W6hdleC/1O2hniK5klab5TNf0+MS4sL87D67H8xvka0yYqsrCewb9t+USnNR", + "7g9by0I/Yid4oVhxAy35MGGhaMK4sA5gc5kLCzmTBemMpWWBxjSLjofygVXJt6gsQFkrUFfV8auVPWsU", + "SSwLZzXqf5VRUVWcQytQJ742fVfVFDpHj+1Upgshs2e6c7w5guU+kZQ1YWc7ve5MM0e+DsK0R1KDxtQu", + "+klElbNB6NUlD21VLZGot/7Zlp4Ztd8baWZ6y28rrhG3XuzKOaNcWV9n25lXHpzvxbxPCs9+prMf8Hvl", + "ZDL3+pAN2ck6jCk/w+edBurpWEFjfWWZ0/kwFTNgBEaJO7la7DBmqzU7nEIUDnbbld3GKGTKi96Sh7MJ", + "GK3cqJmtc1dDe+r4+GazbeoHbeSvWmEuSJyL8UwXUJCLPGyuhP9uGaZoiZgSc974DvfQzsRpBVtys/0N", + "Vhz3mB+MZS3TF3n75HdxJinzhfbX72/DCu58hvQqqWlzqt2RYuche3t4rGV63ZFqySQRakvyGRy/Zubz", + "nba6Kfh2HcsGB9dTYTKJLov2duuHmtZ5uw4Of/JZGAz7a0ORsWu6j5YUrH/65pv93TKu6mslTPta8Sc0", + "8oT1/tSx3j6pIShLQV6dLVmkyfjpS1bcMhvqhlQd9dTBOxYA54UV9VRQVCk0FzHgflKaEXa0Q9SN+Zgz", + "uM0MUU+6dXi42Vq/+tquTd56II4b98r+DF4595ngtsw+jJoBGH3UnjYLEFdeie0q3BLb/Xis7Jsue7gj", + "dTpX4Qnc0QsbS9m3Ow+9r2Tb0AiueJYDxl4JY2QibHg2+RPYr9/508Nt+uBW7Wh4u63pNfGptOKL7V2m", + "nQ51/WUtMxjVcatcw5lQic8GuWedziPvSQ4MlQpKUzJeqpsOuudr6JVh3i5MH69ClZpyTHtviYBrGtWd", + "vMszfhNw8USdEe51m0+rqevmw+D+uvliN95lxm8wnZD8VZyoN993rwADOaxPgvTm+57AtJqX9UmHOxzs", + "7kWRSL0dL498/R8OzSm3rZUJ+JclQo/Ye8JBW9cOgIgE9Wi58r28HyXAy2mRWvHCf40vhauXttqDQTBP", + "DrMCstdot6jVcdr30OIr7zTc2KWlFQ2xlk7P8jdnTud3JQ3axALG2X6SJ1kmEskd6EYAscpCsXPDYzEr", + "UmYXhQM081mCMnRKRIUnloeKtTEFeuPgVhFG2o1VdwgbIZT/OFm9Ya78XrJ6V+mC1JVIdb6rJ+05Jk+m", + "rqw0GjnNeHCJxUyHbCXV0bo0UKpLN6b+byacwrIK/+q0OAwzrbTTSsalax0jU0u1Uh4bbW1ZdQudPvSs", + "hpRUMhm9gyA73RBnHp4ce9/RwsdJgVLaa0s9g5CWkhyT3m0tRGMHozLsMeiTf9l4h11xZSuZtijs5Foa", + "MUzFlUjpK2WHqjzXfBYuf3Mld0NqFDJ1abWy+xF7YabSGW5CwiwveVNBe599q8o1BQQyocFG7JU2ZXKw", + "7SnBorZcXrhiYYYwNSOwYYmO0ZUMS/xSlW+vH/x3nyTrYOXLMY5bc2+M2HomsNaiKH2VyJ+LKra6zf88", + "e/e21MS2XVUqrT/izcnR8IponLWraxa2absUulM4+7sqg02h4DpabeAuAJznzKVdhcxAWDYHAiLLQWAD", + "M1+vG6WPVGayIybFtQhQPyl5w8qoSHrsAGlaSThcHZSXFKELu65xj17xYB9LFV6raMndrqwlGOG7qmuv", + "e5dCqGyHrvpnnqbDGItHhig8r9SpHWZjfLxfPyQFZLmQZLxRBbFesru/x0Lk69ztXKG5rMucGJQBxoR9", + "baUpssJnUVeVxRa93KqEg7xM6McyiWLLVMT4ooeXDriZTsVC+qpTpECxRZZVjDN0J/LePEBSV8AThhlp", + "AaFj0Dn66p2IKcQxoZio8BZcjC9mM24dlRxV3oxFDYzgUDyeYSwYlbKi0UJ1dnCGmAqhWKotylvXfGmZ", + "NxIDu0LWYakEIBXPZtI9Z3waGnDfBjol3AVdJeJ85IHGX3u96u+vwujRRkbfniP/dvKLF1FSbt2aaMWO", + "taD1wa5d7aZa7mbXFa+5uMKgA9pHKwVYKda0s279bjVHQPPsjL4UtrVOQKvTV/s93SqMMfgpV+sIYZy1", + "cEbgJzciYbjZ0YVarZrK9gKMZSGA9SAJFWP2qaYqcJ8Q/3OhfMAGEHKYC4VXrpgOuo/afI2TYnv47btD", + "OBcfZQlFUWu1K7DeHpzaMidef61NMrQYwYCuAd6Tvty5VM7wIbSiCe2FAkqhOCVwRQmHfs6B7liSTWlt", + "xGdhLRuurrVma9RRQBBAEc8VWJwXXhfaurJ2X0cCXg35R1UsNsPiKdTrX3CQ2ISBOTST6p++4r3hTjwH", + "Kuv4pSDJF6WdqjovuL/anMeiAgJ26OsTEyOybSfA9qxMhYLSfvVzulBVM4QNX9621Hkcjp60Qn3wRutb", + "PPFnMX1zdHqirjSlqfBlbXdE9eDZEqRiXbgYiq16B4dWkVWWc4477Nu9K3P4whibCnSs7vNWqQyEMdqU", + "Ze5usSNybmoTIJ0pLOW/nothqNzonaFCymFLyeqdERyVmaCu0E4oJzm80iEWKZa6sMH5zXv1FS3yBZbe", + "gHyRtph6W4XnxZwprYa8cBp/ciwRccoNySJoPsNcIjoH+QREjsIhu6LWrlmUFxATS5jhQ0bFggpN4DkO", + "orZVbHdpb55yucXNl355y7QBeJLdfdq4yDkQb+wX0TuC3hdPoNyAjxXF15gVRkL0WCkPb495qRU9qZSf", + "21XpwE7GKKb+Vk8S8uTpn3dLElKOE/lz6T5zOIQdjxrrgONhbM3QU83xotZpNeioFUNzOE8cZtutru0s", + "JDJZG7XfQ7ZadO0ZW7uZVVMH/xfWV5kJg7Ij2DkA9C9JppXgNsxjR2HPRsyldf5pBa5mUwH0FyjBFU+l", + "573S2VKdwmoqgOAPiUYULPWR9Hg2VsDgM5LUN7By1OUZbYaYF00Q2MmQWSebU7HgV1JjZCdWKgOxxPqa", + "NcS9i5LiUrwi5WcXCjXbqCcibVXLQ7Ukje1OV/CoQoEfyHJ7EyN4MgaVffvP5dpC7tq2ZivXUQ3Z1n91", + "VVF9F5vv5JXxYL+r5bA1QOFNeBQhx5IqNoLj47LNoieyqcCsSzheo9i3f/OvQPD2KJPCpN11IGman96/", + "JokOH46GU9GymoJmM16Ue6fJNh/uWUk5dj3d/oFHq1f5YS1q92XznP3rGigKahvgHADbI6AZWHazVKiR", + "ixkooUFuqXci9VnTWfBDSNYrXbqh+Cf+HB7JzRk6HDPmYrzxYuFKW8fb6aKjAWQZvhtUC+b49F4g+Vqq", + "RF/feTlhXhruHla2gg7VMsvja0BB7foiD9mbUcb2zhrTxBqA4Galyn5IszVYnwZuXbSRTpSl9G8ngG5+", + "CTdiYEIxnjDhbSvqf0BBidyfPaoOvOnmhPRvL05PBtHgShhLyzkcPRkdwo51LhTP5eDZ4OvR4ehrX4oG", + "N3IQUqsczFI+D042cYuXzRth5gLTpGBLwlFxIy2q87QSNmJFnnAn2MqgLclZoCiLLXJh0NE/iUiBgYUH", + "C+VkiidXtj4WVwhj7GKABhGIcLoYYB7FVCqBHvxTtCqAkDHTJlTAg5WFLEL4UIc7JL+LBMUTFy/CLK9w", + "/3QVwrrvdbKkN3TJ62tpIw+gEhl8q4TWFW4QTnOF9IUt0Rk6zTI8Vl8/6x8Xg+HwUmp7SRk8hsNEWqDU", + "w3leXAx+2b998gpaUDtYVe08PwgJnHCep4eHLQ6BuH66bxLWyq35y16ty/chGnxzeNiF4eWMB9/zgJNU", + "GfRDNPi2Tz9MXqx46nthJcEs42YJD3mCy3KJKS9UvPCXAIv3ax5Eg5thaYkYVpbHyjoIA1fwnWt43Ivt", + "eFNYYSpJuFyIgEXnRlrBcKglq1xryjibKS9/xgp40YXailBsd3y6ULsi1JEwWIM4nAIU6uNzktMvvVVZ", + "zQwPxaU8nLOyyuKZcEA9bHShMEv/EIvUiqQckfZRjh8AFfnk0fHpQUjlp9U+vhamYI0SyYVCh4Fwlltx", + "/zRc4+3Rv78mos/lj9iPIXGS/wnT7FyoPZ+ex+syj7S+lML6c7wYkB9c7UHlFuUI9HV0oc6EYKEELEKy", + "qFYymms9T0UJ2Ad41FVysfCdjtQXkIX9f8+tjF8UbvHuSpgfnMtfYkh7Es6gdcEoqkBj+1M+NzwRtuzl", + "2e4bfnNUWuPtqc+yD1myosGpzovcQrj9tUheafOTAVHiH4OW8raDXz7cF+ULsPLZEr9VsIO93IUGUl3T", + "YbMgaq5tm0IVm1JxOMMybeqVS3+tKofSgsSNM6BLcQuRUV3TC9W3sOmIvcNYA7Os6o5WzclHxhdhTZis", + "OcMBCl6oo+PT0iPOnwuQvnCGka/o7RZCGmaAxGYisBOD3jKWPDcAe2YF0j4cBckm0RRGJ+MXQ0ZxygDl", + "ZaocpTrSTdJMCgTMqk4LpdRD5xEo+Fzuzj8VEbRbqIx1Mk1bEuYFjgFrDiwCWA1PpBLW7iRa0U1Xa9pI", + "WbNQZvcAwGsYvGYq4rrpTdBZsrcXgj9pi/wtD5JAWzSL9iafGJvXqgg38KkF2u+O0UOukmGgD3fH7qgF", + "tXuXLI4ulBWuRLpqBkI/qW7x/Chh/0J9xOfHKo68UMn7kgZ/xtgStbBDOuLyJFGnzZPl7wGVtmAP2wNP", + "FJnb/TqXLLfYG7m8MfxgGp4J7Uj0MuT/A+qeoNIu9XknwxCMvBctOWKDCikV8PjHqqMj9sL/6hkRLAEk", + "4krPnC49+4LYwRDafxOnhQWjBUjQmFVRaR+OgTYDVsKuZTFX5GSQCn4lkPeEUCXrdG6DF8BMGut8KXke", + "HJ781TBZ5vkl/x8e18rejy5UqE1bWHRHB6YUL3w18URQ5iFpXc2RB5PKUAJrmO1SLFHhEo7rQgWOnvMl", + "jOJdQ5nRhUqGzsicwetDxZT7QGBCT5XIK5kUPPXDtCHy9/iW8LfzIjiO3vYlsdF1bX2mMm3VLeVZHLKj", + "lv6nxM4SERhiTCsC1GG6GxGDj28TD7Gi6RjBpY6NzZvF8kvoFPRAF1pNcNd7fEOAT1hU4v0nvcIzie6S", + "cIeElnjmYY0drkK7XiJpVQ+AnXTf43vBk6OaBrbtOO/rPmkSL+TTda4oAEIb5qdEXriGeXc+ftg0OZeV", + "8XUtyuhbnjfquLsPvKlkfyDkadfk3xaBUHsfqoE4XR3S74cm/kyGheBwdx8XShVAOu+xDKd/oCtcC9fv", + "f3v3Mn+t3EEbpuLS2JUMFdlLpc/vBiR+kIlPYKyvmzVddoIDcH5dZ4arLtSYgVkllHQiEPVp4RyE9QZX", + "2HRZqRE4rMs48j3FMBVFFT0wdhPXO5dXgkplePk6FdwKFABDmRLLeCkE/+MmYstf6rkkci5N6/vqODj0", + "PhDsluPflfLAQL8Tlo1Lqcrp0DVx5nMd7ARSc6iDBKOMc1/xqJvM/FW4Rm2kh2TR7UWY2rEfTe10FOUm", + "7uOY/ypcw5pPUxDqljPdi4QE2LZNyi2LOD0QoqwVibqbjOuPCXb2aZHlTahN1Li+wJnLdB0VrbL3cqW5", + "EdZCfqAtpFrYlYVgPAKS5VrgQplMhExOVVabWpmLC9VWvIIiFrFQQW7EQijSH6xXyYiYFeJCuQVVjFiv", + "dMG4qyxSc+lGMyNEIuyl0/lIm/nBDfxPbrTTBzdPntAfecqlOqDBEjEbLYhl+OjChVba2HoEi3cwCvsF", + "zYJPlRH7o8CkKNbrI+madNJqPPSlVx4IX1Yru9wWXfBCEVp+TxILiRF1rRvC5X1gRi1Et5PYnfNLUWUw", + "eyixdi0R2wd/iRuZGgbJHeSUOLCaqYwmm6JFq8WDaI13VQugyLtPeuNl2g5WXVDw/Lvrfes07SaDlIOO", + "Xfk8bZQH9EADdQi54+CbqwmiNWLdFGkbGtNGBSIvqzaSwJH6VSqwEsDUzMn40rI9pZ1PUOhT1lQgVvpH", + "Y66NK26Wz5krUN+ZYVBZPe0oho9hSpJqK2T793tlmMGOlhH8TqJG2lQf/YQmmIZyeK8cA+X1aoJ9ctNC", + "fRzFTYU8B4GYTkKYHGl6hkMjcsEde8uGQ4o/O2Rk0KFXA/4dwv5XXp4hFdwD4WctOeFt6asHr9+Jso0W", + "U4kjdD3cMX6/EmUIc+8grz449YEubjX29U7KHgq4/N0wRtgbKXfudE0+bL6bKlZ11IL1j8H/UGT+svQs", + "BlQP+XGagc5SIfsOoVKY2h7PYnShTo2GVEA2YkorkeVuWXPmKj95w6z38igNiJZs2aX50DqdH+CqKNnP", + "haI031UaphHzJfUw1xKtGVqC6zJ98kvDbF1LjMvB8N4LNSlnHoMdcIyROmK+/C7H8J5xnOQTzLrjHCwa", + "u4LTWbC7Yz4DIJArfiU+ML4yN2GdAziU1jPRZuVYRuxl6bIx9C4b9SnA3ej49ELVljGj8FAMSk0x5hUW", + "DkcZzJWwFp+oBSOfw4VhZPC/CmGWAAM8Ew7ral+oEPY6XTKdgjxMQf4hWt8Ix/14VVYlmiqwsdGFKiFt", + "Ul7KhCXS5p6DcDYV1g3FbKZNw7GFnF6aUEfaIe+MUp2uD1akdOUQPEDJVL7nhhDI+jCielG4SXhsTHxZ", + "YK5w/44tdcESfaGUdkwJyFLxwjHQSDk8Tv9UQE84aI6Rn9PyzssUZKtpG6wTucUKYFLBQ0hasu4+qwFC", + "dccRnhFqzDyiICP2UBTcKOjuyhRClD/hQjnDlQ1PmmdMzkB5xqkWpl8brAZhBmblJpXC1Kggw5RqYjYT", + "sQt5vzKOOE9vOIpij0XlBIXBqU9vbrytNzc653Pu0E3wFLGJQofAuYpZAZDmBJtUjhr/PqFURgd+4xO0", + "ZfvQ7DKbn4cwMNXO5wJE3wtFJ0uUq6RLTaLV6v8ZaMxRaIRe8R4DLIbvdDg61PE/0AwPRhpzlrKJX+gk", + "lIcEiYsVCl6h3kl0DVsQfktaBSTd27orsBixSZ00ebpkiTDVqYE2TKRyLqdpu0cDHPUMz7eVVFDicS9q", + "Yszg4NkAaUSIKnw26KCdmCYp8PGqrlblWljWKSm/VFtqCzL+5U6eMCvh8HDlYhwwrsWB6fzV8M8+KVPT", + "IZdlPGf/93//HyKeVmRcORljOcLTF+dHP7B1l/D26oG+1bgjPqC2AnJTZZPfLsh3/2LwrB4e8MuHSc8F", + "EVNpW41Htj7LyIBio4TfrrFYr7Q8YXuYsfyA8pUfCBePQtJEKg0acjSsozVlqSC6F6oJyzJzkKc7pZRQ", + "Je9r+uJWGTqZBnLl33m+iFtLMZC6A2sX8oMnEJocwuoxhBO8X65EHVcBT/w2qmQjGx3r9htVOZugG4Kc", + "65kJXwz/zoe/Hg7/MhoPf/ntSfT022/b8yz/KvMxMI5+qoRm2EjZ12N+W0DVaj5xz6fGnk+tn6bjZvSr", + "dYGR1akdCRQWj3fScAnECAqf6o4mCOZzO2KeyZTuw5Tx2WgMHnZG1r3hfWf4H3sQKnaGl7AVKfTfQxpK", + "/uNs4n3XD07LuG872ackhhM4t3xcocSEiokgEaXr9h5WYbPonOvL+VoQLbDBteF5LgyrraeRR6jruqJB", + "KVm1oPH716Wx2AtXYkW0ElskpSAoRSzFfASAVDEnXHPs6eE3f6aKRVGFenCBMUawkKiINMJfAK1imoqO", + "CpPNs9zwdKlyNoUTRFNh1ZfShxqZk/PDCkyWULEHkkuZmN+HSwKqwrnt9ypd+bsyWDclZqKXzytlfwkF", + "ZQqQxvN3dJf37zeHf9neDxaYynjt1Xw/zjerMl14ZXeekwhPJ6LlZaBSwvIFt2Llgf6C3sf4eKnexqgS", + "82/mptQPJa3Xzp6sm718Rmv8uQwua4li8nz3oYwR66z9Y8O8nz3k6Vu/zp+8V4Y/sOY1fDKYvnPITvt2", + "egLPzB7ERkAlzrIqNQJS0ebmiA3LPPoP5evYnGUnYHqyKe0/7fN3pMmjnTKO4dJJ7Vj73hxlte9xc8fY", + "8KFvjmY55W5xZ1eX8tJoi8ndsPOb7f3eavcKHLzv0UcGV874XW42yOMbLvUVid2/7/uERX4JV+nfOL1v", + "0defAAwd/yox4f5cuLaSHK4wmL/t7yenrHy11F474RFTpkivyrwE8Bqtu7b5+Y+l+bvMt6muymo45Ygk", + "LTtdvkpAiAmb6tL5eCewJpTUFT5bC+j8spOQ4M/1TnZwOPWwx7LSAIJe/YA/R8j1l1UnQ4wHQPNbvjVE", + "W5f0AOnwjt9z3NQe81lwOUGZGsba3wj5F2oD6LO/W5cwPZsJY5mVcyVnMuaYmdMnNA4Teln8QiWi/gn+", + "5oZesxCESMojHi+kuIKVTIVbHQURrd2ltIZ3cEafC+JFa4lIattFv6gR+0HOF8LQv2xIG81shkkuK9UK", + "ZJaEdKsMXEMFWHmGdBPWPWP/C26bhmBPIubTIcLFQkWV//X14eHw28ND9ub7A7sPHb2KuNnx64hNecpV", + "LBLqeYA3wPb+15Nva33p4ppd/yPyn1no8u3h8M+NTmvLfBLh17LH08PhN2WPjhupQcsYh+lQfIe/KsW3", + "P6pBVPuNlox/WNepBe9PNz323olwnq/o6P4gxHNFNbkDAUX1UkjQ5Alnk3iArIQFbPtSDaQV/uBheKZN", + "Uyj4PXDp3STP8gxaQA5+Y1IRsN754f5JAAv8ums7YHxKDgBrt7cDYKXSOnwv2E7Iei0tlo+0t2RInycs", + "VbtuAabqoZlSOo3PEJpgg2SnoFDv20APeMl3PjTBgf20uuOH8Pu/j0cmjFNT7nyGN4k7QAM/2gXvRhAw", + "qWxQILTSA4j89OqDfuQAlxNEUxj/90IRdOyEG1JNkzvLNMhgWmNtPzNwgvtlDRPoDuBjBbGTca0gbieF", + "WK9L/HCBoB0FkG+dqKsaKoRtfoZXDZVI1ohFvZbxAdZKtguZ7wADZJnudhHFpGq2ZsD2WUa0qbyxiDH5", + "aCcjMu3pCIUkjzrS3QQx5d68ekrJqMN1IhHWjbdUiYY2UnmjnaeCPomrF7371IeOBrf1svDax2qp290s", + "Wka4bXrPJ+1q3Vr6q8+cXLYk+pl5MNwNYYKqd2P+K45qJvLUrGWxk96tLzgnrCi8ViCwC31I23tvyLMr", + "ciT1Utu1JF6Vd4vuhyn35JO0CWNuCfp/l3kz75vf5heDBryei20FRG+BEV7ZtAUldlUVd2HOhdqOOttV", + "xg0N8YVaURF352rzOt97Q79OD7nzhSiPLJxWYEM9fMI+GVq3e3B11fZ629+Jy2fA92uDNe9hNTgAp+EQ", + "2wyrfvuj3UruVdq+ByAoL/wZfuFEZRVcb01YrlcT5K28SBw37pX9GVs90FukNsXuXiq3zBiP224tHPGT", + "klB0qKVMRIW31/44enkrrpZxdfGC3Xfa4k8EjrSZulrfJw5U853kPTzPg9/CpXygW0kF5bxahUidVwC5", + "onBBJYrXmngdSnnTm/Qo29Um37RV5KWrJGf4z/wq4VgJrtGD+laqstVrPKgq+7Yqzs5Q0fTKvrzySpWP", + "dpurSjDwP6bVtmq/ttlYzvAR7kv6t6QHqErr61nt1e6juQfRYCF4grv+bfBfw7Ozl0Of0G543lrl+o1I", + "JPclQGdYux6retNwbG+VEO437KXBNrraqs0U+uFzBGQ86LVT9hmyAunuDdNGbnMgwzxxfRTAxzUhkK8p", + "gz+iP8K7qo5uKlimE8H2dOx4yqhPxLDwwZ+++Wa/Wbj9T99807XMjOqPti7rH4fD//jlt6+jb9pCZjZH", + "nd2jevqWmpkyS+HnzqxRxQb8OfjL7uKGl+q5PaiOvt0wqueW0K+Dlq+AjK+HuAm2A7HySFClEW+tkdo+", + "zUyDfrXdZ6RR5rJWV3AVEMrgdomF3WaM1s6kDdnaNqBuN2faZZ7a3ttnqxqMfZ2ywSfjiq/1vCc7BMD6", + "XXPANu4Ci6b46rOzl31RCKILrg2FZ1K65R6Jyc1UOsPNkp2WvVkMBBtt1DMjbEgn7YOw4dIYn3OprGtU", + "tzOFwlz6SiuW6pinC23ds788ffqUYttx1AW3jCOZY06zryDE/6uIfeXHhT/9cF9RDNpX12KaxflXFyrU", + "S7ej8HGUSuswA/3e/lc+Sb+tL2l4LRPBqMwcVldkVvHcLrSLyLcwDIQ1XwUMtQfN3otZRHnS/2fEfmO+", + "RPCZiP8n+7D/FVWIxaomvjxsvTIscwuji/nCB9dDmoWvLLNLFS+MVrqwYT0vTk9G4W/PnqrMDzDINeP+", + "9zqBR93ahaKCzEc6EREebMSqks0nPj//VCe+QryvGW+wHnfwQcL7qK5WWn+EkF7eJ4MI+Du6UBeKLgva", + "TYFxwP1xHz5PFReNqJLKUezgiJ0ob2wa+uKHPs4Ko4ExJTwd1EwbMTc0Lp/6wOLSONUsoEjBhzoXytcm", + "EH5qW2Z1oBVdqLzsVKastyINFeXxu7SsUKX+cVTBIvwCHb6nyY/oM0V86mvlF14Oh6Uz2cnMzz+kE0Eh", + "jLxQY+HL7KF2ZS6cf8hGtUuo4vhRNYoQVqsfQ1GqAUVGfqUI/k77pWAKP1pqyKEhboAOSZcu25ShnhRU", + "+H9EktZD6GLW5vpEMWgt6wDUaA8uLNHk95hQv9oCZlM6w5UTbrcQ6Z5phzx7RzbSrbs7pVawkgdLnVjO", + "8IkApbGCLhCpCmYY3+Z3UWkh1lkGVK/GfNLe6pYAAjbn12orDJxhqwcFApzi00KBX0IXGODPIvmd3T6/", + "0/X/5v9AddulTNOtoPCjTNOO51lT1VaNvPGFVj69i0Imd3nd3+rKYTe/y2T27378LN2fgBzJOaiGMJlS", + "eEXeHiYpn8xWqHxPzb4YuKT9PELm/flgwnkyzk7P/3s4pRxb9wGe9E7r1GgFxkKtPjZ0PjC3pE21MUr/", + "y2cZEOIvgNlwZ3cBjkT2kK2w1RdDuXA7n1iOoyV0yXHfL7GOHWnlP1tFfMVfmfUQdCdI1YXbpp+vjhfU", + "ZZsU9Z+Ipt1B4VzuDbr1VD2H89eFywuHGqhUzgRlvX20zT6YbbYG97pwO+vRjYgxa/z8oPIRaafQlHDi", + "fWj/oPk9ylm21yBYjfD3HT9dZo9PlHipzAeSG3El8f3L6HJFwiCHvt7JRFmDCx9x3EkJQ0hyHTQ2mu5P", + "KnewMjY7XFtITeZ0mVsgYtyynKOzrdOstjT0/PL6c50BC/OFAqrEzqvjSluO250iFiluu/GdD399Mfz7", + "4fAvw1/+x7/dii7jXRxk+Td3DgqrgN3fbIO6lr8OX0kl7UIkwxctxrFzmQnreJbDXWDux+aFzHznEftr", + "wQ1XTtA1TAV7/+ro66+//stos1W2sZQz8tW71Uq8n99tFwJLeXr4dBPNkNZXmJeYsnpuhLURy7GsG3Nm", + "SVpmykndPO73iE0vZvDDerGFYj6nzANYXQ6Lf0vFqLZPvTi9WRL2VJsoPYGftHgCf/iM0xdQsQeLKCrQ", + "wf1eiBVYSTfGmtNlw63dUfQuY7Y2cbMwG+UNWAuEWsPo174ClSlXeW/B2JBe39Q2v+PBZtxcdlvYaZ+W", + "cQYUNGE+r7siWPce8JUBtRwWc9TPpMKsrQQT3FwKE2rQ/JPMjTKETnjh8s3pN8AT4gXPnTChz3rg0Rtu", + "Lh9aYGnM8YAu1zusoeut9wbPqUS0P4xo9CJJSsgkWPH2fKmGgcxXMLk7biBj2uL2/9Bg2Jxko9j8ZBML", + "9Ez2M8w8iidQFuqq05h34AdGdQLCNnNh2Mkxi7mi6lTg0yIMpYbmSLVGt4EDnW8CA50/PBTU5rj928m7", + "4X/aolBO500BsP+F5Ol2Z7D/5FfcOxCg91cujAUgUI691YkY/dMGZxj2/uXp6xE7K6vRUNmKhUjzZ+Ar", + "NJlM/mkvFEw7go97+89Z1/8dHDDkxplwC500el0MsPLYxaCt+8EBOwNTkiuMiMrKG1F46JQFiTDte3PU", + "NbcvmAFXDYt/ccVlilVh/JKeXVBps/j/GQ7Z9y//evKW/fXl25fvX5y/PMaTYG9env/w7pi9Pjk7Z8Mh", + "NhaQoAx+fMYm5dyTyP8D3b7Lf4lMuhNwFZtAp++r9NPO6PQZm0CFkIhNEsOlomAG+CdIzq+0wQ/w77l2", + "+ieTwp/g9gMCFvxN7na+5PWZd4CDH/Bs4Q/ny3DB3zOZpicqL/AfuS9dCX9TQTzsRwUAq6KE8BF98fgU", + "F+br4J7zKXa8li5e+H8oce3/ilNthf9bKFsY8V7w1H+QM3grn6ObVNjqm/qmX2ue1M8AMEC52pe3wl1r", + "c3mSpHjM/8TORZm0AP61cC7/q3B45uRo94xNVl0LJ1H5rQKXSR0gXr497gcOF8rf7NDfbIAvlOx4CXVY", + "CJDiY3wRLK3YxHvwTMiVD2tQzIz+VagL1ebuGKdSUB2hamBuw158gR7fceQ/jtiRzjKtGJzcDHJG1JGZ", + "40vNA9nexSAUE/AYNop1RmhEDWsXtQdfY42+SEYI9h2jJq2QWWucSnXJvsM+I6UTYUczqZI9+JN9R6fK", + "4B8jo1PBvvvuO3YxgD4XAyxL+PRP9L/UBlP1UJs32jRSk41GI1q5nLG9/wdG2PcemEpcM6TEezQyU9qx", + "GQhw9a0iIu1hv+cXKqweo1/DVtdwZu9icOCy/ADd+nI1vxhEDBXe7MmfDg+rsZv0Ye83GPVDjVid69yX", + "wp1KBSyBCgIlS8UzXyVTZt4vM9NJkQob6DorlJNYu0iQryCpTYlU8hgxasRe3pSpJa94WvjSD76g2HMm", + "sFISvUGQEdTo295oNNqfREDIrAYa7OEdy6StUD5qO2KnUimoFoIp8tGvzcNq5d08jLUREwaVkPic1nOh", + "Kij3DrjhCNiE9r8HK8GR4iTf25+EOpqWFcoI64zEd9WxuEK898CJnq+AcAYOKxMkDFqW8l+lR05pwR2U", + "3F6BOb84PQlHCRXErHARfvOFYaLgTxxdqNhwu4jYu3dvIn8BTsc6LcsYJLAuvbQYNG8dRlWoJARA4tej", + "n06On9JhjmUCtTdLbzS6qaquH1AOaRs1xhpbX3UIVlg6rOY9eKH+9iZi8IS74qnwr1lTAKYiBPoXqd88", + "LrXmVV6N/OL0xD5nMlQ5Y5arZKpvRLLBPdWTzvcgyDyMoFibofFmbcpKWEbJTw8e1qEYTSoz6Uj79mf2", + "Rn4fVFh0upijgCTvcw8iRvwTS7JxeH/ZBU9FwhIuMq3K4dFwgbpb/P6V9UMrcZ1KJaAGq5/V9xjCZ1oK", + "JcBUWg0RiArSMnxzeDgafEyLa+NQ+7nY7nkfW8CIWgkPjxP7d3qGPfn607rlNSXsmnc5yg09vXNtzFPh", + "9K/CaCgqAkRvY+14sgzCZH97Q/VzYATM26wZjBLBa4+bJMVTn7Efzs9PmTN8NpMxA0rgRuyIp2lI9Qzg", + "i5EO0sKQ16AevoYkwtKxqYh5YQX7SclLw2eOfuWF08BriSFhW6pcX1b0DMTjb29aMzXTNs9g5+f678Lo", + "QZ8Iamw/dHoIu2T+rJJ7udGTRGS5dqSn9SPjuYpwqrUj6v1wrl+tUJtv9r2wThthfY0nZhubLSsRVquI", + "QOGpr1Grj+fdXC4p8tHIIJNU0JVT39Ly8Lc3TGmfKxoralpvbliINAFR57K1PONLdffbE+qBLo8Gvvvd", + "lU225lqHk/RvJFb2ataFGbHQ+JvDb5ic1dp5phmat3PNvwp3Xq7nAel7OQn4dLW6A563b/C2GtM1f6yO", + "A+xza1FViGmFaHLjq6dTqkG6ss6rQmWan0EKW4u3YVaUlL4mNCxRZCAxLnke7LT1IaqKvNKUsGKFg1Ag", + "uxNwsDPqBR4i9aUDzIdTAbD3+PUMYpCsYHEquLEhs387YP6FCMPEOm3gGeOHmMAqaBRM4l+VmMXYKQwB", + "TI3gybLKU0IjPF+fD8ZKxQweK/682sAdy1o1Af7BBMRymnoFq48nUd0a4z5d2sxPW3frbgSiaKHjZ8Jt", + "oQgBR54ePmni5zUnBK15pFS4+rwMYn16eAj9UI1iAYVTEQds0LkbSvWM8Up0ArQi5IPR63Rkj69Us6NH", + "utJuQS4gJHih4kGbQCMCWQgS034nOXgewjiZLHmqFxc20aTfJQ0p3KejIL97inGfttnbL8gK9zma4e4m", + "pjSEy1rOo/ZnwYnyegVFPqGVp0C1BHJRjdicu0pvFeKmVxZaJ2aHRD2wtYU4HpEwoa5EqnNRPRL8tJbx", + "JDigPT38puX3mUzJwrindJg+OKVpU7X9ylYkSdqKKiHJ+ubwkJFuUia+YjppCtpxfJpKW0kK5Mj7QP7u", + "NBdO8Yn83at9+ktqjV7F68hptajSDTcacxNKKVf3bWErKhYjogot7zYakMexyBG8Clfd9GZYe068MSzl", + "DgVsG/jnb6IHSuyOjmsu8auZkAQW10LzaNM7vJqbUHrEXvJ4wdDyhQzO50XI2EQmz9hvVvzrw8WFAm/v", + "Z+y3cElDgAj4fnGhJiAp0O34ksqkm/QK2WGmlXZayRhVs8EKwGOjrV0htF7F/Jxx9ppbN8Q7HZ4ck/4I", + "9DZBgoGOqpJOEA9h2RgLnQWVEW17xI6NzmlRFAZIIDHnuQ3PpIlMJpS14hmKTmTuFvJKJPSbtJT02S24", + "Yk8YB5fD4DSbwlqtAIFCgn2QTpZdCwOkhNTcuANoPC1mM2FG7AhNZZbZhS7ShDnD48uW0dD/VjgRO1zv", + "iL3C5CjV9m2QrVaODAWUatrqNeeviix8+FgUaHGiVT9HB182+Z9ojll+x9N0QilUG8PpNBHW+QejSEoI", + "tw4KP6C6+VrCeS94LkJOi7lQwoBtpEkJJyP2SptSYvSnJ/zz1OPuj8IokVJqE7YHzUFiTFNhLCusz+6n", + "4yITCnqhdXmyHzXI+YRKvwPMaZOVGbSzkB9w4iWlf8dlHWNjImpRlXFjuvSDt1F6CgVobm9rQR1QUWeh", + "qDoKtraJTyP2Du1dhlmhEnbYch/henNtJT0G+uFkxKxuIhaa2wiNBKCZ8RZhPxV35FM4Yuf8UljoF4sE", + "J0LDwYTgZkKMF43KNLGwQjmcDggSqGaHRngwrqZLBQeY9IBEHphDGhJuaCEt1q2qiqqR62/lMd5Agt2y", + "VJ0i4O8C8CP2HlZFKA3WVsu4Y08On37zHDuUwMxrlAAQzxZmxmNB5pKZNNYRss+N4AQFQGVGnbXj6ETa", + "g2zSdPDLRw5T6sXxX/dgRp9dyqzVHcCNnglzJczwTCjHSgrQi8GTR8QBuXxsEravMBUU0jbMBZXKq+A8", + "Fx6fIbSDKKjW6diI2Yi91WoIyGeLKdCURMQphy5XxPUvlEM7NKkESpokpCHu6MmIzouUu5BznSvyN5Bq", + "PsZxSZimWNURe+cWMAiMe6GgnU9a6YTJpOKpz18SManitEC/Ny8dVOXuMcdRXZ/pZCYwxs2vsUpEdaGm", + "Yi4p15NgFi+jStVUuFhnYlyoS6WvqfC+EtTClWInrLVpPWoj9nQN5PkC1vsHkuhpAppsg4kY3QX4NVs1", + "FePjpWYnfoLG3DwtLPuG/Si/B7QpZW8g4SjZeDtyaUD+qObbasfUfYMNd2F0Jouskvvh+ipYwPsVEgGw", + "AlqyUNewAOVdbapcYmvAOfo8InKh1zcPdg+v6InbdhFVIzYVc64ifIBJZymoIOAdi1HYVdqxqWB6itgJ", + "L66moQxhHdM12xhAUiT1fHo9DdaemEIP26MQcUjSB/igiCDW5mw4tBFxqrmoeO+4MALRMWErYlp6NU+X", + "Xtupc6Ewfx3mzFsykU1FkqA/jCJ1pgRlKXMLbTGtHDkFvVO+nJBBYQThLArCsfcSyrSSTpvwCKrWyKfk", + "HhMS2qE0h16ApNS8ULgqbkTYgs/pB9NHoRt9WlsvdBUJhWThEPiiEckaHfWOToYKPsEDq9TRwHloU41N", + "r1JcZu0M3UJkDB050VvDMwlhgQkt8ZTwSYtEPFwF8Cidc8iBH3ghjVvySXJs6mCnYMTWau7TIK5X53QL", + "4Y8ngk3QEemQj7htP94PLEE3h5+s/xrWBpDjMz6WDIlM48JYlmjEIOXj7jKu+Ly8Z5aIaTGfw+3XH4na", + "MFtMAfSnMFzpvhkkr3ZrbsXc7ODBCT5OsynHy5F/5LTl1hx9ylg6T6ZWCMYamehDuD58+H8HAP48O2BR", + "mwMA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/server/openapi.yaml b/server/openapi.yaml index 3f678f35..21f959a6 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -1911,9 +1911,10 @@ components: default, so a caller that omits this block keeps today's behavior: in a PUT (full replace) an omitted block means enabled, unlike `export`, whose omitted block means off; in a PATCH an omitted field leaves the - current setting unchanged. Storage opens with the first capture session - that has it enabled and stays open for the life of the instance, so - once it has started a request that disables it is rejected with 409. + current setting unchanged. Only events captured while storage is enabled + are stored. Storage opens with the first capture session that has it + enabled and stays open for the life of the instance, so once it has + started a request that disables it is rejected with 409. properties: enabled: type: boolean From 614c11ac2df5c92691397c6850dfc68024fd71bb Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 14:29:21 +0000 Subject: [PATCH 07/10] Hold storageMu until the telemetry config settles PUT and PATCH took storageMu only for storage-off configs. A storage-on update commits provisionally before capture is applied, so a reconcileStorage deferred from an earlier request could read that config and open the sink, and a capture failure then rolled the session back to storage off with the sink open. Every PUT and PATCH now holds storageMu from the storage check until it commits or rolls back. Co-Authored-By: Claude Opus 5.5 --- server/cmd/api/api/api.go | 7 ++- server/cmd/api/api/telemetry.go | 42 +++++++------ server/cmd/api/api/telemetry_test.go | 90 ++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 22 deletions(-) diff --git a/server/cmd/api/api/api.go b/server/cmd/api/api/api.go index 7d8d71c6..e0dc3a67 100644 --- a/server/cmd/api/api/api.go +++ b/server/cmd/api/api/api.go @@ -134,9 +134,10 @@ type ApiService struct { // so a toggle-off drain (bounded by otlpStopTimeout) never blocks concurrent // telemetry reads/writes on monitorMu. exportMu sync.Mutex - // storageMu serializes S2 storage reconciliation. Unlike exportMu it is also - // taken under monitorMu, by the storage-off guard in PUT and PATCH, so that - // guard sees a start reconcileStorage has in flight. reconcileStorage never + // storageMu serializes S2 storage reconciliation against telemetry commits. + // Unlike exportMu it is also taken under monitorMu: PUT and PATCH hold it + // from the storage-off check until the config is committed or rolled back, + // so reconcileStorage only reads a settled config. reconcileStorage never // takes monitorMu, so the order is always monitorMu then storageMu. storageMu sync.Mutex lifecycleCtx context.Context diff --git a/server/cmd/api/api/telemetry.go b/server/cmd/api/api/telemetry.go index ca6614b8..d45bd0cd 100644 --- a/server/cmd/api/api/telemetry.go +++ b/server/cmd/api/api/telemetry.go @@ -50,17 +50,19 @@ func (s *ApiService) PutTelemetry(ctx context.Context, req oapi.PutTelemetryRequ return oapi.PutTelemetry400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil } + // storageMu is held until the config is settled, committed or rolled back, + // so reconcileStorage never reads a provisional one: a storage-on update + // whose capture fails to apply would otherwise leave the sink open under the + // storage-off config it rolls back to. It also keeps a start in flight from + // racing the storage-off check below. + s.storageMu.Lock() + defer s.storageMu.Unlock() + // Storage cannot be turned off once anything may have been persisted, a // clear included. Checked before anything is committed, so a 409 leaves the - // session exactly as it was. storageMu stays held through the commit so a - // start reconcileStorage has in flight finishes first; without that a - // storage-off config could be committed while the sink was opening. - if !cfg.StoreS2 { - s.storageMu.Lock() - defer s.storageMu.Unlock() - if s.storageEverStarted() { - return oapi.PutTelemetry409JSONResponse{ConflictErrorJSONResponse: oapi.ConflictErrorJSONResponse{Message: storageDisableConflict}}, nil - } + // session exactly as it was. + if !cfg.StoreS2 && s.storageEverStarted() { + return oapi.PutTelemetry409JSONResponse{ConflictErrorJSONResponse: oapi.ConflictErrorJSONResponse{Message: storageDisableConflict}}, nil } wasActive := s.telemetrySession.Active() @@ -116,15 +118,15 @@ func (s *ApiService) PatchTelemetry(ctx context.Context, req oapi.PatchTelemetry return oapi.PatchTelemetry200JSONResponse(s.buildTelemetryResponse()), nil } + // See PutTelemetry: storageMu is held until the config is settled, and the + // storage-off check runs before anything is committed. + s.storageMu.Lock() + defer s.storageMu.Unlock() + prev := s.telemetrySession.Config() cfg, allDisabled := mergeTelemetryConfig(prev, req.Body) - // See PutTelemetry: the storage-off guard runs before anything is committed. - if !cfg.StoreS2 { - s.storageMu.Lock() - defer s.storageMu.Unlock() - if s.storageEverStarted() { - return oapi.PatchTelemetry409JSONResponse{ConflictErrorJSONResponse: oapi.ConflictErrorJSONResponse{Message: storageDisableConflict}}, nil - } + if !cfg.StoreS2 && s.storageEverStarted() { + return oapi.PatchTelemetry409JSONResponse{ConflictErrorJSONResponse: oapi.ConflictErrorJSONResponse{Message: storageDisableConflict}}, nil } if allDisabled { s.telemetrySession.Stop() @@ -212,9 +214,11 @@ func (s *ApiService) reconcileExport(ctx context.Context) { // is single-use and binds its stream for the life of the instance, so it stops // only at shutdown, and the storage-off guard in PUT and PATCH keeps a // storage-off config from coexisting with an open sink. Like reconcileExport -// it reads the desired state from the session, runs after monitorMu is -// released, and is best-effort: a failed start is logged, never surfaced, and -// retried by the next request. No-op when the VM has no storage controller. +// it reads the desired state from the session and runs after monitorMu is +// released; storageMu makes that state settled, since PUT and PATCH hold it +// until they commit or roll back. It is best-effort: a failed start is logged, +// never surfaced, and retried by the next request. No-op when the VM has no +// storage controller. func (s *ApiService) reconcileStorage(ctx context.Context) { if s.s2Storage == nil { return diff --git a/server/cmd/api/api/telemetry_test.go b/server/cmd/api/api/telemetry_test.go index bfa2de27..562377c5 100644 --- a/server/cmd/api/api/telemetry_test.go +++ b/server/cmd/api/api/telemetry_test.go @@ -1209,3 +1209,93 @@ func (s *blockingStartS2Storage) EverStarted() bool { defer s.mu.Unlock() return s.everStarted } + +// gatedCdpMonitor holds the first optional-capture enable open until released, +// then fails it, so a test can act while a PUT or PATCH is mid-apply and then +// drive its rollback. +type gatedCdpMonitor struct { + stubCdpMonitor + once sync.Once + entered chan struct{} + release chan struct{} +} + +func (g *gatedCdpMonitor) SetTelemetry(enabled bool) error { + if !enabled { + return nil + } + gated := false + g.once.Do(func() { gated = true }) + if !gated { + return nil + } + close(g.entered) + <-g.release + return errors.New("collector configuration failed") +} + +func TestTelemetryStorageNeverReadsAnUnsettledConfig(t *testing.T) { + ctx := context.Background() + tr, fa := true, false + for _, method := range []string{"PUT", "PATCH"} { + t.Run(method, func(t *testing.T) { + svc := newTestService(t, newMockRecordManager()) + st := &stubS2Storage{} + svc.s2Storage = st + // A non-CDP session with storage off, so the collector is not needed yet. + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{System: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &fa}, + }}) + require.NoError(t, err) + + // Turn storage on together with a CDP category whose capture will + // fail, so the request commits provisionally and then rolls back. + gate := &gatedCdpMonitor{entered: make(chan struct{}), release: make(chan struct{})} + svc.cdpMonitor = gate + on := &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{Network: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}}, + Storage: &oapi.BrowserTelemetryStorageConfig{Enabled: &tr}, + } + done := make(chan any, 1) + go func() { + if method == "PATCH" { + resp, _ := svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{Body: on}) + done <- resp + return + } + resp, _ := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{Body: on}) + done <- resp + }() + select { + case <-gate.entered: + case <-time.After(2 * time.Second): + t.Fatal("request did not reach the capture apply") + } + + // A reconcile deferred from an earlier request runs now. It must wait + // for this request to settle rather than read storage-on mid-apply. + reconciled := make(chan struct{}) + go func() { + svc.reconcileStorage(ctx) + close(reconciled) + }() + select { + case <-reconciled: + t.Fatal("reconcileStorage ran while the config was provisional") + case <-time.After(100 * time.Millisecond): + } + + close(gate.release) + resp := <-done + if method == "PATCH" { + require.IsType(t, oapi.PatchTelemetry500JSONResponse{}, resp) + } else { + require.IsType(t, oapi.PutTelemetry500JSONResponse{}, resp) + } + <-reconciled + assert.False(t, svc.telemetrySession.Config().StoreS2, "the failed request rolled storage back off") + assert.Equal(t, 0, st.startCount(), "the sink must not open for a config that was rolled back") + }) + } +} From b5a71a721d184044059a3f26e6fe4b37fb84cefe Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 14:29:21 +0000 Subject: [PATCH 08/10] Never fall back to the boot S2 stream on a fork A fork's boot S2_STREAM belongs to the instance it was forked from, so an applied identity without s2_stream now leaves storage closed instead of binding the parent's stream. The platform always sends one. Co-Authored-By: Claude Opus 5.5 --- server/cmd/api/fork_identity_test.go | 18 +++++++++++++++++- server/cmd/api/main.go | 9 ++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/server/cmd/api/fork_identity_test.go b/server/cmd/api/fork_identity_test.go index 3d750caf..f4a4cf3b 100644 --- a/server/cmd/api/fork_identity_test.go +++ b/server/cmd/api/fork_identity_test.go @@ -234,6 +234,22 @@ func TestAppliedS2StreamPrefersForkIdentity(t *testing.T) { assert.Equal(t, "fork-stream", stream) } +func TestAppliedS2StreamNeverFallsBackToSeedOnFork(t *testing.T) { + useTempForkIdentityFiles(t) + markForkIdentityWaitArmed(t) + cfg := &config.Config{S2Stream: "seed-stream"} + + writeForkIdentityPayloadForTest(t, forkidentity.Payload{ + "instance_name": "fork", + "session_intel_url": "https://intel.example.test", + }) + require.NoError(t, forkidentity.WriteAppliedMarker("fork")) + + stream, pending := appliedS2Stream(cfg) + assert.False(t, pending) + assert.Empty(t, stream, "an applied fork identity without a stream must not bind the parent's") +} + func TestAppliedS2StreamIgnoresMarkerForAnotherInstance(t *testing.T) { useTempForkIdentityFiles(t) markForkIdentityWaitArmed(t) @@ -288,7 +304,7 @@ func TestS2StreamResolverHoldsBackSeedStreamWhilePending(t *testing.T) { assert.Empty(t, resolver.Resolve()) resolver.RecordAppliedPayload(forkidentity.Payload{"instance_name": "fork", "session_intel_url": "https://intel.example.test"}) - assert.Equal(t, "seed-stream", resolver.Resolve(), "a payload without a stream keeps the boot configuration") + assert.Empty(t, resolver.Resolve(), "a fork payload without a stream must not fall back to the parent's") resolver.RecordAppliedPayload(forkidentity.Payload{"s2_stream": "fork-stream"}) assert.Equal(t, "fork-stream", resolver.Resolve()) diff --git a/server/cmd/api/main.go b/server/cmd/api/main.go index bbfbdf16..0d2c2cbb 100644 --- a/server/cmd/api/main.go +++ b/server/cmd/api/main.go @@ -476,9 +476,11 @@ func (r *s2StreamResolver) Resolve() string { // RecordAppliedPayload records the applied identity's stream in-process so a // resolve that follows the handoff does not depend on re-reading the identity -// files. It does not block: the handler contract forbids holding up the handoff. +// files. The hook only runs on a fork, whose boot S2_STREAM is the parent's, +// so a payload without a stream leaves storage closed rather than falling back +// to it. It does not block: the handler contract forbids holding up the handoff. func (r *s2StreamResolver) RecordAppliedPayload(payload forkidentity.Payload) { - stream := forkidentity.FirstNonEmpty(forkidentity.Env(payload)["S2_STREAM"], r.cfg.S2Stream) + stream := forkidentity.Env(payload)["S2_STREAM"] r.hookStream.Store(&stream) } @@ -488,6 +490,7 @@ func (r *s2StreamResolver) RecordAppliedPayload(payload forkidentity.Payload) { // a restarted api would otherwise bind for the rest of the instance's life. // While the wait is armed and no identity has been applied there is no stream // this instance may bind yet, so the result is empty; pending reports that case. +// Once one is applied only its own stream counts, never the boot env's. // // OTLP resolves its identity per use instead (otlpIdentityProvider), so a stale // read there self-corrects; an S2 append session binds once, so this read has to @@ -508,7 +511,7 @@ func appliedS2Stream(cfg *config.Config) (stream string, pending bool) { if err != nil || payload.InstanceName() != applied { return "", true } - return forkidentity.FirstNonEmpty(forkidentity.Env(payload)["S2_STREAM"], cfg.S2Stream), false + return forkidentity.Env(payload)["S2_STREAM"], false } // chromeJSONProxyHandler returns a handler that proxies a JSON endpoint from From cc7a22f87482e1cb149beae4868bc01cbc6ce9fc Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 14:29:21 +0000 Subject: [PATCH 09/10] Test the first seq the S2 writer forwards Split the writer's start from opening the S2 session so a test can run it against a mock backend and assert it forwards exactly from afterSeq+1. Co-Authored-By: Claude Opus 5.5 --- server/lib/events/s2storage.go | 9 +++++++-- server/lib/events/s2storage_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/server/lib/events/s2storage.go b/server/lib/events/s2storage.go index 7cd08ea3..92222d74 100644 --- a/server/lib/events/s2storage.go +++ b/server/lib/events/s2storage.go @@ -166,7 +166,7 @@ type S2StorageWriter struct { mu sync.Mutex started bool - storage *s2Storage + storage Storage writer *StorageWriter done chan struct{} } @@ -196,6 +196,12 @@ func (w *S2StorageWriter) Start(ctx context.Context) error { if err != nil { return err } + w.startLocked(ctx, storage) + return nil +} + +// startLocked begins forwarding to an opened storage. Requires w.mu. +func (w *S2StorageWriter) startLocked(ctx context.Context, storage Storage) { w.storage = storage w.writer = NewStorageWriterAfter(w.es, storage, w.log, w.afterSeq) w.done = make(chan struct{}) @@ -206,7 +212,6 @@ func (w *S2StorageWriter) Start(ctx context.Context) error { w.log.Error("s2 storage writer failed", "err", err) } }() - return nil } // Stop waits for the Run goroutine to exit, drains any remaining ring events, diff --git a/server/lib/events/s2storage_test.go b/server/lib/events/s2storage_test.go index 0516f045..6b71b75b 100644 --- a/server/lib/events/s2storage_test.go +++ b/server/lib/events/s2storage_test.go @@ -326,3 +326,30 @@ func TestS2StorageController_StartSkipsEventsAtOrBeforeAfterSeq(t *testing.T) { require.NoError(t, stopController(t, c)) } + +// The first event the writer forwards is exactly the one after afterSeq, so +// nothing at the boundary captured with storage off is persisted. +func TestS2StorageWriter_ForwardsFromAfterSeq(t *testing.T) { + es := newTestStream(t, 64) + for range 10 { + es.Publish(Envelope{Event: makeEvent("ev")}) + } + backend := &mockBackend{} + w := NewS2StorageWriter(es, "", "", "", 7, S2Config{}, slog.Default()) + ctx, cancel := context.WithCancel(context.Background()) + w.mu.Lock() + w.startLocked(ctx, backend) + w.mu.Unlock() + + require.Eventually(t, func() bool { return len(backend.envelopes()) == 3 }, time.Second, time.Millisecond) + cancel() + stopCtx, stopCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer stopCancel() + require.NoError(t, w.Stop(stopCtx)) + + var seqs []uint64 + for _, env := range backend.envelopes() { + seqs = append(seqs, env.Seq) + } + assert.Equal(t, []uint64{8, 9, 10}, seqs) +} From 829b0f761b02dd86c7d1faf5ccfd4f50c938ca82 Mon Sep 17 00:00:00 2001 From: archandatta <35818003+archandatta@users.noreply.github.com> Date: Wed, 23 Sep 2026 14:29:47 +0000 Subject: [PATCH 10/10] Correct the ring-ordering test comment Co-Authored-By: Claude Opus 5.5 --- server/lib/telemetry/telemetry_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/lib/telemetry/telemetry_test.go b/server/lib/telemetry/telemetry_test.go index 23cbb280..32a3f904 100644 --- a/server/lib/telemetry/telemetry_test.go +++ b/server/lib/telemetry/telemetry_test.go @@ -279,10 +279,10 @@ func TestTelemetrySessionStoreS2After(t *testing.T) { assert.EqualValues(t, 3, after, "a storing session starts after what earlier sessions captured") } -// The S2 sink opens with the first storing session and reads the ring from -// its oldest event, so this is what makes deferring it lossless: with no -// session there is no publisher (TelemetrySession is the ring's only one), so -// the ring is empty when the first session starts. +// The S2 sink opens after a storing session is committed and reads from the +// seq that session started at. Deferring the open is lossless only because +// nothing reaches the ring without a session: TelemetrySession is its only +// publisher. func TestPublishWithoutSessionReachesNothing(t *testing.T) { es := newTestEventStream(t, 16) ts := NewTelemetrySession(es)