From 4b6be65cf3614b2448fb9b345248caf9c20f6f2e Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Wed, 14 Oct 2026 21:58:52 +0000 Subject: [PATCH 01/10] Define process termination and output replay contracts --- server/lib/oapi/oapi.go | 1614 +++++++++++++++++++++------------------ server/openapi.yaml | 75 +- 2 files changed, 963 insertions(+), 726 deletions(-) diff --git a/server/lib/oapi/oapi.go b/server/lib/oapi/oapi.go index 22194a0c..55e423cc 100644 --- a/server/lib/oapi/oapi.go +++ b/server/lib/oapi/oapi.go @@ -2891,6 +2891,30 @@ func (e ProcessStreamEventStream) Valid() bool { } } +// Defines values for ProcessTerminationReason. +const ( + OutputError ProcessTerminationReason = "output_error" + OutputLimit ProcessTerminationReason = "output_limit" + ProcessCanceled ProcessTerminationReason = "process_canceled" + ProcessTimeout ProcessTerminationReason = "process_timeout" +) + +// Valid indicates whether the value is a known member of the ProcessTerminationReason enum. +func (e ProcessTerminationReason) Valid() bool { + switch e { + case OutputError: + return true + case OutputLimit: + return true + case ProcessCanceled: + return true + case ProcessTimeout: + return true + default: + return false + } +} + // Defines values for PublishEventRequestCategory. const ( PublishEventRequestCategoryCaptcha PublishEventRequestCategory = "captcha" @@ -6624,6 +6648,27 @@ type PressKeyRequest struct { Keys []string `json:"keys"` } +// ProcessExecFailure defines model for ProcessExecFailure. +type ProcessExecFailure struct { + Code ProcessTerminationReason `json:"code"` + + // DurationMs Execution duration in milliseconds. + DurationMs *int `json:"duration_ms,omitempty"` + + // ExitCode Process exit code. + ExitCode *int `json:"exit_code,omitempty"` + Message string `json:"message"` + + // OutputTruncated Output could not be fully captured due to a quota, storage error, or a descendant holding a pipe open past the drain deadline. + OutputTruncated *bool `json:"output_truncated,omitempty"` + + // StderrB64 Base64-encoded stderr buffer. + StderrB64 *string `json:"stderr_b64,omitempty"` + + // StdoutB64 Base64-encoded stdout buffer. + StdoutB64 *string `json:"stdout_b64,omitempty"` +} + // ProcessExecRequest Request to execute a command synchronously. type ProcessExecRequest struct { // Args Command arguments. @@ -6644,11 +6689,11 @@ type ProcessExecRequest struct { // Env Environment variables to set for the process. Env *map[string]string `json:"env,omitempty"` - // TimeoutSec Maximum execution time in seconds. + // TimeoutSec Maximum execution time in seconds, for exec and spawn. Null or zero disables the deadline. Cancellation stops the process group; detached descendants may survive. TimeoutSec *int `json:"timeout_sec,omitempty"` } -// ProcessExecResult Result of a synchronous command execution. +// ProcessExecResult Result of a synchronous command execution. Output is bounded by the configured process output quotas. type ProcessExecResult struct { // DurationMs Execution duration in milliseconds. DurationMs *int `json:"duration_ms,omitempty"` @@ -6656,6 +6701,9 @@ type ProcessExecResult struct { // ExitCode Process exit code. ExitCode *int `json:"exit_code,omitempty"` + // OutputTruncated Output could not be fully captured due to a quota, storage error, or a descendant holding a pipe open past the drain deadline. + OutputTruncated *bool `json:"output_truncated,omitempty"` + // StderrB64 Base64-encoded stderr buffer. StderrB64 *string `json:"stderr_b64,omitempty"` @@ -6710,7 +6758,7 @@ type ProcessSpawnRequest struct { // Rows Initial terminal rows when allocate_tty is true. Rows *int `json:"rows,omitempty"` - // TimeoutSec Maximum execution time in seconds. + // TimeoutSec Maximum execution time in seconds, for exec and spawn. Null or zero disables the deadline. Cancellation stops the process group; detached descendants may survive. TimeoutSec *int `json:"timeout_sec,omitempty"` } @@ -6737,8 +6785,12 @@ type ProcessStatus struct { // MemBytes Estimated resident memory usage in bytes. MemBytes *int `json:"mem_bytes,omitempty"` + // OutputTruncated Some output was not captured. + OutputTruncated *bool `json:"output_truncated,omitempty"` + // State Process state. - State *ProcessStatusState `json:"state,omitempty"` + State *ProcessStatusState `json:"state,omitempty"` + TerminationReason *ProcessTerminationReason `json:"termination_reason,omitempty"` } // ProcessStatusState Process state. @@ -6767,8 +6819,15 @@ type ProcessStreamEvent struct { // ExitCode Exit code when the event is "exit". ExitCode *int `json:"exit_code,omitempty"` + // Offset Opaque resume cursor after this data event. Also sent as the SSE id. + Offset *int64 `json:"offset,omitempty"` + + // OutputTruncated Some output was not captured. + OutputTruncated *bool `json:"output_truncated,omitempty"` + // Stream Source stream of the data chunk. - Stream *ProcessStreamEventStream `json:"stream,omitempty"` + Stream *ProcessStreamEventStream `json:"stream,omitempty"` + TerminationReason *ProcessTerminationReason `json:"termination_reason,omitempty"` } // ProcessStreamEventEvent Lifecycle event type. @@ -6777,6 +6836,9 @@ type ProcessStreamEventEvent string // ProcessStreamEventStream Source stream of the data chunk. type ProcessStreamEventStream string +// ProcessTerminationReason defines model for ProcessTerminationReason. +type ProcessTerminationReason string + // PublishEventRequest Request body for publishing an event into the telemetry stream. type PublishEventRequest struct { // Category Event category. Optional and advisory: for a known event `type` the server assigns the category authoritatively and ignores this field. It is only used for unknown custom types, where it is required. @@ -7254,6 +7316,15 @@ type DeletePlaywrightExecutorParams struct { CloseTab *bool `form:"close_tab,omitempty" json:"close_tab,omitempty"` } +// ProcessStdoutStreamParams defines parameters for ProcessStdoutStream. +type ProcessStdoutStreamParams struct { + // Offset Resume cursor from a prior output event. Overrides Last-Event-ID. + Offset *int64 `form:"offset,omitempty" json:"offset,omitempty"` + + // LastEventID Resume cursor from a prior SSE data event. + LastEventID *string `json:"Last-Event-ID,omitempty"` +} + // DownloadRecordingParams defines parameters for DownloadRecording. type DownloadRecordingParams struct { // Id Identifier of the recording session to download, as passed to /recording/start. When omitted, the default recording session is downloaded. @@ -10038,7 +10109,7 @@ type ClientInterface interface { ProcessStdin(ctx context.Context, processId openapi_types.UUID, body ProcessStdinJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // ProcessStdoutStream request - ProcessStdoutStream(ctx context.Context, processId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + ProcessStdoutStream(ctx context.Context, processId openapi_types.UUID, params *ProcessStdoutStreamParams, reqEditors ...RequestEditorFn) (*http.Response, error) // DeleteRecordingWithBody request with any body DeleteRecordingWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -10994,8 +11065,8 @@ func (c *Client) ProcessStdin(ctx context.Context, processId openapi_types.UUID, return c.Client.Do(req) } -func (c *Client) ProcessStdoutStream(ctx context.Context, processId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewProcessStdoutStreamRequest(c.Server, processId) +func (c *Client) ProcessStdoutStream(ctx context.Context, processId openapi_types.UUID, params *ProcessStdoutStreamParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewProcessStdoutStreamRequest(c.Server, processId, params) if err != nil { return nil, err } @@ -13275,7 +13346,7 @@ func NewProcessStdinRequestWithBody(server string, processId openapi_types.UUID, } // NewProcessStdoutStreamRequest generates requests for ProcessStdoutStream -func NewProcessStdoutStreamRequest(server string, processId openapi_types.UUID) (*http.Request, error) { +func NewProcessStdoutStreamRequest(server string, processId openapi_types.UUID, params *ProcessStdoutStreamParams) (*http.Request, error) { var err error var pathParam0 string @@ -13300,11 +13371,48 @@ func NewProcessStdoutStreamRequest(server string, processId openapi_types.UUID) return nil, err } + if params != nil { + queryValues := queryURL.Query() + + if params.Offset != nil { + + if queryFrag, err := runtime.StyleParamWithOptions("form", true, "offset", *params.Offset, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: "int64"}); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + } + req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err } + if params != nil { + + if params.LastEventID != nil { + var headerParam0 string + + headerParam0, err = runtime.StyleParamWithOptions("simple", false, "Last-Event-ID", *params.LastEventID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationHeader, Type: "string", Format: ""}) + if err != nil { + return nil, err + } + + req.Header.Set("Last-Event-ID", headerParam0) + } + + } + return req, nil } @@ -14276,7 +14384,7 @@ type ClientWithResponsesInterface interface { ProcessStdinWithResponse(ctx context.Context, processId openapi_types.UUID, body ProcessStdinJSONRequestBody, reqEditors ...RequestEditorFn) (*ProcessStdinResponse, error) // ProcessStdoutStreamWithResponse request - ProcessStdoutStreamWithResponse(ctx context.Context, processId openapi_types.UUID, reqEditors ...RequestEditorFn) (*ProcessStdoutStreamResponse, error) + ProcessStdoutStreamWithResponse(ctx context.Context, processId openapi_types.UUID, params *ProcessStdoutStreamParams, reqEditors ...RequestEditorFn) (*ProcessStdoutStreamResponse, error) // DeleteRecordingWithBodyWithResponse request with any body DeleteRecordingWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteRecordingResponse, error) @@ -15332,6 +15440,7 @@ type ProcessExecResponse struct { HTTPResponse *http.Response JSON200 *ProcessExecResult JSON400 *BadRequestError + JSON422 *ProcessExecFailure JSON500 *InternalError } @@ -16585,8 +16694,8 @@ func (c *ClientWithResponses) ProcessStdinWithResponse(ctx context.Context, proc } // ProcessStdoutStreamWithResponse request returning *ProcessStdoutStreamResponse -func (c *ClientWithResponses) ProcessStdoutStreamWithResponse(ctx context.Context, processId openapi_types.UUID, reqEditors ...RequestEditorFn) (*ProcessStdoutStreamResponse, error) { - rsp, err := c.ProcessStdoutStream(ctx, processId, reqEditors...) +func (c *ClientWithResponses) ProcessStdoutStreamWithResponse(ctx context.Context, processId openapi_types.UUID, params *ProcessStdoutStreamParams, reqEditors ...RequestEditorFn) (*ProcessStdoutStreamResponse, error) { + rsp, err := c.ProcessStdoutStream(ctx, processId, params, reqEditors...) if err != nil { return nil, err } @@ -18400,6 +18509,13 @@ func ParseProcessExecResponse(rsp *http.Response) (*ProcessExecResponse, error) } response.JSON400 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: + var dest ProcessExecFailure + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON422 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: var dest InternalError if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -19566,9 +19682,9 @@ type ServerInterface interface { // Write to process stdin // (POST /process/{process_id}/stdin) ProcessStdin(w http.ResponseWriter, r *http.Request, processId openapi_types.UUID) - // Stream process stdout over SSE + // Stream retained process stdout and stderr over SSE // (GET /process/{process_id}/stdout/stream) - ProcessStdoutStream(w http.ResponseWriter, r *http.Request, processId openapi_types.UUID) + ProcessStdoutStream(w http.ResponseWriter, r *http.Request, processId openapi_types.UUID, params ProcessStdoutStreamParams) // Delete a previously recorded video file // (POST /recording/delete) DeleteRecording(w http.ResponseWriter, r *http.Request) @@ -19914,9 +20030,9 @@ func (_ Unimplemented) ProcessStdin(w http.ResponseWriter, r *http.Request, proc w.WriteHeader(http.StatusNotImplemented) } -// Stream process stdout over SSE +// Stream retained process stdout and stderr over SSE // (GET /process/{process_id}/stdout/stream) -func (_ Unimplemented) ProcessStdoutStream(w http.ResponseWriter, r *http.Request, processId openapi_types.UUID) { +func (_ Unimplemented) ProcessStdoutStream(w http.ResponseWriter, r *http.Request, processId openapi_types.UUID, params ProcessStdoutStreamParams) { w.WriteHeader(http.StatusNotImplemented) } @@ -20996,8 +21112,40 @@ func (siw *ServerInterfaceWrapper) ProcessStdoutStream(w http.ResponseWriter, r return } + // Parameter object where we will unmarshal all parameters from the context + var params ProcessStdoutStreamParams + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", r.URL.Query(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: "int64"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "offset", Err: err}) + return + } + + headers := r.Header + + // ------------- Optional header parameter "Last-Event-ID" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("Last-Event-ID")]; found { + var LastEventID string + n := len(valueList) + if n != 1 { + siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "Last-Event-ID", Count: n}) + return + } + + err = runtime.BindStyledParameterWithOptions("simple", "Last-Event-ID", valueList[0], &LastEventID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: false, Type: "string", Format: ""}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "Last-Event-ID", Err: err}) + return + } + + params.LastEventID = &LastEventID + + } + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.ProcessStdoutStream(w, r, processId) + siw.Handler.ProcessStdoutStream(w, r, processId, params) })) for _, middleware := range siw.HandlerMiddlewares { @@ -23347,6 +23495,15 @@ func (response ProcessExec400JSONResponse) VisitProcessExecResponse(w http.Respo return json.NewEncoder(w).Encode(response) } +type ProcessExec422JSONResponse ProcessExecFailure + +func (response ProcessExec422JSONResponse) VisitProcessExecResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(422) + + return json.NewEncoder(w).Encode(response) +} + type ProcessExec500JSONResponse struct{ InternalErrorJSONResponse } func (response ProcessExec500JSONResponse) VisitProcessExecResponse(w http.ResponseWriter) error { @@ -23572,6 +23729,7 @@ func (response ProcessStdin500JSONResponse) VisitProcessStdinResponse(w http.Res type ProcessStdoutStreamRequestObject struct { ProcessId openapi_types.UUID `json:"process_id"` + Params ProcessStdoutStreamParams } type ProcessStdoutStreamResponseObject interface { @@ -24585,7 +24743,7 @@ type StrictServerInterface interface { // Write to process stdin // (POST /process/{process_id}/stdin) ProcessStdin(ctx context.Context, request ProcessStdinRequestObject) (ProcessStdinResponseObject, error) - // Stream process stdout over SSE + // Stream retained process stdout and stderr over SSE // (GET /process/{process_id}/stdout/stream) ProcessStdoutStream(ctx context.Context, request ProcessStdoutStreamRequestObject) (ProcessStdoutStreamResponseObject, error) // Delete a previously recorded video file @@ -26065,10 +26223,11 @@ func (sh *strictHandler) ProcessStdin(w http.ResponseWriter, r *http.Request, pr } // ProcessStdoutStream operation middleware -func (sh *strictHandler) ProcessStdoutStream(w http.ResponseWriter, r *http.Request, processId openapi_types.UUID) { +func (sh *strictHandler) ProcessStdoutStream(w http.ResponseWriter, r *http.Request, processId openapi_types.UUID, params ProcessStdoutStreamParams) { var request ProcessStdoutStreamRequestObject request.ProcessId = processId + request.Params = params handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.ProcessStdoutStream(ctx, request.(ProcessStdoutStreamRequestObject)) @@ -26639,710 +26798,719 @@ func (sh *strictHandler) GetWebMCPTools(w http.ResponseWriter, r *http.Request, // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+z9i3IbOZYoiv4KDs9EWJpNUrLrMd1ydJzrsuwuTfmha6m6ZrpVhwQzQRKtJJANICWx", - "6nrH/oj9hftLbqy1AGQmmUkm9bDLVZqYqLaSwMJrvbCwHr/2Er3ItRLK2d7Rrz0jbK6VFfjHdzz9IP5V", - "COteGaMNfEq0ckI5+CfP80wm3EmtDv5ptYJvNpmLBYd//ZsR095R7/8+KOEf0K/2gKB9/Pix30uFTYzM", - "AUjvCAZkfsTex37vpVbTTCafavQwHAx9opwwimefaOgwHDsT5koY5hv2e++0e60LlX6iebzTjuF4PfjN", - "NwdoL9L0ZWGdXvwkJm9fnp5rndlwUjCVNJUAgmenRufCOAkYNOWZFf1eXvn0a2+qTSJG+kqYayOdGCm+", - "EDbniYAfUzHlReZi1/rsXji9kAnPsiUzIs94IhjPMiZupHVSzZiDWTGpmJtLyyJgdi3dnL5NuEvm7Hou", - "FHOmEMNev+eWuegd9SZaZ4Ir2PPajHLu4Gh6R73/9x8vBn/ng18OB38eDQc///q0//TZnz7+WwnCOiPV", - "DCBYXZiwoOoC/pNf8TP8m4mb3AhrpYbZcsfEFc8K7oRlTjPOlFYDscjdknFj+JLpKUtw/3GRLBVTqXDH", - "LaxhwW/eCDVz897Rnw7x/9Ym9bHfM+JfhTQi7R39o7LGONufYx89+acgMvgO9uulXuSFE+ZFAgN2PfWV", - "o/NbD+vw4BhHeLhgcSOSwglmAbhyEs542FtFHd9hfV/fm1QYkbJMWgdDrEMeslf4D9hv63RuGW68YFNp", - "rGMCCAIGlE4s7DbyqW8I7NNCqhPq+TTuIh7c2saHNTTuttHXVpgXuXzJs+zVlafz1Z0ECiCkSY28AoyZ", - "Czahvn025yrNRMomS/x+KYwS2UAu+EzYAc8ls8hijuI5DIClGJ2FXeuz04wvr42czR1LdCr8Hkqt+swm", - "Rghl59pZxlXKkkzmE81NyniSCGuHDKZuaXoLrvhM4DT+9pZJZZ3gKRML6dg4z7ibarMY8VyOYEXj4YVa", - "O/GEOzHTZgn/FqpYwA766fZ+XsPxfi/lbivza9jlY+hWo9sOALDnGfX42O85UyiYbrp+ZOemEExOcSNg", - "hmwqRZaya25Z7MXSQgC+WvmLYJlcSGebuZNrwH+cCnNyIazjixxY4I9K3rCFTIy2ItEqRWiw4dz1jnpS", - "uW+/LsFL5cRMoMChL+Vuh+Np2O4VzHY2AOyX57aZu7ScxG6s5RRQGEgi58tM85RNtWHjiFZMAFy7zk0A", - "tde3kg6U2WKykA7OxWk29kykpIuXOhXjPkt4nouUccf+9PTPz9hk6YRlmbwUMKhZMu3mwkArVwB7oo0b", - "shehI/B8waRlSeGYVoyzZM4NT5wwbAJimJslkplQKQq28XA4/EfEmZ/HQ/ZiYuHsYc3VMWGhqBkMm+RT", - "WtCPo0UDMv3Es2yQZDq5ZKEd04S8xFsMzGQhs0xWUMuPoYrFhBApzmAkG0jiLUgDkTKjCyee2HK+fZTb", - "KePE1ohZ4TfLpLNxCntiOBuy8Tm/FGeRJ437bPyq8az2G/fBkCxrnCGglf+dyRSE0lQKw6ZGL1oYa2i9", - "kGmaiWtuROOg1nFXNOz79+fnpyzo34xaIf8dNhDqCu1VFrKy83G8+qlvIEegxTPHk8v1Kb48PmUfCgWM", - "ZohNzg1PBDMiNwLQEJWwuWAVPQcp00JbIBP4EXqjkFZEmkP2GtihZYUVDEZQfAGAEq3gZxTkhiNWuzlX", - "zCp+KUYJt8gvF6hWANyXc6MXgh2LK9RO2anRTic6Y9fSCEasr1nGZNlrwxf012bFAlczxcZ9BqhrFto6", - "UiJq6sPKEDorFuod0cbaIH8XRg8m3IqUUUNGVIR6qyQ1JZOqEQ/6vWmhUG6/44vNGmdoiMTUZ9owUjAJ", - "M5GDcKXVcqELGxvbRhSG2XRYDTRrWAu1bl4N/XaSNuMe/V0hx8bZFSZb7/7jhzewZFh74GYe2lRmTYS6", - "QmG1ba7Mk4arbUm/ft5NpFZXEVck2hoS5iQJWcYnIsODwukjUTmkQOKG3C5VwhJeWNHM73Juwt0xy95P", - "e0f/6KTplBzh489r0hdB1iaDmIRTwa92uLaZFZLbyIhyl8z5yznPMqFm4uS4aW/4vwpRwQhm59yQ+kuC", - "nzi2VoJdSSsnmWBJADhkLxRDBj6YGZmioE7mnCVcMSOcWdLNkbOpEXbOHLeXLBeGceeAdPrMagQ8jhBH", - "Mh2zBV+yiWDcWp1I1O0QzKLInMwzwcYACFui/LegEORGp0UiDHZGbmquBJOO8cRoaxlnOajSRqCGQxdY", - "ULH9B2lZzo2LmA1YHifFRC4tyBF24liqhWVKOyZVKhPuBC1LA6MDNqBNpSOgRCZQjUDGuYZQLSf1Qdgi", - "c60XmHgQYb/jgEZwVAs4A9YqAel14RK9gAucV8i0SgQeQ+Ucf+LSecKQlg6+XxManJZpcGJ95jRLBQ1B", - "9xOwRwBvL6cSxx37aY6szq7EyDpunEjHqJet/Ebgx4wWPBG4yVcyLXjGsIXBadDVCU5aJ0lhSsxADT6w", - "SsCscoldL0c0n7tejjYc6ONdqfWuFJChZAeEEHe9O/mj24FVrp7XLW5UkRBq16q2JW64ZvkeYbO6Y985", - "9PjY71W56y3x9+T4VteeqOyXuwEXN27I2ogXklVG1WcJMBNoQRcyT/heaAC+TYS7FqLOU8uLU9v94Hxl", - "oMDsG8TaGMdMx0fYACWHnqBISVeWk2SCG8anaI9bmeqQvdaGOX0pVGDVlhjsQnBlGS9vK9QIiNTfBJ4j", - "usAfdsBVOpjrLAVxRj3rc8D5KX4lZ0jc/Jovh2w85TIrjAhrCPLROk13bpqyAkNqJhPpyoPwq/AAUNG9", - "mfPCAnA4Mb88y67nMhMrkzFiwaUS6ZCNgUfowq3M4IktWw8ycSUydg3SZ1KkM4F2XSDqbbD5hKtUKzwj", - "OhrCOKFSry/owoUTSZmVMzz5zSuOGDjFNXMQ3mwiUCHEqVxLnCOcUyrtQloL8tSUWFIoIHWRDi9UwKEo", - "zFaOrY9aBHyaZvqacQP2CiYdaDNWOoFalHUyy5gRwK4YB31HpoQsfZSB+E/rNw31KcQvSSpKbjTiOHfs", - "es6dQPlZ21FYyazgJgVys0WSCEGz7/UjV6Z1AEcnhACao5Pt9XvxHNZ5dL93MwAYgytuFF0P/9GLHOUs", - "QI1fXkfw8dN5HCd+elEO+LHfuxYT2KvRXNsGTel7baNKlwdL6iorQo2oUdsPwHPu5uvAT7mbdwTO/r8F", - "MjJHXO0myQrY5a13phrrrxgiagx9B7sEQsON36Jg+oGJLiLn3aBcfgbdanUdj3rVVr2qqmQ/oD160wHt", - "rkgF7GtUo+rXht+tCkV0iDcnwK/1u9255/qAnbxwc22k405eCd/VSTAJPmepRsEAd9Ur0aCnzXhO76dt", - "lzZ/NbyeaytYKjKJKhqIInp6TIDDcSNwGJAsXDkRJMqaqobPhqO2hwSQyQObi0ROZUJPjPSeBjP2yok3", - "Y7/68OH9h9HLF6fnL79/Mfrx3dn7N3978d2bV+P9aOHXigSctTtZlc/X9nrswYyPgt5ghCuMQs5YWA66", - "pNUZPvjV9LC11sovas8KwcblZoz3a9qT75fKFHeV+lcNgmAOQsWqokit6EjUhCVcJSLLVrSWuu4I9vcB", - "jrmiB9Cyd1cEgCORxabV/hSUwwG3oKqJtMEi5b0QBJmsAc9akHSjMO+oKVzPhfEincZATo/jpPehLGyE", - "f9/6wt0UBODbVXa4bln2K7iUKmVG5No4MiDC8gh5h/CacCXTKkGjQYkepohhmAXP5C9w9sp5RdYKd8SE", - "csLkRlrBrriRXDkLe2mEp3eW6CzjuRWho5CGXQmDziGTIrkUju1dPWMH7Oqr/T4b461qxFU6glvVmO6b", - "dvWyFVm+JVW7UJnEKxAsk6Yc18otG+O74bhOMvOg8sA5hdO5elb/8ys418Io0PXh2GZCOGEdSrHqRHv9", - "Ho7RSGANR3hG5NBNyTPof5A7Uu+4vfxsKl112o86XUedzrO+T2Yoaz6p3ZU7ehJo1+zqeoctjdhowV/B", - "XetRt1+auCtGY7pXq1nWYPHBu7aXQWzB1RJ7WLxQJ1rZYiGMZYvCOpTA3MIXNDD7CdL86lZ1pg3LuTR+", - "7sAQuTHyCu0QKfDEn2AR3uDTrzxrJNoYkZEzW7THh7eUqPw1K8F9b1evvajMjC5yS4va+J5zHDQ6b0HQ", - "9H57xPjKShfcr0Z4S5J0Nr4OwAyExMeDsvVEsIW0lhw44j4wDtpZgqLQiKk2ouGFJSkMPZIFNdi12PN/", - "M2r+J9F3/Im3PC3dWeEBd08Bwwat5C2dIr16A7HWnmTQzJRwY5ZMaYIJb8akoFceCW0xQbK3+w+jR61N", - "+z6Uqe0c8VE1+q2rRmn+onB6KrPsbeOF86e5TOZ0UnrqXcu47wFODhkg00uutJIJz6iB56apuELf6UHu", - "fWb+P8/Sw6d/Fv/xVX3RCTcwV56mMP2Osz03cjYT5qVeLLhKbyFoz7iSDrFnHGAOHQEdM25mxYJka7k2", - "qfLCHTU1l2rDYvssl0qRQ9/cudweHRzMpJsXk2GiFwfkYBT8iw7W4BxMMj05CMDE5Kv/eJo+Tb/985++", - "SZ99m37152/S//jTJP3T9E/82bMJR5f9A++2OwowhvB1yF6RWcKvjTiGtCyhPWRzTq8vDp8TmDbMiJQn", - "qO6JRCJ1SMUyOYmzzI2+WR4A9qXc8YMkzUfl1i35ImuSSP6gR6hXjhJdNGni5OYCc/TNSQ31zwV+xgH/", - "zpGCPWtQacBC5BJo3w/OkjWpUNEjPcBG4XReDvjEsv88e/9u8OH0JZOpf1kop5NweIVj/9S4f8RZvPiv", - "elOXtg4QF/i2QcYY74AhWJJJ+Bs/Kq28XO+gDydaKZG0+keeBHFK2wjOT3iCrOxXWxDpMinTql+Vt2k+", - "8h2Cv0Kaj1Jpw8chO7/WfhEW3cmDCx+6kIRtgONxwDk5epkg/5eW1lqJPXj67E8NHIGQZ4MyMeHJpVAp", - "UzqtefJ4OYn9/SsQ4L2n6XYUQf+8TQNig8pIQ/Yyk/iq6DR7+uxPpReufc44y7SaCVM666IKzYzgWRVG", - "t81YCDfXafUitMqjGrnqwnP83dy2ViTGuvPWT2FTaUOPQEMz6ZihAzUR8xhpNtCpm4uFFdlVK8nCZZfC", - "WhoPAPDY/1496Som4xnT2HggNRdnj5D+3dV3sRvOr9OxrGhO/owqmLtJfUrz8C+0TR7ra3xDvRdx5yEP", - "kxroLUKvrdOj6NtF9IXZYbzdjdvIv6gp800/D2N5lItfmlxMPWWOZsUG5FqXh6FfKRLjq8hnFWTNfKdR", - "nP1+RET9ELvJiUxbcb/iASB2lQrU9lEY7CIMHpnrl8ZcN7AnIIDfNVfqxIXOhHtJqQTsmfzlfvmRrcPu", - "yJnWej3yqEce9XvmUXMB4akNvMZTAaMGgB3HJ6dt1o52TrdCUL8TntfvXcu06W0lbhv+vmXXrqVK9XXj", - "sv32MWqyphlvicSNmmE5Qld+/BP2+E4XKrX3zY+rsLvz43qvR378yI//iPyYqKAbN87EtB3CDcu1RToG", - "KJRKhSVam1Qq7oS9FYuv0ujvhsU7nbfu4vKWu9giNjzUTys0Iix0BrmNZZ+mfYbdGwz7NA2EHvJSiJTt", - "jekpHvJkLKSSC5AT+Ae/Kf+YFllG24rux95e5GOgkNOWPi6YiAqNSS0v5neWj14StroBBhQMWYwio6mx", - "PB1ihwDjfxKTM42+A8iqjkj0sZmwrjDC9oNDMaYjSSXP9Izyjkg162O+AGZF5pkbjFXJijRkkEZOzoJr", - "eqAJbAcTOH7/9sDn0GDO8Cn4S8S5ZnJiOLov2ULEHFXRP3oi5jybRv/0sOXDC/VeiYoPV9ue+JBxCoOp", - "iA964wmtrDOCL4KB0GIYWdpnieaZsEmQmd61CmPoaWRpWYZuOSpbloKHDhx+DL4ryJZFJhYYYp9Ut6tf", - "9ivlY5S1pft/olNKYYHNk4xbC44nfsu5glaXQuSsyCHzV5IVFvOIwM7hMza6oqxKmWGc1SjMdfw8SFy3", - "uUNqMC7xU2exWiGQR4fTdodTVDFwqz6Bm2nDsTRmGAo0V/chLacaPEeBD0HfBco4JKExUdZ4yF7xZB78", - "p9CFTSLvyMhNqyQfnudGX3klkfzdaJSj8n0XPxZZytBTijMrEiMc+z//638zWGxKWd/0IspgePLqg6uc", - "7TMjpsIYYWzfJ1exfebEIkdfUM85c+7msBzDZywJVzYAGn2V/FxgSO+KlfGE1sxZhnpDn3GiY/gHeaAm", - "EIjKZ30MS1HFAp0zYV4M0V3gGHNtfQ6gynZSYs0Fz3NABUh2ufok3/mdvcHXqd/2MLIV6NZ35f6KUbMz", - "xNUXiH6rzaAryA3mxH6rtroD8La7cb93/P7tcKqTogO4Y714DS3XAdjE6Cw7UU7/TYrrk+k7jCPuBPGs", - "sWvDEMK9lpk4AVUD/tFtvmerveqA8XtALMNnM8TgbXCx18tapyawqbQ53NCgjVe/OkE+Xu23CfgPYnkb", - "2KHbJtBvdWHFbYCXHTeBP9dFMr8N+LJjE3ixKIBdYqPXRi92XsWrVgBNw8mFQNqNDL3jKCer/RqBKyuM", - "Oxc3Xed+Ejs0gbNL5eYCFItTqZL5X0lf7wj6rLHz5mGItm87Tq335oHOeX7bUcqu9SFO+UwMJ6DdnOvX", - "RndBH+jyXaVHA0Dv61WmXOwG9eVqtw2gFc93B+w7NYHtJhoR2LpcRBCUc7JMpXeMV8JuML9v7NswSAhi", - "7Qb2nW+9AdC5/l5ap83ylXJmuRvYet+GQXIjlTvXp8evuwE+9e3TaQMwSmLWDdAHsa4FIRBQLsTkjZyK", - "ZJlkgiwjnUCeNfRsGsBx4wiDE2474udZvVMjWJ2/0TztJLkJZOzQAm73SVb71IGecwPR2Dxx8goQA//c", - "Dpbavaj1agSM5Lkb1Jdll2aQRnAnQi9yyusMu6HvhkF2nHilTyNQUC20veXUj5s6Nw6jc6HCU0xX6O8r", - "fapAP0Zjx5IykAYLH6QAVmInm2YHJexj/1bAmtTFHUE1qya7AtmkNd1ybc3q5C2BNersO8Jqv1nsCKib", - "Jrsj0O164K0Btip8t4bYrNx1B7ftBrkTpLW7827z2HpP7g5uk6K6G5SNiuntQDWoorsB2q4y7gavSVe8", - "HYR2tXA3eOtK3G79m7XJ3WBs0Mx2BaTz+4LToNftiISrV5gd57BFFe4ObZsCuCukFqVvZzAtKtjt4LTr", - "WrvC26q87QqwXV/rCmer+Xl3ULdHzu2W4NvAajNZd4e1wfD/8eem96C30Zdj20M2vFT7x1P/9n6z9E++", - "lh5srXAhwr3yYmoZV4zPhGqqD4RZGZ6vProev3+LzyPhXXqi9SU8n+J7N/xA7ltlgP+PJ5XRDCbLtjIV", - "6HlUepRVqlQddY4xb7XhtlqOG6yN7dbNDVbcdrt3i6G9g8l2i+lym8lxo6Ww7V2h+iay8XmjyUjYaudr", - "sdJtNpGt2rY2m6jq5qB1S1OLIabZ8tFgXqlZBDeZjdrMHo1Wi2aTwGZrxJYbf/NNvfUlcfUdsP3Frf2h", - "r98tELnKz9AFos0vRzFx42saet8WyqRCVeyEYWfHP1QrjfXZaZHnwglh9oPvYOnx2OC1Q84x0rK/vR12", - "9bjwDon34nRRrv7R6WKL0wVu1UMmbG04j1tkvI/40eSN4X1T24uJdfeSlbbRTbbiDwtHPa6BHAdfsCbn", - "EHLbKD1rUQw/tL/sx43ncRx9pLoziNKvSqSUl6YD6bNTLk2Za0ouFiKV3IkMy6gkIl33L9aq3AjydfsM", - "DGRlgx55yEYeUqLGw7KRplPZnZOUs13nJOVvj8zkPkoSlgvrVJVwIazlM7E9lxHdvrCxZUZkfCnSUIxp", - "fVyfLTCVhr41FzczgtumAl8/zZerMLEOBNQewk0fUdT2UTWSA29WSLf0UVvI7VzkxNGgQIuaYepkvLvJ", - "YoFOrJQDETMke7f/4JdMGOQog+G1ioEoNBr5BBoR8JrPuFSWYlCUuGZh3OoUhDHajI/ib+hKzbQJ+8ry", - "YpFTCmlaq0+1EdMZ+AWHuor+93rKA7bnlrkvCu2LRdp54WAJ+yvJyypb2ev3Vneq+gnn1Ov31mbUyPjX", - "nIA34ZUt8pBFr9lJ2xPgtaCihdfcpKUe7PuwSeFC8h3v+yzSfq3Ux78KUVB9DHDnZ7ps6b2kc65kcinS", - "EDAlVWLEwvtx+6wQ6M7t54X+mIUq5w/foks3GSrIGDCVmcOqiRNKiMnThSxxzU8b6I85DcsjLua049mQ", - "nYfNhMHJi/W5L6RTjUgJhUWILuu7M2Qvsmu+jLVokIlhmc7gAA8rYNI9p+yd1Qa5ESmPdSxRSoJPukzm", - "wR8+sj1u2S/C6LYAj3Vf8k1oUZ50JLgqNvh8mylTuolpV09emorLvc9riJ7rhGbDJM2HYUYjf2zj1aiF", - "auk0OAeMS5OIGsF9npg8qmnjNjf4LbGSVZ6/ypojt9wisBuepW4dLxnNJlsiJCvtHmMid0qqRJneRkqn", - "oktGOLBLrmaFq8amObSSPCYL/D3n7ShtmU2ydxsm3RWDiOdsGiHYzI1YaCcYddg63KdL1PTHyGrSycHg", - "ToKh2YbeQVK0dXwUHY+i41F0PLToaHn6epQlt5ElBubflibhe/we7DLQtDZdOgiSIXXkTXUxwfToa9Ya", - "HK81bj8tc+nf32g36yP9F9PTqRWdltbHOylWLvPUDhiz2xSW61P47083hT+OvrDJMfJuqsIq5C5awnqf", - "RwXhUUF4VBDuMxF91sHwD60spvsoDwQJdchex/j1HQoWtKglq+T+qJH8oW+3NezcIrqCW1pzyR74OaSC", - "mXMrqgKnY82XkL+HWQcrxs3g/ryCpx+apa1wyNFi/hqfeiUvHDohmol0mM+GFh+L+IRn99r7TArrUk6Y", - "Xh///f7K/1Pn/gu5onYslgP78FYuxMvKS/4Kl9a5P9u3J29fsfBWDEyAU34K6cSiX7oinLx494IZMZMW", - "3ieqNvJqcqTn1d5PLBSMgmn6oif0rJBRsfOYoyOOXUmk9JmOwTug4XtIr9/jRSp1r9+DCk/wvzzPM/+E", - "hPIFTfULneK5LIrMSeDMpTm/42l5n0ZyZmhGbOSVjJ7xGWelS2QaMjcx74hpvxycF1NeZLBdDpxHcSsL", - "23XTtkRb3VqHbXJ23aLCNnd51GAfM0b+sUxOTXTwB042vj229I5Mas1XvxOfauj1yKoeWdXvutqM4bPR", - "LjdgX5sf+gUvxlvegHFoUIa3Dw2tWoY+cWJRSRi32+gLuRAjr2R7FF65NUnrpEocc42XAsAAPS1nRfOk", - "iIYxaMyQNxVVZvhHRUeGDKpndAGwPnVe+wrummu138N57eCEvHpHKp26uTF8GfcPaB/XY0cLbi/X9+87", - "6bxPMdyeskxfi5S2quzK9p7+JdH5ss+e/SWT6rLPnn77l4W+EvttZ4fX2FgPedcUufWL8nqS3NWb8hEb", - "xzvouE9/vL8K/9Y51cUrL6LjuyfHbVch1oPQWuoCom5gt5zIHP43NGaXYomH8SJzcBYvncn67Ou/vBWO", - "99mf/nI2l1PXeiZfYjrphkcdeA2EM2E3ldzRwHlenp2xXN6IzHZ+MlluAL+8K/g2e1GFNnbQwZoSodyT", - "ChZA76SBlZ0eFbCdKvMWTo+MyAVvSjc/F940FZJCA9XNhBImJI+9FBhLLLir0XklyiOoeFtltgDUUbNI", - "rkEsUorsF1k23vdJaWPlcJzU48PK70W3vJuYDiygRUr/IJYrQvpSLCH0FcTypVj+mMM/DL/+wX9GKQ0i", - "4l7ks7SjS7HMebqZzICeZEzYroqFMDJh1LONwqQd2aUFvfhSLLtQMTrmUxcccJ2MKtAz7a20a4B/EMuJ", - "5iZloQnoApmYojLgg3G/+osqFjlP97s/a7VE5/9G1BbFFyJt3mjAsGo2bCLInM9E3ca/zKM9V4Zw5nHU", - "Fs/5BP7nhTH6OqDn629A//8B5l1142e8VGEa7gGQcl5bUUtWP1nSPWNE+a/r/vVfeK2PclmbxEwJtzZl", - "W0wW0jlfW55RAV5nRTbFp8UOV8T7VbCac5Tdk4pVAt9Jyap2e1SzdnIqKZzT6jZSDff8O+q+LtToB3wS", - "jEpRWBsUaVFoRwCePMZSLWma4RfkzvAP8GKB//VxQ/dRqKXvV7uNKftWxJwhzm7I3mk1gFgophXjbIxv", - "WG/1FXg5LwRXRLFw0ycR5g07bt6qAmYyudyueWK4MWlztJ8YGZhhWBvbe+YHw3sVfd5/1Dl/N/ZMkTne", - "5K35vTbyF60cz7xTJMOmfQrBRtT8aS7AetP1ek9DNV3ygVEk9zfQ3fToksu3aNLYYEWXxmmeksAf9/3f", - "H0QmePWDp+XVdd0Dy5lqn+5ghcZhszIUgTlMrjCizw5Rxei8m9s01HK/fis6aq7hD3NrDDil/i3H738l", - "TbQ0BpTXiz06XDrn/H6qf32hKilXM5gNz0YB/TbiaNm+gq6Dp7vhq5NZo/v5qVAMfiv9kP578HeWZ1yJ", - "PqlzMyOE3W2cZZdx/utu41xL65qHwVQO19IKZrTzOehWR1gnj0cr7uaUz/d0ySiB73TJqHZ7vGQ8PqY/", - "GjxbE7RGSmmR1NhgRVFD/0DMWTzu+79eqTT+GzQ0Etz45z0+UHbX0MIL+VQa6xjOg6FKc++qW7mDvxXV", - "zfBUFnbLfYQatW5T5+3xg226kdzbUF4+j7iaZQ1o8MH/vuHsb6E6/EF1xg2beF/K5DkoeG3DPLSG2XHw", - "O6qdAHKEILdbkDC/q6hOw64IVXy3bKP6FhX35Zp6uwN53EHvbaV2RhKlbGpZBuuWCv3aSWbg/dCOvWIh", - "LYgFEhtywc3Sn1L1RYSHffLEFFSd+1e578jHOmjfTYjTQSPvVqLkjpp5e37pThr6pu6Pmvpv/DngPlS4", - "ezCnPxrO/6iG8wcyk/9mjeJsImDTPdNEakLJ8JDOnu0c+tHr89Hr8/b2wo3l5u6olKyV1uikizT0elRB", - "Ho2Ff8QgwTVSaOT1RuQZTzAx70iohp36UDZghquZYEKlPl1Qq7WqAtQ6blwXsNhwC2Dy+YVDbZzrWfi5", - "MkfM3S/jaYbN2D5Cy8TLMaoT3nmUP4IfXcN+3LcTXXVSXQRWY5HVu0qqCLSbiKo0f5RNj7LpDymbIg38", - "ToLXb8ceYRMewLN4R6a4vWLxHRlkc3G6Tsyyresj43xknL9nxukzDo0oHdGtzVPraY/WLVS1vEe4io2Z", - "jx7OStVM6y23FspAOrK5EI2XFvqdeZdHhu3wMYzMJCyHj1jIp1VHT3gmRlOeOG02jIDNwgNSDhNnexfF", - "4eFX4in7RWtMN7D/u36Z/v3ZwXYSmq1V+e9NatZG2FFsrvR9lJuPcvNRbv5e5WaN2BsFZ27Iwj/N4ENr", - "TDD+jNLEFnlO4qQtEJjC/Dv4wkRe6DMDRPcxerfbYEwE+KnI+LKxet8x/MImwl0LoQLs/lq5vt+RKa5F", - "6zm7lrkgVWcnTeeBBfgNMAHHVSI6PQr7tvXBnjMyIV4FbLEMohd3mAPWsceuDcViS9SclxOKM4nJ73Pu", - "SxIKlXYe+kH1l35vuWF3117Gu+5tke8wfsedvQqTuZd9vQfFrSx1/yBaWwl+R5Wt2vFRX3vU137X3kK+", - "RGODVPe/RMGOXjJYOhYmi38VeWcx/8dWDEuW8vuxt/O8s8uhZo7nqxH7juf7f5xQwM2SsZYjqTGBzZeY", - "8d8ncur1e5jHqdfvlWmcev0eoFzHTOhV99q17cEf2WTFx5aXHrZfyHYprQCdQK8GAsSkILBnWI6rjwVw", - "CP+uuUl32bgNqLXmHvnF7FY1s0HIqx8SG4S/Ma9B+AOTGnTctlM+E9/B53P92uh7cvYHoMNJBeoWvbSh", - "/aM6+qiO/rH8FdaI4A+cbR/24iV5JJwlRghl5/oeWVOyCroLf2ro9MikdmJStIGjiVhqlY6uvB66OV+k", - "78TEjRMqrVpwQv/WtK+ZzFtLfAJKYwEkrRi1uaWCjaPgy+zmQTAJI7Zj9NC72wgtpUOrI2CTu6ziZjP8", - "m+CAeochlpuHWN5xiEcp+KUVMvSbsbt5pGTDrwlGg3VkATRHQzAQQcICT9sb/zMXM8g3kasZZZq4FpP8", - "fnJEwQ1iZAsz5YnoxthAIjt+KVQZNu77r9VlA47Xxu1a9Ik1odWoVOjcyYX8RYym2rQ5uoS5C5XoFDBh", - "yq+0Eal/BQLTPAMDUNsE/1XwTLomBqAX+O4HaOsbhTQbh4eUgy7T1i79Sf6Ontfuqhkpnj+MXuQB76IV", - "xS6POtHjxe1RZDWKLE8jrQIrNGiSWYu5W2T3I6O2iAo/iT/67TPTVtwjZwVwnfgpNXzkoo9c9A9o/kLs", - "/4Nznu+5SjPxn/yKn+EajyXP9Oz+WNG8EX4X3tTW85FZ7cKseJKIfIvVK8WdJazF5jShVNqF3OQh+cgI", - "fyeMsJnUWhxt9SJ3o92jAoVywqADp9OMM4LjUe/WkYK/H07dD5S6nWW/41dyxt096ovKQ+zClsu2j4z4", - "UWv8Xd+9DV+IxkW+z/m/CsGwQYWzbOAMzxlnmVYzYfyFWtINGjCPZ1UYd2LkgThbggunwhggEJ3JZHkb", - "o8IHD+KUIKwbFUIDRmM8WGq+ci1GAA5vsX7X05LirlN/kjzhr27Sp6IBfZEOhoYrylpy+0zcEUSLq6gX", - "UbB0I7jVqjzKgAs8y4QJ1eCgrDHm5F7mVD7FiEzzeyrPVJhshGtoeCM5w++xRrWwTiqa948f3oTZofyC", - "WfGJLjCPOPD98X5AHhuz80KnFuSpnMtXz+7t+hZ0gXP9vbROm+Ur5czy/jWDOvxd9ITVno9aw6PW8Luu", - "cQBo3rhITwcMW9SWE2gFZUDnwqEbyOx3bdSq7PF2BnlqpHLn+jSd3h9TzD3M49ddGGG19SPze2R+v+uw", - "J2lzCGeeC54KM5pq7YRp1805o4Y4X2rMroWB41Gp2KB3U9uRE4s8405svwXwAD50iUHgmSwzVfmfdr0F", - "hKJwo1QniNIjXbhMKrFpPqEt821xQmIxEWnaYSTHZzORjvJ0umkMasX2eJIIa+UkE/vs9Pg1DhWfe9vG", - "8me4yx7703yIPc5AniQ83+LnhI6PMGzGZQpbi4wo9G0DvuBmJtVoop3Ti/UBvsPvjFox/P9kvkNpDQ8e", - "A1DWgL8RU3dn0KbZ7/QDfL4zcKfzBv6r8zsAbtZlSknZbHrmMzHCnKq2CzL6QuRqtoKHLTiQ81yYVg/e", - "U/i14ru744IJeItbLcGODrW7gkbjxSixdoQbBF5xm2kEfV1hc6Ap7k3uDSDesY4IKd/iYoenNYLoqZnR", - "hdrgxFe2YTPD87lMLLF5BNF+JC2Ozqd8FiQE+Tj/vusjGa4snPBCp7erbppOzz2MtzptstZ8r69xnaVo", - "8JrQ3vgD/vOF/Y5b8e3X5L8avp1h9Nh92Ghua/34gFai+1PsvdWpg1IfWj4q9I8K/e9ZoZczpY0YJTyZ", - "b5EqRBFsssw5sUdYIHRr1eg06pcb3leiikxNf1MvLbTcZjsLruRWKcWlAkYnUkYdHp3Pz4T7SUzeyKlI", - "lkkmzty9vnvbBuhduH9zv0dZ8CgL/oDOQ03E8LvJxmJxNbfQute3ZF3vjg0YDsM43VDZ3nhq9C9CkbpN", - "tTYfTs0Oi+zAjB03joK7Em7vMRLI1gF3YsGrXR657yP3/Z3XTjfLkXLzEbodra/1NXyGAfPMJ3kR5oq3", - "ph+9azAsUF1rbBHNpS0YFtkahMPeT4ARv2k1273lN3JRLLynVmm+q4Z6Nzy18ps2W10dYLTZbYHXIjjr", - "LKxRZt4ujvXx3nDmdP5G81Sq2X2KqQi0m4iqNH8UT4/i6Y94OShp4A8eaAUc6WF05yrcrnzpUXN+ZE2P", - "rCnfon39QbjTygNhQzL7a8ZZ8D1J8Z1Qls+EX0xqy/pjZq/fq79kds1hSaWXmvN++h9p8uWOcUUsmDKC", - "flm5QIEDCtVxc1YCRBrKS7XEh/DgBIvVVL+YzLJhPb1+5Y+f5kJBLt6Z4SlsnzZyJlX8B/z80mhr34fv", - "wOvKP5yRiWv8c71noSyfih9N1wSsa3f3FjPC2tWdNtTG7l/MGYHFAVBYzXbaokrqlKNfu6X6qm4RdP8y", - "twiyk3XdqXqKmXVUat4h8j3yfb8cXggpcTpuzDk3M+FegOEeXPPxr3vR+AnUkNcgb9H5W/o8av2PWv8f", - "S+tvJITfUd0IWM4mdxpq8Tm8aFoLOsc5b76heA6aafsAzDQpwXbjpLUOj2z0kY3+IdlohQoeeeiXw0ON", - "4E6Er1o5cXO/zLQBfkeu2tjzkb0+stffe8CktmKk1SgVjifzbYlMFGXJssz3TMvtTsWkmM1gjoG3Ekhh", - "u6fx3kCMbenAbpYjcvoeZdK6TpFZeFjUiUEn5PaJVlM52xQDSINZYa6E6T7OCmwMQ6RfvHz5fad7KZS8", - "EsbybKSEu9bmckTRoCMyRm6vNUftLJsZroBjRYDMA2QEkHY2tHZzsbAiuxIWCaRLMrfbvF1UpdoDXA0q", - "cHeRYo+Xg9tIry6hhEBOXgdDusbtTkP4RAmhjYLDDnhGuknV801Lnvs5ok8eJfqXl/+FTzIoOwTMlVLI", - "AQYZnbVj9XfQmB5efFvEbgKVsr254GkmrGVaZcv99qQISWE3k44S11XywR6bsiyYkeOTzRkGJgFgtX6I", - "N/KvU2p7soFmB86fpEr1dcVz8/jktM27cS7TVKideQd1a5tYc9C+n9aNrzBODJBefiplTndwCG0QH436", - "lhLXo2scfNOpwDFTq26pHr7Iu7rOW89lectz+RIyxfV7La7Jfu3RJ3kDpRBujG4f3IL928Ja/EQQes35", - "W4GcyGBXFlJhCSDM9bfgN+Uf0yLL6MA+V2A5Ud8xXa8ezlKSNg3QTcls6fqobe6kbT5qgo+a4OcxnTfS", - "7+88ZV8DuXVhw+9zoQJXuk/uqytwuzHdeo9HXvtol/5D8q4qGbRk6VIia9ye0I1hEwaQRLqB39y3BH18", - "kfyNvUjqIpm/uhLKNftS4+/kMc3yObfii/EVdDBzjJbv9emPVyoN/3yrr0T490uuEtHZq7CedX3dZN8x", - "6foXs42QFd7zYdg9T3yjCTfwV+H0aKL15YKby/C3LSYUHQ3IqwqeVb9Ed/zQ2ukc6dUzf2i7kHBkPrlP", - "v3cpltfaVP41qgLpcmjreSCa89llzbkgvpizoowVsLOYrqLr7lQMCetpN6lZsGSt2BO+oCABsHoARgaj", - "B7HW+O/S5NFp17SyOhOvjNEGmef6xr2o3lihMRPQmmnDCpXwAkypZbEnJm4SgV1DdMqrhXTorg376a41", - "S6V1UiUOVRqrC5MIy66lm7NUTqfCwBaBOsjsnOfCDtmHQjm5EEM//ovTk5fAelK2578MaUbAkOw+y41O", - "C4CJ5NjHSlB9UFttHzUg63hyOXKGJ6KEHad9Pjf6WrG9uLb4SxU0wcykEn2W6KxYqL5fyqgwWcM4r6XI", - "Ui8fgRgTMMYHtZN6oo7FUQtoVHu5EzNtllU1yq+/8YRTf7PpYoRbxQK8FYGSgxPrCAV7nlEPTDUJW+ia", - "6nGfG9AWvO0TTnoKu0PlxEMvlha4P5hWNJML6eyw0dzsGl4pcCoMDtY6vsiZVOxHJW/YQiZGW5FoUKe6", - "aenOS8eVLR8hyvV+3qbHOBug9ssTjBu7SaVpPJNdzavYM9gEPvZ/XcEpIIoGis+ySOvxOsYSLUxCeiCt", - "1Q7ZKblN4EsS3YhoYZ7a2wgXtl46scCx17VU+sCN4Uu6JwF9NSWtgO+MErKGR1tqAHMxZOgt+RGiF1J3", - "54mvcIVhI4aQ1G+8BIRdhE4kGvqMZ9d8adlFDzHoonenXVzbvOZE4W+kEp9/o0oGuT5DeMHwjxl+ZlOZ", - "eQHq5kZc1+d4DxOrpeUKjLorw+RZdga9oDvS1nqYa7HgamAET5HTk4TyosjWLAwBSa51kaXMJ71HU8Nr", - "bVhNxO3tk5DrI4CpNNaV9pgKgXJPogSiQZT1/SOImMobFFY0v4Wwls9En+ED1EXvx9AT2dARm2i9uOgx", - "baq/7UmFBRilFfsMLhO+8U15IZwWCg0WF73aI1Ibz6wbMANr/HmNOb7Rs85KC9Qkpdtf1BoyPevH/ZVq", - "qsu/rrlRfSZcMtwffgZJHBb2KIe3yuHm0qL3LIVr5/HbksE7idINoqpVyQYYfRbz8BpdzOasUFOZUQlW", - "ZLdkhR6yMfKRMb6i6oJqELGaykREaJlU1gmePmc8yxjeU9iqxLSgKgtuGMioITsTZAW1uUjwtoU8sMgy", - "BjjRyFgeiLe/Rsa7ejzrpzPcyuqCxWA7y6thUevtljhceFpEoisNNoElLrSSThumsXhulsGuDoL0pOMZ", - "shXzM5nh+pSqjO43ZYg9E7lO0E3gei6TOXagmegkKUz0RagjfntFTDjl1XKYeEOUqjKZZv2nPQ80QG1P", - "At1nRljhGKyGJ/PK6hrHUfxqZMW/GnK6aaUdWRKyJZMqMYJbuNZXtsuC2UElQSXrUzOYl0jjBJzOvQG4", - "0rNxEzpwz1tYqwOF0TiVV4fG/dhgWg64uWZbZnvWoXLEQRrYyjptWCj6hO1vGjHIhQ6UTY8OVGQS3XOa", - "1VAjMnHFlaPbubSEys/JCQ0awM5UzgRoAX8j0ukHq1LZ1ns2e9LayhQqh1Xd2PqSSxTcIL6qqsBuj5yn", - "Rl8JxQFJF8Jx1A78yS0Bm4nQvT3EMOGNPJHy17Um0aypnXoQA2DrcioT6o+5PIIjVJtsGuP2VrmXb+G3", - "uhlxLmWTTzCpKmFBQ3wnGx95wcbia9Np8BuiEbxVq2SuQza+FAYerXgux0fsB/yDvTg9YRRqwPaMwH/R", - "iyJ9HJTJXcLM2VjcOKEAEcZHZSp3P5/4G5Q71QnP4K02EdaOj5hdWicWzH9gplAKTozDW423SpbTrRkX", - "kzRH43SYP/wUBur1e7WBGjXdgCrtyNagpGzDhyDNCBmAWxEdHHg6OSBRcXJcO+9ACyu0hYe/gWK+dy7/", - "XoBssO2LcKZYI5jvz89PfckqyxY8h9O95iZFN7KB9JgCswfWpgvHyJQrfyEhw/5GZmd8aF3mXn54LY9N", - "CscWfAkv1lwt8WEbWtXLIawt5kQ5YTgy7ZeZTC63XpYK+E8CTYMm4X0J2ZXkJRJSzg2E0O12JMuJ3PWG", - "1Limx3tS6z2psvUjPNkHvC21n80935msyETidEMxQChHFX5lOXfzYGPHtYuUiQwVrRaVYtZgyDl/+4Y5", - "PiOJpKdN0ODAijwXJuE2SK3vfjw/f/+uz1702fHJ31p0mEZl/m8Sq+uhtYi4n3ItA/eZM3KxaDEG3jTB", - "Fte5No7dDEoX5hpwWAvsos9C3Ihkyw2Al7cHvIKHNz0YqV+eNp3QxmtSBQV/EMutDO9SLCeam/RLYHdh", - "PY/MrhOzuxTLT8Pqaudyz4wOFrG2gT+IpX9njtrnDx6PaW+JAb2CKfbZdzy5tDlP4NbezIVuwU0D30P7", - "/JynFPxTOsVdimWoBWhtC3fqzm19ZNEmbnvy7vTH8z47f/Vf5y8+vGrnuavqoLgDgzlLjM6yM+FcJtKt", - "rMZia2apuWc44d7Ep65sEsNNrNO5BY8rBYHY/d82e1rfjUdG1YlR0amPPGJ8Gp7Vclj3zL2APY1umqKf", - "EM9vBhHTufMeL9y4yjsgtJoJC0jfRS3B8Zat4y3vezxvj7kF/6SxtqmjumnzXkvFM2bXt3DqvI9pWEFg", - "NV1WokfLLUMt72WoFVz2GBKPzi/aT2h9hzey5jfySoAa+pJMla0cOZNXgl1JcR0dsqhD6QcO9/hpkQXe", - "/cSyn8Tkw/nLaMN5Jy71/pB979vBI/RzfOsMDB1sOzHQVkKKT9v5IdHbWe/Km5u245Elt7JkwIoRYEXw", - "l39ATtx6NDsaacFM5i33OV9iyUxAvPHaWsYV4/PqVbr9ZeBNJJT194EhO6sZ743wQ1nv7IilhpG8gv17", - "kskc4y6ASNAVkCZFzn8x5GBcTmm8k7G8w4Yfx8CH7tyhDJaIXow7sIhTLuntqvFUJsu15X4OFrGyLY9c", - "ogOXKNHiEzCKpgO6d15RiQpqZRdpYdBePVo0JYfgWTZIMp1cstAuWoAizsJpLGSWycpB7FRbfRNXek6h", - "T/7ROtHGCJtrlWIsVBtX3PFFrroFG47uLb2yH1e4RwvPOffhXZU9cjq89ABVZNq6ITtHXdGZZWCb/kEg", - "NRoDdOCRLAuP+6PIj0UIDYNHfQWO7DPMUwWUjB4a5ApPScASerGoZt/IOdy9kanHLn4C1km4rgra3/Bg", - "jC/+ylWfSPdCtiiZZuhMMhOjjC914cK1x38s+4Qf9n1Wg6k0Yti4uhjBb4R1mrwZF0P2ApVUI7iDtGVo", - "N+BsaoSd+xUvOMTI+UuAbVwgCCsjbAGBcGLqYTMFdtmVB+CEGziYRe6W1Z/C2xWdjVaCPCI66oJ+tXfl", - "8m2Y+MjmW9l8wLOq7H9ANr/xhLbx+ToeUbBWU60M+B6JtFwYPj4myGxGQEHcOJHGh+/4ihx+GVbfi1d6", - "bd8hP7vtW3GipHvNZbaVaQYZkKD3rNIOWKJU0kl4W6X5fmpKW5n8I51tpTM4sNEUt+zhyazpeHYjMutE", - "3o6SFLvKtCnx0Pt9OZGTyZyW6m3X/gphCzOFWCEM9exgu8ZJbF/thyAqO5FTow5Soy0jBgL9tqSdR8u1", - "uJnzwjryM8nKyyDZ2hzIRTtk7zSbFoZUi1Vl5hpUCVJUmFbkeOVp+3OQcNOuPdLxVjqOB//JiLn1oB5E", - "bNYQG5ZYgFZartrTAQhQogPA8EAA7FoYwfAlq8ijG5AtMOEpODIvvQobMjDUCbIqeRtGvEfh+0Hc+cqy", - "sqoGlsFXdZBXxAiCBTUt4j7MeI5+UXQPerl2cTEixNiuaOXB8uQMTy4BmldV/D3AG3OkZbmWyn1WPvPI", - "Y3bmMZ+UvdyFtQRa7Wo8ge1bNZMwxy8FUlmEV3mHqZNSl/1d4w1Nk9y+P2V9s1aDai6M1KlMKsXMglUo", - "vI1feeehbhRYwrknIlxZxCMNbqXBjUdwzyTYdDq7UWCuGjxNqG7nQKhEpyJlp+/+2hFB47ZNlk5s1dJz", - "Ndu0xnckoU7STGz1IAnSDIxojf4jnH1zeLiw7F+FFM7THb09KM2kGkwzTHyLrso+SKGjJcoPfVd6W/EX", - "eKSwdQqrWkofkLY83vlq6huvhusImFGvcIv1iT5Opl5FRsTC3eaZETxdwv543EMPMdAcySwLd2ClWW4k", - "PEWEtXsQY4RRfVGXbr/PxoXBtK8hfgz+HcO+xhSbNjbCR5vDBowrqTWes3EDMmLEYs4N3NazJct1XmRl", - "LnjuWMKt6JqV456IpfWIHuXTVurxGPrwt9DNh3TP/lQJJvjadmZVAgw9VkNAtVl1G1w/OmGMNqNmF3W/", - "bJ82oPKbN2kp4Y6OXn34MHr5/t27Vy/PT96/G3149frHs1fHzT6oftKtAYphUZXowZjk0MVKIRwtUCts", - "pPWRD0atcInmgf1Khx98UwgfrJgDcIS18OhqxI+PjP5B6WsVcktJlWRFKtixD0fts9fCJfM++6/vP/QZ", - "ZVLqszO3zISdC+H6DKsE99lbkUreZ6819DkXN+4cbrZ9VqHuPjginOnkErq95UpOcYanRkxpjPduLgyx", - "yYU2YruhsXI2Nazolwi50S/Lb+EHAtNZyoTjs6joNAcVPjz7rc76kfFuZbz+0B6e466dyz3z2hApvjVd", - "TWhIegJZ/EMorN+NRt4zr0QZ7jLvaoTierp8vy0hEnEII/k5Adm2srmT0GYIbZhUqUyIm16T+lNYkd4L", - "z7Oeu+XcWOBDOeVHJIaEiSAat0vakRGpNCJxmyhH2lJU2GpOXz1lnAUIwy0FzBpCO+lHBqZNSjuEwK+l", - "CREIf3113men78/OmwVcrq0bBfbTfGYTnS5RtACUg9Mfz+MlrQ+L41dcZuBy1yLKaGnN+Eol/nmGMekV", - "V4bQC4+hzGtc2WzcRlOIe5LafVYoCZlmK5kMKs88jxL67hI6ps6tsbCS4awxhG7C2+ZaWbGD9KYOzIhE", - "YGJqf018LU00WHj6pIaI/nAo/s2AuvXx3RGx0i/AvxJ+HmWgsguP2kAHbYD261OoA6snc8/6AGBn4yH5", - "k6ihcclOMT3d1Kd+Y29P3r6i1EafVCXwM6vqBF1knZ5Wr1bZRm1mIRdtPDouOgCMW0WCE3bmYO4WWT+k", - "RoWOWIng8a74m5dEmGLLFbYFleJZUyuW6FS0ZIfEBi32hkZYlawg73/os3fasde6UOn+bQWmX0lJiBsl", - "I2Tafmk4PGm3v33xmXhimREqFUaY6E6XUD+2xxW76L247rMzxfP/66IXnAr2IcNOVsvVEjtLZ0U2hV1Y", - "giQFt+Yh+xCys4eyEH4EPwOvY/UrsRb0Bc82pmay0H1M2DsM2VzGkB3bR576dJthamMAP2aBYzMZ6wx2", - "NZYCgLtK59WTeJTMrZIZvaw9bjygVG48kd0e7TZkFCtzAFV5fIg0qCD+p00cBqPDqIgJWvmrlGsn/+18", - "qj37F8xiywEc68VLyh4C5ukO7zvH79/WOoSEqbDfAHCYRogIC1X5jglS74vOGxf1SPCbCT7Vi5FPJINP", - "Iw9O++2ndN9PImk+ivvWwCnII20RkjIycrDx9WoU83vLuPMZ7dZIYAr70WdGZNzJKzziVXlMLmV7Sjs6", - "NcyGuT9kP1rBxs5SlrrruntPQ9TTyv7XV7ZVE3mD4TRdk1FQ8E1LMoqnflv8JR1ZGmBNxZXACXMlMK1c", - "gDSXU7RTlYbDK2kLCB93fCIz6ZZD9gryWlY7kOce2emeDvyosGjz6ZjKo09CNx5Sj9d6YP7hsRlwZCsu", - "J8Wi8MRZw629l2/O9j1qx7DdU2FwA1Qi2LlciEwqAdkZP60QW13eo/zqhnuwYZ8Y8x7kbcm7WDZUtVsJ", - "m60htFDOLNf8Qvd8QYlDFDPVDpblwmC67P3GINvqro5S4bjM7O5RxYGcKhvHuHNGTgon7BbKwyWt096c", - "p+DmC+oKFs7cjNK1TfJZpxKRktcDprREIOHJAX3k+kzcgF0FCy55/vDyzVkzyqO60BCIXB3XJtoEY4+0", - "/qz2sAA/7ETwkH9ztt8s+tdw0lubdsySHTJm4feyuEdti2JS7sbbkWyqV954eCW9N2Hr9jDv1XimlQX7", - "uZQB1x2UoCTfKi7ewDXKOubVPMjhcMolXHPevDz9rcqLJC+Z0aOcaJcTSf7Q4qF6EvcsFrIkvyUb9jhd", - "ojRh9F3ZsE9O1ch9ZFqCD/T/5uVpmZhUTsMjSGui/lEzs4GbFyJJA9xO2SOUTttZ5vH7twwaNHDNyjjN", - "Nmoy5LRM+wP+2HXiz73ABsS3A3qS8ImiYmjYuVxINRu8yDJ9PaAn/Mb1Ai22p5HlRvCWCVGeLmb/VfC6", - "PChhb3N/qUKE9eASmAaX+VTo8FNL1vuHFXrVqQEPo9N7ALmHAzUpZ7cWetslnebbb/nlzX3VkJeF7p/D", - "hBfn/ijOtogzzR/8ol07i9+4cc7Na+j8pZjmylLK3Si2WimGEmus0S/yCw8X6Je95MZIgTVUYtKZKdUc", - "lQq51gRLDjjmy4b4MnShvEnVErda2OfTcoeV3XrkEZt5RHlYD8wpms5ltxe920l1FbCcWuxa9emduGab", - "Kz8xbq2cKR9ihCSxpfhTzg2oxe3rOcUG60uCAUIN8cog9rkPTqIZNBR+si2Ju3et6nRvtZs+7ctqiQNO", - "31v9JPKKrGheJRZ1JoXN7y2h9DU+BLc8xMXyUSsGdjbnV4JNtJuTnIt+RLaOO7Unl/gCLS2rgKeXGCwn", - "g/7D7ESlIhcq9YUlqjGHzxlnUK8sEzGxW/CNionWJigrpfuUPh6PzzS7yoNP9FRzzifvc6E2PDoqcR0V", - "HMcnTEd+AtuqsTPpNsQOhiE29FzTB8R9xGvqB+Wx4OJigys7r6UCk7aMLvUJnWEKoYSh1bWcq9siSb2+", - "VI8hrShOkSoQ/UCvbIovhbQlyhYLYSwzgsJnV/Q0rAEW6j7NMeWSM4I7Jh3oahwt+ZJnO8Wi3pdWVj/l", - "R6VsMxE6PhkRXn9S4ruFToazbNaczts8rICGMdjJky4Sg1aColTUclclo9mdK8g7Ja6zZRyKTx5E83DS", - "ZQ3mH4qKyjzvgTZRKxXXrZNpVGMCqIrprB3GvXmBZdwBDr/IJVRMbOXQwHToSBdcoQmy6nf6t7e1hLCp", - "kVdB2fBN+mzOVVqJM6YaggOyZw54Ln1a7CNmRILVoWYsk1ORLJNM9LHWuy9biOqQv73TZHydq5gwDlpU", - "qntP5cy/Dw3Z+VxYNHiyhbYOAvn9BgykSoskZtzLjYYhmeVXos+MwIrrvrrKfm2xfIaJYxNSwrsyXT/q", - "nRlvw/E9st521uu3C0pXjgClH5L5th3N7lm5kfhqKbnXFhLzcbO3oRgrOGIfMR4xnGg4CWYgDfdMf/3w", - "Fw7UfBxax7EwPxsnOhVjf8Lclr+BD3gcugnpb5sFnLiE6fSIA+PRIE0y4y2m+U6pyvgTy2LrPlaOCuvx", - "bAe/oeN8nIIvLXtKrObVjUhA+8Pcmx8CixrvHn8CB9oQfxKf39YZY2i9kGmaiWv+kFEWm6IgavtdiYXo", - "mA/s1Oib5StjtNlg5OQqFcjeb5aDjC+FCeEOTE98Udx6ooohq92h4RcQApoJSmI+19YNEB6dtGU8DkO5", - "Kcghe65tJe4oUAlGMPzXgGr0DnAFg1dUwJ4iQI4wpdIzun+sz9r2mTaMs68Pvyrn568WT2wMhcx1JpMl", - "3Zpp0FRYJ5UXWm/09eBKZ8VCxEziEhcCW53SWbITZ4NhHN16BtXwDfgb9IrwICt9xkrfxpJoD8l4vJzz", - "KghN0Toj+OKIFhmXh5IUIz7oeLDeRxn8AXpbAJDozJc5krHksGc40sI3rpjO3UAqZsRUKnqVCwFh/Hql", - "SHZdBrNUTHmRuQGsNxMGbR1gs+PZJ87Js4Llj8K4XRjDTo2QBh9SDDecx30/YulUNJYtj9yAGA20O9rE", - "Ukw9DrNawrGRadUZYgvbi3WjFxJ7YrYGaI+/oku3ParymxGyIZH2ax9RjI4KFXMM9KNRkLjXKBVKQq/c", - "aHjZN6NJxpPLTFpX+1ooI3gyJxDxqxFUq7DvYy9HLrP4gqYLF7+F/RlJBYeVCUcgbpb1iRkBWATgmqZd", - "5MTLSvDxS6rsyLO2ytd6wuIhe1E/H+Jf6NRQKTSR6JkCgpOWmRB4xy0r1CWEblai7GqwgPlxqD6Sinrh", - "9Ybz6fV7Gw+o1+81nhBxw7Ujqn6unFH1czgk0AXWTqn82HBMBKV+Tr1+b9NBwd115aSqnypHVf1cPyv4", - "hTZ8ncP0ezcD2N3BFTeo/ME2H5cb+l3c5crHDzDLH2uT9CG9p7jFx2GHT/2efVfb4PD1x9r+hq8fyu0l", - "V57zzJ7HldOnEKp9Ut1aZCL1WX2IO9sw5R/9bpXAw5djZV/HTQ0fX1bTZ4fhkGX9GDZ3t3hxOpwy3hk1", - "I4TUrE17imgo28iVdFDDYbOSRsS1EnKPgybo5hXJElUtqhqb9lky54YnThjLdOGsTAX7Bx/8cjj48+hn", - "Mgkkwoe8jPoMTCPaOvbt15WORMQLfvNGqJmb946+/RoeB50TBub//0Z4//5vDx3Hvik2/94i17ec5E5X", - "lJhgdU3u7X1z+AwV67uo1fu7Xn8QBeMaNvp0fBB55l0tmzLtoI8ZZmQ2cgHTwdpM/hYsbkRCCrouXF44", - "Jp1YoI5V6UClRBc8zyVlrkX5s0WNgVlh5H+YWigvv7UX5AYInT5GZXr5ji9gTOdNpFqJ7jrVOtjO3Wpr", - "WN322o+7WbpBgR5Nvv0a/r0lhe9KOosKReNBHDT1WKvwu2h+eVnVfEnpLcfrlxPdoPfCXvi0UTtanHwv", - "5rTHReHZJJGZh88+vDp9s36xamTT/8mvOKWhYAJYccibylkujJUWzoq9A53nn3g1RB+rC3Ue3RwmEt+Z", - "bWjvq2XBdF6cnkRrsLiRzvbxM8yOSXuhfOZ/baqfmRMmEF5IjIwR19iOpOKQnZaTQwXhQmGJAXklwsPc", - "YJbpCc8Yx1IG2tgjlmTa0s04BCraYLpgGXdgzRNZdqHIpYQ8X9nrQlGJhFQkGSdrimWFFeV7fhgCiwT3", - "fc4PqWYXCn5GoPWxawN8Z3giMrSYF5mTgzAO2BKvuBlfKGBr5IjLjHCcDlsa/9I/iD/j0o3OBtNMXzMr", - "Flw5mdghwWFSXaiKe4qwsQwDwfYHaJ+zaVgzlWGAhgNyG8h0wjPLUn2hlHaV3RkP4RwoE68RdPt5zsbh", - "92FutNNAEEOnz5Ca9vbHUATvQombXPvtxFdUj4JAtXB+meR2yN6IG3hdpdNG00YYhbDkQmVSXQa7hS/d", - "EbSZytGRTsDx+QZgAVYhHkYcHF6oF6Fj5kctS1IZlgl+JbxVBiF44js//vvz6sleqITDJlU6M+mw8qqT", - "ScVRSC5ybVxYFOmZzxHD0qXiC5lcqDG12dsfD9mrm9yQOA1JZqAj3WxcYRTsSOH0gjt6jh6y915Y2Qul", - "c+I0z4lvQBHC3Gh4XWFKl7Zm6MjGRuTZ8NpIJ/aGw+H+mGlzoeirWEiH7Jx+6eN0E62szoTXKMm+lujF", - "BN2u0Yi3EFAPX9oFaF9vqQIild0r9T46jZC4Dl6FKOd5yDCGZhJyDvgTeyu/618opGfPcGgHLeM+FVlI", - "EZ9ysdAqqmX6KhRfwO9PLAG7UL7BAN0ucazo0R84U1DhPLa0aG3C6xdo/Grh5+ceoqjVXgS4fe/9Gqoe", - "4gutX6eKrHrVVly1GBGrHFmR1Obx7WF/zRp/IxfFoqLdhBIWwYjEjqk3bP+3h0NSm6FP7+irw0MQgIr+", - "erpVbUMptFU22iLbXTSGTJFVKUhoHlfWIBTbNEFPKEx7lRATXfn4CKInTzjRyBNHec60t3tr49EbMVvp", - "0JXiHKl7r99DNbKjAbKqv5ZBGNwYvoS/g39aF8OkuHGsDPooZxZqkmqzbqmMNwGyVlakHeUB6B8eHg5g", - "PWCpZugEbfgyQJ8U0ynu5kS4ayFUuWe2EYm7PlWto271harR5EnGzXWjKnxmC2EtbIqs6vzRbtFA7XnW", - "fBH88eT4WbgCLsMmiRueOJK8g7nOcPMQWYOyhOlagz/rhYpTWC3bDWyaNAr0xpfFolLJ+zncddVM2CAg", - "ufIMEjkLxNDmmUykCxWY6pvojXueikABa2V1eTYqlbbNhnCEFq/ESDp+88gwHsEQUZUJYS/UXpwV6hKJ", - "zrBEcJHTwyG+5ZSTPQC8LWZzB6HCIqdb5YU6DxVgPViW8V8k+VYaZyO3RTgVTcHPsbYDFTS1jieXDSYQ", - "+Izlqzpjkq+81YDsc+HfVESVp4m0VqyrYXar7rV+gBJptzDj6kVwtzsboJ8SDd40qFKwv7BSvwBpl4KI", - "/UtQIoaZnh1INdUHqZgUM2wgjKk0uOZGHRAVl7ZYhIaWgJSsZ9St8eUoJKvbehvEhl0vg2HV/dVua7t7", - "JsyVTLZmoSM/mhRfFGQi8CaFRglxk6OuCCreCR4QSSzrdG79Ezm9C2szKFNb23nhUn2t9lmqUW0MCmDF", - "LfL//K//TRpZOQqO669ORKVZYCWDmbwSgyIHVFdW0g0p1V1f98h36K6Pew27+fjA1/rA55HpEySTazuX", - "W7jaAIi6r83KMkpPm1c30hGfBISl1+Z4T6ILZ9TbCpUKk6F0rvuumVjL1BM13i2RLoJ3ChAkiTO3JOtG", - "dIxj+Zz7ay3NPGRuYFKRKr+HWmG0/u9j29OTY38TpJepJipCyE219TsMPWRjJNoiH7OF4MqGB0dceIpC", - "mfyyJSZUNQzfQ0TKOJsLnrn5MrgIkAozZGP/dwDIWW7EldSFzZaxT22EOvMaz/iVGDVPKJxErJTpc/L5", - "21Eozomn7EhtdQbO8jlTZcHaNkShwrVTWU3+EY6V7FhWw222Un3SxtCJSEu0nSBSaR96/Z5fUSNTyxtd", - "j06O13Ig0hYM2YtJmdy9aW9gMFbk69V8G7eJ3McyraBrrK3JyXh2enLckuDVb6Dii+YH9ZnhC29RqS8j", - "7Kf32Uq8pgoOW4vCOWHgX2ueVeMuNZSrc+p7qtjEilDQvNeLH2SrOy0oiG+kKm68sxd7//7t4FJmmTBB", - "7qFlMh6CVPj6BCv+29shI8mRkmfA+CAVVweXCzsbh5gHQDOuSnJA0Cuet0FoLMRCm2U8UK2qty0ffxuz", - "U9pi4mEG41Rgd7bIYaOsSD+xRF7b7keB3C6QcbNGWi9GgBIPKZCbj2V3eQzzXBHH9UVEcdxkdrHOcNlE", - "gT/N67QgEpmSuS+Q4pCNlVYiiAtv6F+jludsvBCLpCKWkpnRRR5aeuMet2wuobJckhdWuDE7wH7aLL1v", - "BgUPvfvx7YsD+jAAJ3p4TJVZVrJnrfyULdNZGtzfvhke+vj3VFIVdgGjwgKtM0VCiZnHWi9waUdjlkm1", - "4mACi8VM14sEZAvNkz6Us2yk1oVYjKZGiNHlZH2jXxshGB1Z2BKp2A/yO+a9kKrJUGByfZYKI68Cd4PP", - "Y4B+9C74IXtTOO3DE8veisXgRE01S4tFPmQvrC3QfM++xnHIU0r+IobsOLjnhIzpRiQZlws0dySggFjU", - "vjizCzBOk0+Ov6Jn3MwEntrIacez0eUE3xaYdYCjcPy047TYa05DoeLH5tyk+GZhsRy4P005raykfnac", - "qt/gzOICra/ee6Eayb06tQbGBb/c+Sje4X5a9uHFW8KiOxzHw+zCNs3HC8Og+DTDoB9bFJGXerFohsZ4", - "xdurLm73FvyGPf0GfUNsvyIras1a3MmtbTzSD8LivYBZ4UjYNM/KH/OeLXDeXGk1MNZSVA39C3Xb+UIs", - "4M99eBEhp1yAls+XFl+oPNZU1UNA88KicteMRM0b7HQ+ctxe2iY8zVmpZKDtjlY5sMINcJV+qIWuuggT", - "xlraewBJsckr2lINVcfnMAW6YYyZj3x+hbb0DUjpA9yg7UuOlwHu2DdMKEcu45pNdKHSKLUQ2RFZdzHB", - "1yQozBMpnN+cEIxv1q3yzsjZTJjRNgLw7SpX0S6kSMKEqxQ42fjl6Y9H7B1o8vA/QBBH0dmqlC0N5x7m", - "2JnAIqLh2x7P4HEYmkXjaqXwmJ+300yqK31JCnOpWw/Z+6kLzkL4pm7ZuDqTMdurgPFEVPFvEmYfk6Qk", - "XLFUwitDeV/ynRKapv8Z9vRKJk4uhuxtF/pvNH+v1ouu7h3xu8giuqpkiFC7aWMvYtC/PxHKZ7WNqlAK", - "rOlm3c/9LnxzGyVslAHdmW5diq5zpQ6OZnSI/kS3n2UlNHVTrGy1pA4FqM55NMUSZsdqNrVw8H5PYsR7", - "r98DRzphev3ehCeXoNqqdOTbhKtxbGLn3Ii0/Btr9TXqjGEdIWTzJV0upLAvMV7zVkFyvsJIGQca4lis", - "cA7dh+ACEQJDW68NPHfJfPcggdW1LP1K1sstvaQRmNXZlQh2E6YLl+iFoOJL/n3NZwB+qHlkUlAOSJ7M", - "D1LhMPl6tO8F505AKIoVACUBLThQ7D7M0+pMPOQkaYTwuLuX6VmfwbNMnzxC93FW6w9xcR+d0dkd5kcA", - "Wqf3Ygaaib+r+SBgxmdcKutqIdLw2gHjFegCRlDpbbXPTjO+vDZY/bzuStBnNjFCKDvXzvZZksl8okEA", - "kzdYvxrpXALViwVXaShDeSVWjtFX/HTC8IfGsB8ptXIcKlhE95JMJpe2zy7FEp6JLC5UZ8DHP8awhQec", - "mHc4Rql+EN0NQjmjIaVwmj0kXp9i5sVIbGFjqml7qOjpSvkESEFM8wsh5A/JqLLMVqP+vQVyLdi/XoVq", - "L0bwV+P2+0HcdorU3x+yt80B+s+Znk5B+ntvI4RBgYO4LyXFPOTpCSN1KhM24VZ8+/UgOIABY8y1cVW6", - "HbLv5WzOKIBz6+xxrx5w5t+VKRvo1aQPj/tzxjHIYaCnA3/LQ8MTTs8/Dg+CkZ2M7sBgP25QUVpmtJtg", - "f1nFCbJrBzW0KuZphHVZ7iuNbfJ0kLZWm8yrDCm8drNqgV1mRUYSGZrRiR2RDxa53Ejr7VN7Xm5ez3Um", - "IvD90qez/AjI4C1OMJYf3JLzTrastpXCosbptPdZhPm9OH/5faUEcNtsrE/TxVVwhMTTYuNfP473YTmc", - "KT3Q+fP65MgPmILig9ugf407176KG9OGpdLiP3nZ9Upyml2fLXXBFgVVaU9xCsElaAwLAYdPNsbDHze7", - "vnRCsjSvS+rd0OysqiCinQsSeHpBGt/x4IdjcXWudWa9RkTGngYtkmoHiHTk/VQb8hPQD3CgiBlAfkFZ", - "rw9PUVhD9j7cwzNpXTzYyqkqsU/uc8iCxJUwS3iY8fYomgk8WydZEdNgVejIq8khcYRiYRFBpYAOZO00", - "IsPSgj55VmDhhSJ3sLTPpGNWLvIs+v7ii6Cv8AvJVSXicmp0jiDmcjYX1oU4d79tqDaNT1ReuGEqbQ7B", - "TW914au4wu3S0MPivFhwhZFgSWFKN3nALUyH6knrLLLlsbfMcs+qE27JJSU64hZGBWe6OikD1e5u0EEU", - "xW2kk193rOyE6LdB7/OSVTbw05hI4Wydw1WQLpzxpVg24R7OGNGvmj0gSDkr3BHLQMO9FvDfMhsHz7zn", - "hPW1MHTWZ+X1p8+C9uDvZftD9hNV6Rj7GY37pbtEhVkC37HChWqTR8g28ZUl8Pjn8EhK7+7BlxYWPp2S", - "QzgozBV4e/6uE+Oe+3in7lf12/0+G9sKimF6uKDA0BNPg/hH7jgRsOUUlKAhxjguzx9aqK1FE/arYkkm", - "uCHW5JpPmRYzXmglHYRERizGfHplVgbSBvbp6d6VMICzz4URz7EKSqavbd31H01g6MPBq1tWl6YNb8J+", - "eV2TcbVaCsDN9gZY3K6QXmGvEop12nidfxcwZ9QtwOlIxLcWVesaEeJ9vFB6VYid8YVgY48m4zJQBxMF", - "qiVD20xs32d5Vti6oaRC9Ot3y7phIIjBpqf/NN/5iFeFORzxoyb3x9DkalS5G2m81uaaU+Y4PY3nX+GL", - "TtOsfdRXLcfOSsJbzJJRwaIjRkzGSwhWqIwiDmkHMAaIOPJcGNFHRYceB7gKXSvjIWhPyR5FCXH2wMU6", - "BJeDbSuKJg+EQuR8Lnb/zWlCv+rDRuhWQTrQaKDhc4q9JJyrjEBoVkXugCpeMYzqXROha5ftTOnvz9+c", - "1tlwFxRZ67UbmkD3AzQA+e0LXO8W98cGJJPIPQERS/24PGoGo9cx731NIxiy7zmpytMpUPZemKTjS8uk", - "AkXjSuzHYJ+tuHVrSqwLtt32+NgrDl6mttAjPJyEVyPyCYf2Ysjeq8qOeLYKygbZnBxirK9NQPRwKURu", - "mdMpXz6xbCLm/Epqc8TkdroiAOS948+7D+QtL0F+4u6O+/75sanP/RAUew8qrL9oxq2iTFphE8vS6ahJ", - "wmfo6c8JE6DaMq/MVBrrAqiY+Ri3b84tk64EplKPXgAiyv5MTuPrkVTWcZUI75yc4PUNwITyEzy+x+II", - "XpDgMNLGiFOa3deHf25iILcktmsDm42185qRyccV2lLgngnHEG3hE6BO2HhfGR/fOOjWjZsD+lLYrAZ6", - "g9sH+AJgIO5EMBvBY3Rz3Lxy80OitbB74YT3vj788353ig0BWUEnFK9CvNkuUtPn18OH3IlPmhgcaEtG", - "gndj7zdlvbcZeYD7tEhr5+nj2xqjX1qcy+NoIwK94EjVwcf4oLQmey+5AxDmCjD7wGdsPUilxWStcEV7", - "HusCeIAyRLf72DeQUdxJX3648gy6MhN8nK1CanzVtE7kG6I8y72EhoQN5eaVnt46H4X9p3wjxlU/4D8F", - "eeTBVvd7cRMsZQmB9YeGsliMphmfWTof2KLtfp9hzeEIm56iX8ITDtpiuqaZWLn/Fc41FThFkIx+JVcO", - "ul4j76jsUyamrtfv4bMZTBWTY/p3anKPBRnceE74+tSS6+bcv5ljG/+iVxkVXqsw31TPg2kcAAIuR5di", - "2WT20ykl6oGfYX3QNtixUEYg1IptqSV0rHT8UcVihL1sLQj76Sqlv8PMqcjS5UJ4wsqF91sI4657Qtys", - "r+K/WKLxiYeXtf1ox3JNwVmNkJbrkP77NpBW0PWmB6BbkJReTG8XXRii91au4F6Kl8+x0C4kNtieq7st", - "ZO+lfx5+UT7L3sI9Jzwye9ytpnHhluXc4P2GE6v3xiGYSnCvpduxZ/EXqoSSU6W7mCEAI2Px6RSvXNQb", - "NgGvmtDA98254Qvh02G98hdireLv1LOWuAomFO1iPv9cc2QBkvICeMa2y8c6w4JQA8Nn3bofGz5b7b3Q", - "V6Jb77f6Sqz2Rn9gYBPbOp9Cwx/EstKXnsu3dTzDVtVuwo3IQL61q3AvsWG1dybE1jveGTTyKFyJQViP", - "gAneSWsYVpPDlfOt7TdBHiExVbcybk3tbGsrDwv5uSVJ0yiQ/aZlgpyAsOW4PU2Ruo1UbgR34lgaNLsu", - "byc8F415lqKmkQboDBqyPZ2g7zeuss8wRuo/vvlmv64b/8c336ASV8lOdzj4j59//ar/9cd/ay5y5eYN", - "wcQTqzPgNuUkoCGMkODSVwY5GP77dpdHGKlxMwvr9OInMXn78vRYTDEAWasdN5O8BCtTStwIEvP97LPz", - "/fzrs6+ad+BSqtW+e/Ao8P9L0ny/sQdyua2cqrIqTGPe+0jOgTbnSbNC7bTeyg0IIDxfhhzxaxsd3RBp", - "JL/CMG0/zLaDeBvWuMMZFCYb+V3Ev9u1n4VU3gf6acMDWnUxNZjbJg3bYkN2zR0nD7tSn3XX063g7Mct", - "q6FBmpZxLDLhxCl389sxky10HKg3xWHuk3pp4jGZ/u1m3+Tje7JWkaYsKhItIWFFfdKLrCV73UFseoBX", - "ryF7keVzroqFMDJh2rD5Mp8LNWQ/zUW09fRrz53ro0nrR0tXeSwf/PJi8PfDwZ8HP/+Pf+tWA/mYrngd", - "LXP17Zrj+2u7Uhuuz9SuLAHdUu0aU5mMDHdiO0jfmkFrAPz9L+Ddjfm5FFjn5BRfHlPhRIIBFvuNg17L", - "1M23j4bNNs6/cWtXtbyHudSCatJyoY0XWbrZNsbHCrjgV+96a/m2jqHJao6imBHJTwQus8H6RynznWag", - "YzEOodveb9xhedeYfuuw6Uw25lDyZaIwNK0s+LE6t2B2BMo1gnYI5rKIYel2obWb/4VseOiXAH3iYzTc", - "amENEw6UrJUfENlXhul3a0nFnh4e1tKKfdO4sLvc5GEJO13kmxlxyBeLXj96yv5x02fLn6vX5pxLY+PZ", - "ubnRxWzujccwiRnGQb2F65S/nzHuWCa4dewZy7X0jvBxpqtTrgYZxhCkZ1VZ/Gx9NRt/pLOs4TCca4MD", - "Mbn2DNAe/534BTY8KbCQR8BmPOFrvqSFoLlVcEw2nUkluPdAznXmH1yQb+NoaIizo1yYkRUzxDQiB5GP", - "kMhGC8p8KGdK1+vC1zIzVZrXlvTNjnQZC1XjvNZO8IRmsU4NW+lzbZ11S9Fhu6koTglxi+aVC8PCfvnw", - "T2QT7RNkb2l67GltrttT+bXqDtHU3dXovAJ4k2nzFdlLSrf8e0uku+Lp3zF/Ltw1KX/uQSWVLrStwCZT", - "Dn7EJwaMEIDfn8CN5EmfPfFJa5+QBeeJ9+14wq64kfhaQ+aZRZ6JI3bR49dcOvRxGs6003tP5s7l9ujg", - "QFCbYaIXT/af+4ygrNLcSZeJvf3nF73mbG404+02iHK3XvkemHH6C0w82YBRd0o/2RoxsoZR95uCMEx6", - "3ZpDsfIxO6yPzsPJ7VHRx/3ex5gqrSmNHYWW4nzLqMLqwhreWzABWzswHzTUEdq9p8Xr9xyfdEfycz5p", - "TaXXjFT+2efHPNM8fVtkTuacHOFWvZHjA1FDQidSK8o2zGlWIEh6/QSPA44Z76Je0CWa8zVlqIAfASK+", - "vPtT8CN5F9yDuV6IAwrkLB/07MFFcXj4VQL98V9i5eL0YvB3ss8MR4Off33af/bNN81Wml9kPsJ3r7Up", - "/l3mjJtkHlJ6c6m8d1Whcg7lP8qkl+Ws9zx/YN8cQjrf52SoDjklwA95Kqwb/tNqtV9N1DKRipvl1uty", - "nK4PCG06+ooWdriLSaSCCE1gX8tMQI6F9SOWdpRKs5k2UA9DH7Ro+mtWmBY6xZIuDcjIrQObpZxKH+YN", - "7WrpblLuxAB7N5nXGuUnLIssoRPpfNbCPrvopeb6xgzg/y96TBt20RuY64EZwP9f9Jpjiptx/TtuRS0x", - "FRwgedSt70RnC2q4e631g7Dj0WTpRAM9n/mQZPx5yA7ZtDINKWyHaOQQWc7xfloZrB/woHKGftPb0InC", - "zlsSYb0uq7qSI0wZj7w7+nF0mBJpdzy87VnGoW57qLthSfMTis8TBdnuK0aElx9evTh/1ev3fvpwgv97", - "/OrNK/zHh1fvXrx91TnFaKvi/QNUd1nz2mw+3+PmEiex1HvoHvxvRPCvIu2B/Hkod3SZkoTHpEY8Y47f", - "aKUXGK/iwQQvnhK6d+UhH64xGL7JqV6bBQo7reJZoy4MU5mITF+zPXoNpSnRM6l3sx2378O4z4yYcZOi", - "iyg6k2qWF5NMYq466cBZKMuEGZQf/Qagt+37s3N2EGd/4H8KmdZiWqvgXojlizAVlRWCjVfmEu0q19II", - "Zuc8F1gRTqax7qr3rPP5Sqrhy9LGDQ7JYBJfpP6JDWm6g/fMhdpSoyYW3d3sHVorRd0P8fijZA7TVDMx", - "Cmro5nAb6vYy9CLdeRUohuDvBPAMemwC5n26doB2Rj0iuDL2q3NIUb0vBs906YsNq33h+Lp2P45tIwSK", - "kPE1HbcAoLaVerBl/0zPuvV+o2ehbyUKh5xhtkA4KdujY0ATHHya7wrlB7FsgkGv0SMrnMtE2h0cPd2f", - "UbcAGBwTRxBj3PGQ38gr8TcprldOugTT+bwDpPVD94FFFVBbl/mWuhxXeqxCk0rGIn6dgEH1fKpQtwoq", - "ZqvfCd6H0GsL0J3hrcOqRqx3AVUGMQZIoc6jTLNtRcB8HbeTNBOrvYH7SzXrtk0ezhvqU9+kANAEs1kX", - "SN5atg4jPMl2A0KtAxQwR8X805shQJhoLU26753qxci7duEOdQJ0rBfe4+wNdqlBpIwOHVkCQHuDHVZ4", - "QQ0UJIfoDgha18EkeZfeSV7vpXmn2Wten3SZ46JD73excQuMHfaxhNW0l45PRjoXqhOocz55j20jiNWK", - "/NuA+PYr2k61KPJOhaYr+Zi64XtTZYD+WorYXbPv3ld5wFUB/7G/S7fKtnTs2MSEdu1aZT279W3gorsB", - "KNl5x36r2NO1WwNF7tC1mS3uAKDkJTt0WqHVHXrWiGOXaa7y2V36JvnufdYFxK0O9DYQmhXp3TtH/Xn3", - "rg26ckcgLRrVbr3X9djd+n8Q99P9FuyjRXnu2Lsmu7oiXJPc68rdV+67u3Sr3Fm6d1u97XTs2Xjt2rHv", - "LYdutSvcon/VyrFb90arS0cQjTrFbavzUHlgeOJCU3ODWdZg5bhpg5FXKnpzkFqF5L7Drjlf4kNKg5dP", - "1GnWJ8MyPVvNq8pzCDEn15VNMXYrDyl6Fl934dG/2bAcigw0POnKBT3WlTOq1hPs+iLT4nRRHbrJxvyW", - "gz71udxCFxySu9ybUyiAEwatxmklJrzVV3RHB9G2Z4x3lRcMmkKfav5xMuS+PcVC9bkThqHDxrBeqf6Z", - "930Ifz/ddritj5Urp9nJ8aHLA3N1hbSLIvVLbUR3PZ1a4RpdFE+NvpLWF+PEZvWtK8mxclxU4XDFl6vP", - "FoJbDFOupgHFxuR6gtkUzSX+QU47vHBzbaQjRys/frC3+yMiACHYGSJHpcJ6v51qgTQ/8JUb0nhsurDi", - "1AfhVT3j62fTNTowxN7cPiqwDULnaMC1IKzdsPAenVwxKumO7q2ppLDymsfSNw/t1Apz3smp9e6env5B", - "t3TrlBhQ71Z2sfmNdxt6ll6zAcOY07dC066QdkLX20d1pMK60bYQrUoWg+BssC24o9+zJtkGmCoEdYa5", - "siVxgH5lFU075K0fr2ZGWHtKJWp2c6n7ae7Dn//2ll0qTG420YVj0tkgjyGfBA7AKOfAkL3T1If+hrYi", - "m/Z9UgRpmQDNMRHof1Yt3LWmvk1l5oTZnNZKrM9DUnE6IxNfo5wrrIxwnUnrav7NfmVGTAsrbJkCC3MP", - "XOsiS6nyXhUTbEyBONNE9eRP7jPm3yypt18klqrbXhI2rrTpGN9fdg68qu/SX4VC/ev9D7Fm9Pom68ut", - "zOdEpaBiCxs8+jqsSF82ruUUgt98gM7tCLctQue4PTIn8vtnXx/uHqdz3BqfM2Qn01KZLayw1VydZVVJ", - "6hKEmxHIBbwq6z1Tvj3sf3XYf/ZN/+nhz81TxK31T1jbzmvq8ZsQ26cIAccnlKQxRz3TplTYDjD7Dzoy", - "UBKlZoFhxErGjaNf20fHpqWPIBVHLNcfvJqcZkLZgupd8pTnFHGrxHWoTFW6ICNO4F7OBU+nRYZFL8ov", - "WQt6tgZGHbcGREW0+erZYbfwqHWP7J3TFIDumVYdmKM3+HowlV22c0bKCIW80FcK9X4/FXjre0QhyOmI", - "I4F1cyrMuHWjwsZea/NRXjOyeJsTytHUVuYTsv10dmYMt55busijQtpcMR4SN6JlANuwsiJKmOsTyxyf", - "9GupnrRqnGVhsvZgvB8/vGkDjZRK6aF0LraXvfF3FkSK2jmuHNDPndD2jVxI1y1d0qorNQGwzW7w4VYf", - "Dz0kyyC0L3t3NCQ1EFyDjr1z1Eu/so6uG7azIKtt1b2tds2jebd1vNtoSuBNjInc9Sqp1TDHIhwosJ4Q", - "AYUfQxfMv3mhQg62LKsW+seehMCoPbEnHmue4E+2zjVQ2TKFsgjHXqignXFs7ZOiNPnFk1v8ty3ZG+px", - "BzsmlKYSaD60CC2DVPPM6bLGMUx3tbIYfPMBJqEC9ET6lKYAsTHFC5H61tSvwHHxmS9UaBuy10iA1b2U", - "ls15ngtlmVao5VfOiKv0QpEMh19CgWlcKqwxybQVKSWgxhOogJauAthnRa6m0L1Qc54ypXGOFCbVmOft", - "lowbAk22evZGwJF/NhPNSrqZ21lJtsQn+1bRxEC1vJaWgpJX7CZVPZRpww771JYbWHmek0F6cwjkBqNH", - "zJuy2Gb9gOTnOd7BLGyOt750N4Y0jx9CcAC6XS4mOsPBcaAhewX3MxiC2Tne2CaC8UrbSor/yZLdpNpp", - "nV2oPSsE+6+nT3EtywVIJp9qAuo7+jg/G8NWLnofMHbrogeREfh0Tf986UxG/3qR+U+vv7noDS8o5oTY", - "n7QUnpzgBHlmNcwy0YtJuFT6tDME73+4EHCBf+Fo/+OcTxDsj5bmTbwQ2EleqMQV0aJWBxuql3hYC6kK", - "W4MOma0R8AuWSScMz7yxHm8CMFWeJAJzr2NubMYzyS1muvQQBhc9aKtAa8uwyIDTK+Ot1APYgggrhIlY", - "0UyJOhHWguy6txBUHqs52KWCS47CGvrr92ZuZvVo5n80FOciSNzMioVYjSLfSg3cjozW9Vjk5mUU9aL0", - "KEyhK8uNvJKZmImWOxG3oBg2RI6sguQ+nyy0BlCQkQKutuECuraY6KK9FpiBGx1Satu5yGLedLyoFqrx", - "dSK5bhJx2mDl/PJVco9XA0n2PUTvmk+DSNW0gO12PaGu2tGr4Tjjmf36cfXAXqkrabRC43YML4a5Ym5U", - "bapbP+w1YP5agO9uMb3tB9geukvHuZUM7xS3y6tEFw8srmPYa5OmjW8Or+L62x4cmktbihvpRs2h5n6p", - "DJpgsGszBArjHU2+/bo5fqpSEouaskkBBVGH7WG8XYGB4tUK7GP76YE7we2Y6BnWJyHsVfH9toK99SOj", - "ciY1ptY7f/XhbW8z3GoUl2/+w8mbN71+7+Tdea/f+/7H0+3BW37sDUj8Ae1kt5UmFssvs9Pz/x5MKD62", - "dRsSnxNr5aIlrpkTZiEpIW5WLJTdlhKi3wMVegssaLJjbgmE2qeJbtixs5xfq+qGdSrM1iC6wY1lRcRS", - "OWMxcm65XQq+8K0ZZ7kVRaoHcfV7p+f/vb/KWMnsiIIoRqRcCZJILeKy+dDAPUwCpq4cnC9wUFkEvlqv", - "ZiTZ4UjXRoJmtx9mnR38vHaut+DnJxXPIHou4swCtE300FiM+P1ZPKyT48216Ju6g8eTMANuge5FymTp", - "4NIgZKPVsShk2syI0UDZaOY8Dw475c02zNx328EnqJXUHHeF3bUiTqWgSWFJyrZzpbwY5UnD+l5ZJxcY", - "pvry9EdWoONULkwilIO7erkMhalxtojRV0F8BsNH2CswpEI/kXbRUcCyt2gL9C5nHCrkhwL9NPsYA94i", - "wRvfgk7LM3W1wGJvZO/RskXaLIvaDzaV6nZC55g7zpxG1xexInzLivQSS8Stq0/c8U6KRVodZbjVlBLh", - "/rx1zXfSF2E6Pi+bBXDrK/QeQW1IUiZywgbBgWjYMR1eXIoRvAzi30V3OnsVAouZEbkRVihcUThBn6JF", - "m7ViuHc9zeiyVSILrKJRBRXNDplv6lNai7YHUmjM0NeJNURGSsAl2DCg40WvjWRh/g1SgJwt6OdgEMQt", - "SOaFuqwXF8CMOTEPT0cipjB1PP+72SEmOl16kw6CDLWsaAOUp+7VyP2mIu1UnqotLUJZBy3a9tBOkV5J", - "q83yyJc+BI+PMLpPgk4OFwbr2aFYXanzVfPVy6iCMWWHs5ViXUN2ggeKpmD0uoQBC0UDJpgBFrHJ4kMY", - "PQxLywKPIXNSpRgFVlkvK2P3Y53+Sh3vstx5pTp0rZZ8rC9cK5McI9jLmNRGpAaUalAM6kkcArVTNWPE", - "zI5VofDkCJe7ZL2oKDvb+XVrNm7ySxWmOesNWEztvJtGVDqGhl5t+tBW0xKpeuufbfSirfxeS0TYWX9b", - "cWO99WSb8kdX59m052W0zQcx2z1dd5t/zPf4vXQInnl7yIb8tS0eEz/B550AdXSCJVjwAq7zQSamIAiM", - "Endyi90BZqPnYdiFftjYbUd2m0chEw96S7mCOmI0SqN6UYNdnSIzx0c3m9+mvtdG/qIVpszHsRhf6EK5", - "ISNv6Cvhv1uG76d9psSM177DOTQLcZrBluy9f4MZJx3Gh8eyhuGLvHnwuzj+xrIK3e3726iCO+8zWdZ+", - "qA+1O1HsDLKzN+5aQYwduZZMU6G2JBdE+JVnPt9pqy+ib9cybQhGOhVmIdGN1N5u/jOji7zZBoc/+YxZ", - "hv21ZsjYNTVbQ6WKb7/+en+3whT6WgnTPFf8CR95wnx/bJlvlzRelFEqL/eWXqTp8dNX9rtlvvwNadWq", - "FVZ2U8NPeWFFNdUnasE2FwnQfhqfEXZ8h6g+5mNplaZniGpS1cPDza/1q7ftyuCNG+K4ca/tT+B6e58l", - "EGKRFrQMAPRhc1pUIFx5JbabcCO1e3gs9s2WHXyOWx3hcQfuGDE3NXwhmj2EP5S6bWgERzzNgWKvhDEy", - "FTZcm/wO7FfP/NnhNntwo3U03N3W7Jp4VVqJm/PhbU4H7xhZyfxK5a7LMD4mVOrzhe9Zp/O+j/oDgQrX", - "l74v17BP90ZwrodeC8yxilW2VCjmGWHaeysVUbGo7hQJuOA3gRZP1BnRXvvzaTl09fnQk+yWg914lgt+", - "g6kf5S/iRL39rn0GGHRrfcLKt991RKbVzP1PW3zeYXUvilTq7XT50pdJ5dCcqh9g4MaVTIUesg9Eg7Zq", - "HQAViV8JdBjBXj7mBfDltMiseOG/JpfCVSsA7wEQzGnIrHCWTbSbV8rd7nts8QVKayGH0tKMBlhytGOV", - "0DOn87uyBm0SAXC27+TJYiFSyR3YRoCwymASwxMxLTJm54UDMvMZHRcYeYAGT6yim2hjCvTGwaUijjQ/", - "Vt0hxJdI/tPUfYGx8nup+1KmdlRXItO5uIXbpvBdWXw0cprxWiZrtpKWcl0biObSjRXS6slBsfrcv1pf", - "HAYLrbTTSibRtY7RU0s5U54YbW0sToxOH3paIcohA+cxwDgGmYQHOPLg5NgHiBQ+ph2M0t5a6gWEtFQG", - "g+xua+G0OzwqwxqDPfnnjWfYlgNgJSsqhQhfSyMGmbgSGX2lTJ6l55rPmOpPLko35EYhq6pWK6sfshdm", - "Ip3hJiQ39Zq3xX4+U2qZF9QIxlMCRr61IZHr9vSt/aa8qzhjYQYwNCO0YalO0JVMpMGxeuztg//uE5oe", - "rHw5RrgV98Y+W8/a2uhY3NWI/KWYYsvT/M+z9++iJbbpqDJp/RZvTmSLR0Rw1o6uXv+z6VDoTGHv72oM", - "NoVKmr3Az4QLCOclc3xXoWcgrC4K7tsRCLqpSx+YD9pHJheyJX7YNShQPyp5w2IGC7rsAGtaKShRbpTX", - "FKELu65Ij06x+5/KFF4p/M/drqIlPMKXzCtoPC0XSkxr0hZSxbNskGCN/ZAxwRt1KptZg4/n60FS8LwL", - "ZWhqxeKVLjt291jo+3LgHXE3bqQv0Ab0alAHGBH1NcVLLQpfZ0eVL7bo5VYmh+Yx+TJbSFRbJiLBGz3c", - "dESWsYmYSx9vRAYUWywWpeAM3Ym91zeQzBVwhWFGWiDoRBfoUsD9E5iXmNKyifAvuJgLhk25dWjB4iGg", - "ixoYwdPnmK4bi91rJTw0pR2+/M0hbkQIxTJtUd+65kvL/CMxxmeA6PDRykZg4X3pnjM+CQ24bwOdUu6C", - "rRJpvhKQrbQrY3S4Zb8Io4cbBX1zFaXb6S9eRcm4dWuqFTvWguYHq3aVk2o4m11nvObiiuhI62jkACs1", - "bXe2rd+tKh1Ynp3Rl8I2VpJqdPpqPqdbpZwIfsrlPELKjUrqCZAnNyJluNjhhaqxelMIthdwbBGSjRyk", - "oabg/pCBtALpE4J8L5QP2ABGDmNRnJhiOtg+KuPVdort4be/HMK++IwY+8MLVY3+FzdIjrBDKOuvtUkH", - "FiMY0DXAe9LHlUvlDB9AKxrQXijgFIpTsn3UcOjnHPiOJd2U5kZyFuay4ejaQp4a66wDKuK+gojzyutc", - "WxdLnLcUS9CQK14lYjMungozSOYcNDZhYAzNpPonaWcYz/4cuKzjl4I0X9R2UKnEPQP3VyySWyIBOxyy", - "9/DgT4LINu0A27MyEwoqoFf36UKVzRA39mmros3jcPi0EeuDN1rXGvNUdpZK0ELJ27OolH2Sgsmbihhv", - "LkXcvpgTdaUpPxqkMCzMrqsJbjpBxdeFS/RCjLy3RqP+LeOYo5bH+s4hub4O3KZ6dKvrvFUOLWGMNrG0", - "+S1WRJ5aTdqwM4WlwiszMQjV+r1nV6h1YalKkjOCo2WWW5ZrJ5STHEwOEFiVYLCl9+TzLopFg7KEleYg", - "UbktJv7hxSsWnCmtBrxwGn9yLBVJxg0pVvgWiEnsdA7KFuhPhUPZS629Ql5e9SBCjlwjEuAnVBUN97HX", - "b5rFdv/8+i7HJW4+9Mtb5qvCnWzv0yQSgSXQCfTpUkSXpadQ58pnt8CrpRVGQihcVO63B/BUKvSVltzt", - "7wIgG0eoc/9azU739NmfdstOF+H0/b607/m5r6W+w1Z3u9uW4Cs321sWbq/vzOq7Cf9XIZgRU2FQEYVH", - "E0C9S1KQpWXihieOEqUYMZPW+Xsa+K1NBPA/oMQrnsk0ZGqw0TbDKvaE4FyJLzJY4y3tcActDwP+2YvG", - "gc2H8kIp7XCeu/qIQ++SM03EnF9JjZGg+AQUn4n+8fblKYMphUdRItaf90Lty4VOReYLaeZGO53obCj1", - "Qa35wbPDZ98Mnj4dPPvmgGwSBwDT/t/w333SqXA0WhpbWVvFllUOfC0mC57MpRKZ4EZBPdiZdPNiAqPD", - "j0l+8H+nMnGpmA5gHF4CBGXifC6s8MvlRrAicm0K4KTiQjFz1WTpzXdNhrOSwTb7oSVa0R0ImPv3UrU0", - "SwUVcpJXor2RTMWCBEV7G50L9ZM2WdrexAiegm7W3iJuiM9Q3tby40YUfW18foldH14b4zvehjslykip", - "EiM43s2bHkTFYiIwwSjCq7ruBJPJCs1uD9LZmNuFhoEMLzExxtRwqgpcsW9t5gRx7TTYZvqP3G934mcL", - "35dNNTzm2pLc8ecmknsQWv+A3FYYkbaOuxOpmwgPBxxeKNK7zsicjtl1wk1SG8oeAXMKPsgw10Yar/Pa", - "buKpyqBXY4Ibdc440W1qyhpWhORILWrqLaFiItztOrvPRVRdX301m/H4VpcuOrBuZ7F2v/vYJ0rrHr+4", - "ytI+rgX/v6rzG2+kC9iISA/Y1WfaMPAiLu3y5KkKb1mIjpVOZIWv+xx/DPVZwtm0WJ7h55gOpTZCi3/X", - "TIy6Jq9amfEuDA+LAN+Ru1O2nfvg6FuSy5R5Zcg1rMIlnlh/UMHXi0+eh2VH1lLqWMRYmrbjWqpUX995", - "R8LSCdw9bM4KjZfTjCdYQ8QKBgXi2kz1tnOSyzrh4052TqFVjrc17QgBbpy0kU68zGQ+0dykt7t9brbp", - "1aL5QgnYMOD2+0OzeesjyhQK5PDcoucfoU/oJeHF6Umv37sSxtJ0DodPh4dBheS57B31vhoeDr/yBVBx", - "IQchE+TBNOOz4C6YNPgLvhVmJjDFF7YkNiFupHWUnlDYPivylDvBVoA25JK8kpzZIhcGQ5bSPqkSWGS/", - "UE5muHOx9bG4QhxjFz182gWt4aKH2fszqQTqARPUT2LiLarVDjMLSU9RDYAzJA+yFD1GXTIPo7zG9dNR", - "COu+0+mSDGioMMdXPa8YQf1r+GajKF5Re8NurrChsCTaQ6fZArfVV23+x0VvMLiU2l5SLqLBIJUWhMVg", - "lhcXvZ/3b5+GhybUjFZlOy+SQr5ZHOfZ4WGDazPOn86bbllxaf6wVyvIf+z3vj48bKPwOOLBdzzQJGUw", - "/NjvfdOlH5bMUTzzvbDm/WLBwQOi9yPhZZxixguVzP0hwOT9nHv93s0gvqkOSh+K0s8BAJf4jUmSpdhO", - "N4UVppQfcSICJp0baWO+5dJJMEYMTnj8Geuu9y/UVoJiu9PThdqVoF4K47hULOwCW3DFZ3TBvvT+MWpq", - "eChp7PGcxdr+Z8IB97D9C4XJlwdGkO0yQKR1RPgBUVFOvjw+PQgJ5LXax2v+BN7VRXqh0OgR9nIr7Z+G", - "Y7w9+Xc3Q3Y5/CH7IaSA8z/hY8GF2vOJxvyrzEutL6Wwfh8veuTRe8Wzwj/sVDJ509fhhToTgoXrGGKy", - "KGcynGk9y0RE7APSlWIu5PCdtlRQojVY/3fcyuRF4ebvr4T53rn8FSbnSMMeNE4YVRVobH/MZ4anwsZe", - "Xuy+5Tcvo1+RPfW13SCpb793qvMit5A45Fqkr7X50YAq8Y9eWJuf3TDRi97PH++L8wVc+WKZ3yrawVru", - "wgOLHByoBiIQNTFDbZteU7AplSQ3bKGNYLEb+0XmjJtkLq/8hMSNMzxB54YFK1QqzIU6mOuFOCDmclAO", - "eXBRHB5+lQCR4L+gyARGTUHCCJVTNp+yOXn7gXEOT1BW3HqBBC8UXBeCb6/fF2B9YQ/R+yJD6pKGGWCx", - "CxHECdCsMJZ80IB6pgXyPoSCbJN4CqOd8ZMh9x7KZed1qhy1OnqYoJEUKJhldVDKAI5ucBfqVbk6f1tF", - "1G7gMtbJLGvI7x0kBsw5iAgQNTyVSli7k2pFJ13OaSNnpcADbtwBoNcgWMFK5rrpThDHoCHfBljdCPxp", - "Uw6DuJGE2sGMHPDlM1MzklB1QjV6asD2u1P0gKt0EPjD3am730DarCtl9y+UFS4SXTkCkZ9Ut7h+RNy/", - "UJ/w+rFKIy9U+iHy4C+YWvoN4pC2OO4kPqjxdPlbIKUt1MP2wKdO5na/KiXjEjsTl3frOZiEa0IzEb0K", - "mUwVw9wNIqXks3oaPYMY+WFbCikBE1Im4PIfklL7X70ggimARlw+WmVLL74gCjokKblJsgJC9Rho0Jgf", - "VmkfWIa2XxZx17KEK3KXygS/Eih7QtCldTq3wZ+Jsk8L2PqYKj4cDZOxLAl5MtKifP5sfNOTiCeFxcAa", - "EErJnEskqlRQDjUQlKVLIqbHorJJMNqlWKLBJWxXmVw850uA4p3cmdGFSgfOyJzB7UMllMUFS8fALK9k", - "WvDMg2ki5O/wLuFP50Vwgb/tTWKjE+76SDEB3y31WQQZEuj+htTWSAgMKaaRAKo43U6IIVqhTocJ1PMd", - "IbpUqbF+slj0F90bH+hAywHueo5vCfGJiiLdf9YjPJPo+A1nSGSJex7m2OL0uOshklX1AMRJ+zl+EDx9", - "WbHANm3nfZ0nDeKVfDrOFQNAaMP8kCgL1yjvztsPiyY32egC0mCMvuV+o427fcPrRvYHIp5mS/5tCQit", - "96EGpdPlJv12eOJP9LAQXIfv40Cp7mTrOcbEIA90hGuJR7qf3r2MX6nO1kSpODUG1VMnMpNuGY0+vxmU", - "+F6mPhW7vq5XEt0JD8CNf10YrgaDCEuWGUyfE5j6pHBOq350xciWpRmBw7yMIy96DLhTVEcSo9BxvjN5", - "JahAo9evM8GtIKcu+iwt41EJ/sdNny1/rmbFybk0jfer4xCa8EC4G+HflfMAoN+IyMaplEVc6Zg481lb", - "dkIpeIpHKKPc19ltZzN/Fa5WkfchRXRz6d9m6sendtqKuIj72Oa/Cld7zachiHTjSPeiIQG1bdNyY+ng", - "ByKUtdLEd9Nx/TbByj4vsbwNFXFrxxckc0w8VPIqey9HmhthLWQ628KqhV2ZCEZWTalsVHSci2mR6Mmp", - "zM9VKdhzoZrK8PgSVLgOI+ZCkf1gvd5Pn1khLpSbU+2b9Zo9jLvyRWom3XBqhEiFvXQ6H2ozO7iB/6Cb", - "4sHN06f0jzzjUh0QsFRMh3MSGT5Oeq6VNrYai+d9nMJ6LSusT/qT+K3A9E7W2yPpmHTa+Hjoi0g9EL2s", - "1qi6LbnggSK2/JY0FlxdzeqGeHkflFFJNtDK7M75pShzMT6UWruWUvKjP8SNQg3DfQ9ySoFajhTjYif4", - "otXgQbQmu8oJUAzxZz3xmICIlQcUnA/vet46y9rZIGXTZFc+4yRlND7QwB1CFkz45iqKaIVZ11XamsW0", - "VkvN66q1dJZkfpUKXglgaOZkcmnZntLOp1r1ybdKFIuRG5g16Iqb5XPmCrR3LjA8tppAGQNhMblSuRR6", - "+/drZZiLk6YR/E76tQTQPo4Tn2BqxuG9CAP19XIA7/GN9jiKAA0ZWwIzHYeAX7L0DAZG5II79o4NBhRJ", - "e8joQYduDfjvkMBk5eYZklo+EH1W0qzelr969PqNGNtoMqU6QsfDHeP3q1GGhB0t7NWH2T/Qwa1G8d/J", - "2EOh478ZwQhrI+POnY7JJwBp54plRcjw+sfgP5RjZBk9i4HUQ6avesoGqVB8hzhJkYba+8MLdWr0VGbA", - "PJVWYpG7ZcWZK37yD7PeyyM+IFp6y47Ph9bp/ABnRWnLLhQVLCgTyg2ZrwCOWeNoztASXJfpk58a5h1c", - "YlAgJiq4UOM48gjeAUfo/C1my7/kGFs4StJ8jPnDnINJY1dwOgvv7piZBRjkil+JT/FRrWWb06Y07ok2", - "K9syZK+iy8bAu2xUhwB3o+PTC1WZxpRiwzG8PsPofZg4bGV4roS5VGv5hgPDHAf/KoRZAg7whXDCMGkv", - "VAjgnyyZzlJhSI2wIe+IEY57eGV+OBoqiLHhhYqYNo6HMmaptLmXIJxNhHUDMZ1qU3NsIaeXOtaRdcg7", - "o5S76yOVywAgSgv1HTdEQNbH/1XLW47DZWNM+XQYV7h+x5a6YKm+UEo7pgTk23nhWCa4dbid/qqAnnDQ", - "HMO+J/HMYzLF1QQ01onc+oLKcBGSll53jyqIUJ5xH/cILWaeUFAQeywKbhR0djEZGmWCuVDOcGXDleaI", - "ySkYzziV7vdzg9kgzsCo3GRSmAoXZJgcUkynInEhg+GCI83THY7ycSSidILCyPRnNzf+rTc3Oucz7tBN", - "8BSpiaL4NCgeVgCmOcHGpaPGv48pKduBX/iY6kETfcW8pB7D4Kl2NhOg+l4o2lniXJEv1ZlWo/9n4DEv", - "QyP0ivcUYDGCqMXRoUr/gWd4NNKYfZmN/UTHodAtaFysUHAL9U6ia9SC+Bt5FbB0/9ZdosWQjausyfMl", - "S4ypyg20YSKTMznJmj0aYKunuL+NrIJKKHhVE2O/ekc95BG9EJrWa+GdmPAtyPGyQmDpWhgrLsUv5ZKa", - "Mgz8fCdPmJUgMzhyMQoU1+DAdP568CefXq7ukMsWPGf/53/9b2KeViy4cjLBwqqnL85ffs/WXcKb66D6", - "VqOW+IDKDMhNlY1/vSDf/YveUTU84OeP444TIqHSNBtPbF2msQCOjRp+s8UCfvaS2OtFY7aHtRcOqPLC", - "gXDJMKR/pSLHIdvMOllTvh3ie/AzJtGNOdA834laQpmGtO6LW+YaZlolItzzfDnKhrJGVQfWNuIHTyB8", - "cgizx3hw8H65ElVaBTrxyyjTJm10rNuv1Reuo24ICG0shT+kWvjPvvmmOS/NLzIfgeDoZkqoh43Evp7y", - "mwKqVisjeDk18nJqfTcdN8NfrAuCrMrtSKGwuL3jmksgRlD4pJ00QHg+t0PmhUx0H6bc9UZrx4RyRla9", - "4X1n+I89CLWHw03Yigz67yEPJf9xNva+6wenMemEHe9TOtYx7Fs+KkliXKmQT8ftPazCYtE51xcmt6Ba", - "YINrw/NcGFaZTy0jWttx9XtRs2og4w9v4mOxV67EimoltmhKQVHqswyTkQBRJZxozbFnh1//iWqv9UvS", - "gwNMMIKFVEXkEf4AaBaTTLTUyq3v5YarS5l9LuwgPhWWfSkRspE5OT+s4GTEij3QXGKJER8uCaQK+7bf", - "qQjvb+rBuq4xE798Xhr7IxbE/D+16+/wLvffrw//vL0fTDCTydqt+X6cb1Z1unDLbt0nEa5OxMtjoFLK", - "8jm3YuWC/oLux3h5Ke/GaBLzd+a61g/F+df2nl43O/mMVuRzDC5riGLycvehHiPWRfunxnk/esg4un6c", - "P3qvDL9h9WP4bDh955Cd5uV0RJ6pPUiMgJrCsb4+IlLR5OaIDWNFkIfydayPshMyPd1UwITW+Ruy5NFK", - "Gcdw6bSyrV1PjupzdDi5Y2z40CdHo5xyN7+zq0s8NFpiejfq/Hp7v3favQYH73v0kcGZM36Xkw36+IZD", - "fU1q92/7PGGSv4ej9HeczqfoK+kAhY5+kVg6ZCZcU3EhVxhM3vj3k1MWby2V2064xMRiD2XBqoBew3XX", - "Nj/+sTR/l/k201Ws6xUhkrbsdLyVgBITFtVm8/FOYHUsqRp8tpYC+3knJcHv653ewWHXwxpjzRREveoG", - "f4mY6w+ryoYYD4jml3xrjLYu7YDS4R6/57ipXOYXweUEdWqAtb8R8y/UBtRnf7cuZXo6FcYyK2cKk5Nh", - "jmGfmj0M6HXxC5WK6if4Nzd0m4UgRDIeQQoycQUzmQi3CgUJrdmltEJ3sEdfCuH11xKRVJaLflFD9r2c", - "zYWhv2xIgM/sAjPclqYVSCsLiaMZuIYKeOUZ0ElYd8T+J5w2gWBP+8znQoWDhdpQ//Orw8PBN4eH7O13", - "B3YfOnoTcb3jV3024RlXiUip5wGeANv7n0+/qfSlg6t3/Y++/8xCl28OB3+qdVqb5tM+fo09nh0Ovo49", - "Wk6kgi0jBNNi+A7/Kg3ffqt6/cpvNGX8h3WtVvDufNNT750Y5/mKje4PwjxXTJM7MFA0L4UETZ5x1pkH", - "6EpYirsr10Be4TcewDNt6krBb0FK76Z5xj1oQDn4jUlFyHrni/tnQSzw666sgPEJOQCsnd4OiJVJ6/C+", - "YFsx6420WAjX3lIgfZm4VK66AZnKi2ZG6TS+QGyCBdI7BYV63wZ7wEu+9aIJDuyn5Rk/hN//fVwyAU7F", - "uPMFniSuAB/48V3wbgzBCJ5GA0IjP4DIT28+6MYOcDpBNQX4vxWOoBMn3ICqM91Zp0EB0xhr+4WhE5wv", - "qz2B7oA+VpA4GVVKe7dyiPUK6w8XCNpSyv3WibpKUCFs8ws86jPh1plFtSr7AVZ9t3OZ74AD9DLd7iL6", - "gtKIlw/YPsuINqU3FgkmH+1kxEJ7PkIhycOWdDdBTbk3r56oGbW4TqTCutGWevfQRir/aOe5oE/i6lXv", - "LpXu+73bell462M51e1uFg0Qbpve82mzWbeS/uoLZ5cNiX6mHg13I5hg6t2Y/4qjmYk8NStZ7KR36wvO", - "CSsGrxUMbCMfsvbeG/HsShwlB3I6rgxWEr1bdDdKuSefpE0Uc0vU/7vM63nf/DJ/N2TAq7nYVlD0FhTh", - "jU1bSGJXU3Eb5Vyo7aSz3WRcsxBfqBUTcXuuNm/zvTfya/WQO5+LuGVht4IY6uAT9tnIutmDq61K4bvu", - "Tlw+A76fG8x5D+taAjoNBthmUPbbH+5WPLS09j0AQ3nh9/B3zlRW0fXWjOV6NUHeyo3EceNe25+w1QPd", - "RSpD7O6lcsuM8bjsxsIRPyoJFc8aykSUdHvtt6OTt+JqQWqXzNl9py3+TOhIi6ma9X3iQDXbSd/D/Tz4", - "NRzKRzqVTFDOq1WM1HmJkCsGFzSieKuJt6HEk95kR9luNvm6qbY4HSU5w3/hRwnbSniNHtS3MpWtHuNB", - "WaO80XB2hoam1/bVlTeqfLLTXDWCOXHjaLaN1q9tbyxneAnHZTSmBzh7FUqe62nl1u6juXv93lzwFFf9", - "a++/BmdnrwY+od3gvLFe/1uRSu6LGU8ZgMd6ZASO7a0ywv3ae2l4G11t1fQU+vFLRGTc6LVd9hmyAuvu", - "jNNGbnMgwzxxXQzAxxUlkK8Zgz+hP8L7siJ4JthCp4Lt6cTxjFGfPsPCB99+/fX+kFXrkn/79ddt01xQ", - "8eHGaf3jcPAfP//6Vf/rppCZzVFn92ievqVlJmYp/NKFNZrYQD4Hf9ld3PAyPbMH5dY3P4zqmSXya+Hl", - "KyjjK7Vuwu3ArDwRlGnEGwskNw9DZRqbfUZqxfsqhTlXESEGt0usLTdlNHcmbcjWtoF02yXTLuNU1t48", - "Wtlg5OuU9T6bVHyjZx3FISDWb1oCNkkXmDTFV5+dvepKQj4D9oGYGWGtTzaw1fEPgyixRwiTDd58Rmcs", - "z7gSLOPWVYtaYPi3j5gZshfhn0xph+rdnFs2EUJV+xiRa+MsG09l5oQR6RHDqjCN6WL+Ktw7Ws0rnNop", - "reUB3Q+ahtuQRbC2Yy3pAP2uPLErrTscZ7/XWL/+XECYN8D+21sISqSE7s6uDyUtMwKQLPF10bliHNhU", - "JkOeiPgnQBDZFPrEosq6cJg4gMbql0WWK6uB2j0UKSgtS0UmJ8JQ2RWlHbOwTXNhxFEI1LxZQkP4A7mQ", - "HwtrUmLSA4LFGSV4Y4nOl8FfqmreoimryvRYglnuEGpq5NSnSJaQwYSyOf3tLSsog560hIzTwooyQh/D", - "OK8RitGFE8wZPp3KhHFMJ0+/4xKG7FynfElf/HIgjUiiFwtMenCOdSmHJAS/o0iyl1SZF/IgGIPZ6scI", - "7AyTN42ZNv7Dd8ucWwueIuOQm+M048trA0HXTNzkGlbBLRv7GLWhEtce+t6vfpM/7o+PyARboTUQROPK", - "SXBlr4WxTFI2EUprgnWDfdoHqawT8M4yBc32mhs06UkMPw2hebi/J7Hsdb9MgkW5RtY5CSa5itVVA99A", - "buJYkSMA+FlgUitVRVLLeErlOsn3AjNG0klzZgpFBToCUzovS2VJW5bwwVoI0jFbmCsqTRQzJXhUi/kw", - "oAaDl3PPGQ+4QgefYM3hABYAGs9OwSHWcCRMN+fKsz2680b+GpFtIlimrWtigadFKwu8fxtZK/f7dGGB", - "HRnwq5qo8rj2eVN13Z3dg/TOI50f+PINHcqKmIl0hptllUskOhXkYTY1woZiED6FCgaQ8xkHLK/VpvUE", - "dKGAw+qEZ3Nt3dGfnz17RrSEUEGuc7ykABU+yflMPOmzJx4u/NODe0Ks4AmVAH9yoa64kRApbofh4xCo", - "GuvH7O0/ieRTmdLgGji8r0WOaeis4rmda+IzFyoAkupKXwoAtQfNPohpn6qc/D999itzciF04c5E8v+w", - "j/tPGLW2VCaFJ26lVPDc6GI296lxIEnSE8vsUiVzo5UubJjPi9OTYfh34AwxbxMAuWbc/15FOOS1F8Bh", - "XGFf6lT0cWP7OKvEEz/t3USnS59ygk7ACFtkkU3heZRHK63fQigO41M5BfRFLv3qSpgl5uGBoyYXROUB", - "aHMEFjlBJVxS9k6nYvhPG7gfCQjpLNPXKpwOvLOFSn5D9hLzz+DbEzzUoYbkQVOipEQrnx05Wz736YB0", - "JYNVaA2NAQcFpbqDwwMF0x9inyWG2zmm2fLFIUklZ5nWecgYFGGlWljURTimP7pQVAEnzmzIXmD6BB7g", - "43xi90shcovrDhuB4R1G+68NO4HiBY+GT7hKtSrlYBjCiw4ADsrKVYifCQI9zOlC4VoZWpXWF0vZVLCE", - "HB4qbiYvt90XqItcIFSWBlyg0wopt56ELk98Sqv6LsDlL2VP/I32SVBLeHbNl5bK21mvBF6oeJ4c7q0W", - "s0g+KZHsIlyML3pPhuyknnEsNOt7xgI4PSHtSzOufIo0qi9OUpU2F5URgeDIr2ng62x7hoyJZ6j6EAw3", - "1UbMvFbHJ5TC5kJFP6h6rW7Kc6FzoXwZLBHvMSGBmJ9RHvuE4kgXyopMoP7tf5CWFSo+dQ9LxhnmVlcX", - "6UD1tWeLAdqFwkLx7GTqxx/QjqC9jwKeEmGDVufLpNObSb/CMeopo2B/a6UKKSFK4OdDP1Pk1U77uWC2", - "aJpqSNcmbkD+S5ctEdNOOVLN0teeAlyC7oBnyMQAc1FUEZYFFCCGRwWnsI1fjBLX2PJCkXoNdDhkr3gy", - "XwFAu8bphE+crcKC07QeGCy/RAa2kgOvSuCwSi/U1rETDwoAaAUkapY+RxvNHUPUpMOUhRaHH7L3ORae", - "Y1CkLrIpOiScQgWz9JQ4tT8cwqXnYLupzjUcBIhopX2r/oXyWEuL1orwJpTpl5YlmbYiXeMm5R55bqzS", - "iPlPYFd9lD5dLJ5AFWC/88j9Eq5iYUo4HTp+xye2lLAl9uOuBs3hOYsukP5GF/PPcNew+YhnLyLdwshz", - "foXyY6GtY39aQQ37vJHrlMIi0YVyIHRgJy5URVsPhk0vR4LO8vXhnwlBq3zTPveB1MgoSOwfv3rz6vwV", - "W1f1tLEHv8I0Pw7Zu/psfRYfFy88oUhyUiYyJr4L9xUQ7c/pfgUINy+cxXhEPN8lwopwiEtJfyyEB00X", - "ETpZUWqYL8kS/xD3kLWxPlOOkoZ5gPLVnHwmKmL3+kr75/vL+RJXEYj0jVxI15pO5zxw5hWsL2llIpaa", - "0IflwgwC7WUA9l7LxZVTx1zBZzhLr2CtX2I6JtVtIr9WM+kbSfahBo6BMsVn84QGK3wmJjKZLNnp+7Pz", - "BroX646hMN76gdmHNH024YdtxHWQWuUC7y8qqmbjKld828P0vLTu5bHyRoCVLasM+0lU8wPvj0YljdwU", - "U6x6TUR5I5ml2pOo7UW8uOY2JNEYsu9icuPV0WoCmDmtSeuBqaMUm4gLZURhIeVXXTr7+xgLShDpMnF8", - "7lXbYPxcQ1xvHCYXoYqdz4uGo9qdp8zH2Gfcy8RdNobV9mWlhOy/ClF4WYQa04WiqyEoiFr5hcVjOfHa", - "sNKwPrxrPcHtGzk+eRJUH8p1S3NrjPqndClrSN/JPwT/Z9OD4m6EBsK+MaAfVtWAMPXXchi77bk87stO", - "75Kd/JJeRZXpy88U08B5ujIewkrkOu3+jafUCrbswcrLxBE+k7JUm0GbmlQWFTa+zW+iGm14tqmY+LLu", - "JluPAjbn12orDpxhqwdFAhzi82KBn0IbGuDPIv2NnT6/0/H/6v+BLomXMsu2osIPMss6iZsS8kahE92T", - "igJb3toD6lZHDqv5TRb8fP/DFxkiCuxIzhTPKOF88LS5PU5Szu2tWPmBmv1u8JLW84iZ9xenDvsJStP5", - "fw8mVIfgPtCTXsNavf6CYKFWnxo7H1ha0qKaBKX/5YtMmhPujjac2V2QI5UddCts9bvhXLicz6zH0RTa", - "9Ljvlk7Y4Ln8xTorl/KVWY9Bd8JUXbhtPszl9oJTwiZn5s/E0+7glBvXBt06uueG/deFywtHliA5FVQZ", - "7DF+5cHiVyp4rwu3s6+xEQlW1pwdlBbWZg5NppYPof2D5kCOo2yv07rqDO07fj6b1mdKTh8tYbkRVxLv", - "v4wOV6QM6ozqncI4KnjhszK2csKQtrGKGhvDm07KkNmYvzIcW/AkdTrmX+0HJxTyGa1MDU3QvniRXkjn", - "wgN4WfxuFa60EW57GS3kuM0BSnzwy4vB3w8Hfx78/D/+7VZ8Gc/iYJF/fefEWSWy+5Otcdf46+C1VNLO", - "RTp40eSKLhfCOr7I4SyiQ6+pgKbOQ/bXghuunKBjmAj24fXLr7766s/DzZErtamc0aPBrWbiHxxuOxGY", - "yrPDZ5t4hrTe2UFiWT/0/uyzPBPcCubMkt4q6YWjvt0fkJrQ46vhjaqYzSg7K1RFRAcyGIHc4y2biKk2", - "sFCHLuW1RcRsCU8bsiV8/IJTvFJBXIskis6E98OsMmldK6OCJ0o6bHH3h9iY12qTNAujUW7VtWRRaxT9", - "xlfpN3GW9/Y0i++glcXvuLELbi7b/ZhpnTb6f/nal4pw3WcJ4Sp4Q0WwWMdzKhVWtiKc4OZSmFCn+5/k", - "didDehmvXL49/RpkQjLnuRMm9Fl/g3/LzeVDKyy1MR4wLcUOc2i7673FfYqE9odRjV6kacRMwhUfSCXV", - "ILD5Eid3pw0UTFtSozw0GtYH2ag2P90kAr2Q/QKrM+EOMM5sYoRQVR7zHrwPqZZqWGYuDDs59u4ZPnJA", - "GCqf573Vb4MHOt+EBjp/eCyojHH7u5P3E/m80ThO53UFsPuB5Nn2kJv/5Ffcu6Gh43KILFMuhk14L272", - "4dXpmyE7ixW7qbTvXGT5EbjmjMfjf9oLBcMO4ePe/nPW9n8HBwyl8UK4uU5rvS56SSaTy4teU/eDA3YG", - "T0muMKIfqxP3w0UnFm3H0ph1qGvBNTACzhodbq+4zLBytp8SLKk4PPwq+b8GA/bdq7+evGN/ffXu1YcX", - "56+OcSfY21fn378/Zm9Ozs7ZYICNBRRxgB+P2DiOPe77PzA1RvxLLKQ7gYCcMXT6rizR54zOjtgYqij3", - "2Tg1XCpK+AJ/gub8Whv8AH/PtNM/mgz+CZ7EoGDBvymoSU5kJt3yzIcZwQ+4t/APUMHOIYazj1GV2YnK", - "C/wjN/AEKpbwb5sYnSHwhOew52fIVAIwjHjiE5yYj4Y55xPseC1dMvd/KHHt/4VOPP7fQtnCiA+CZ/6D", - "nMJdmcJNw1LfVhf9RvO0ugcZxtpWvviQu5M0w23+J3YuYmJX+GvuXP5X4XDPKZzpiI1XA7jG/fitRJfK", - "R56mLwvr9GK1NUBo/oVc0crfxlX0evXuuBtyXSiPJwOPJwFbUU/kEYcxKpUyEmVLJAmtYojtmPzyMKxl", - "avQvQl2ophC1JJOCKreXgLkNK/Il0X3Hof/Y97VjgXsmuNgLhaFuPE37GOlMFErbEWY/XD+CvX0sxZ+A", - "Hc9itFzF037811fn7IC6HDi/0zid9Qi6/VCsfUw+q74XtYBY/Zd6sdCKAeJMIa1wlZdxvKh6Gtu76IV6", - "s57BDBO9IC5CDSt4ugdfE40OvUYI9hdGTRoJs9I4k+qS/QX7DJVOhR1OpUr34J/sL4QGDP4YGp0J9pe/", - "/IVd9KDPRY/Br8++pf9SG3S9pDZvtalVrxgOhzRzOWV7/xdA2PdhfkpcMxREewQZnfWnoL9Wl4p8ZA/7", - "Pb9QYfaYIDEsdY1l7F30DtwiP8BwnFzNLnp9dPnrs6ffHh6WsOvsce9XgPqxwqvPdT6g6jgTqQDVfCDb", - "UvGFDyOQCx9PtdBpkYkYMM0K5SSWtxcU40NWY5IUnIL3IfYjVh+64lnhqwPLmdIGnFcFFtOnKxiFpZfs", - "fW84HO6P+8DHrQYR5FEcQ/xWGD+1HbJTqZRIgYG7ZI6+e564Sl/gQaKNGDMols9nNJ8LVZKlp4ywBWxM", - "69/bD3SRpDlQQm70FcaeFKqSTeFYXCHNeeSMfrYGNmshQuRdxn+RnptIDJ0sYwEroeVD9kFY4fr4zXvH", - "9mO8ow8C7LP379/2/QFQkH6odJvCvPSSIhKtI0/9NOTIw68vfzw5fkabOZIp0HB0xqOTssJIKhINrE5a", - "JlTqr+IrS1+NOi2zMMRYKcgWATfYK54Jf5k3BVAqYqC/kFcDKtdcMAHyi9MT+5xJnAEQlOUqneibjREq", - "ntd/AD3uYfTkygi1K3tdVcRK+354COMN9coxPIKMj39ib+V3wYJHu4tpbOnice5RxAgwZFjG4fpp5zwT", - "KUu5APYbwOO7DZqu8fsT60ErcZ1JJQapCKP6HgP4TFOhGklKqwEiUUFGlq8PD4e9T/ngXNvUblE2ez7M", - "hmGca6zy7Gli/0630KdffV6vxPoFoxIViopOR+dkm/BMOP2LMBrqTgPTa7/anBr/MOqzqWBKDYCAHvya", - "AZQ+XHa5STPc9Sn7/vz8NCZJIVd7DAIPTv+AvhiSLC2AvAbr+DXUmZOOTUTCCyvYj0peGj519OtKXBu0", - "xYx6ahmR3TOPv71tdOunZZ7Bys/134XRvS7O7Nh+4PQAVsn8XqX3cqJlYpRsGSDjvoqwq5Ut6mw3qB6t", - "UJtP9oOwThthmQI9JmO2tthwHazMok8JV8pML/Xp0jsGhRemmaAjp77x4eVvb5nSvpwgU0Kk1r+2zEWW", - "gqpzKRp5uLr76Qn1QIdHgO9+drFJp6xc/orIYq966fAhC42/Pvwaw4FjOxkiWal5s9T8q3DncT4PyN/j", - "IODS1ugNed68wNsajNeTcbXA75aIKySwXmGa3DiJrIqq0dCRtR4V2hL9CFLYSpw8syJy+orSQMG6pMal", - "z8MzdRWEEY5TP2kirljhIErc7oQc7Ix6+dj1OHXA+bArgPaevnziNpZkghsbkjw1I+afiTGMrdMGrjEe", - "xBhmQVCwzmuZdQnDrTHPTGYET5dlKmuC8Hx9PICViSlcVvx+NeZTgnOsI/yDKYhxmJc4z0/twndrivt8", - "lZU+k/H/R1zvHRlEU6a+M+G2cIRAI88On9bp85oTgVYcckpafR6zDjw7PIR+aEaxQMKZSAI16NwNpDpa", - "zVpGxAfQq3xkj5fJE3AcuqSHXI5WuBBriDdQzyMCWwga034rO3ge06/IKFO9urCJJ/0meUjhPh8H+c1z", - "jPt8mr79hKxwX+Ir5N3UlJpyWUmL33wtOFHerqB8QqnoKFFOgTx0+2wWUhhUs9KsTLTKzA7LVCjcQhiT", - "SJlQVyLTuSgvCX5Yy3ga/O+eHX7d8HtIYMn2lA7DB588bcq2T2zJkqQtuRKyrK8PDxnZJmXKffIjtBQ0", - "0/gkk7bUFMiP+YHc/WksHOIzufuX6/SH1Bi8i8eR02zRpBtONOEGhUjtvC0sRSViSFyhKYQcAfIkETmi", - "V+HKk96Ma89JNoapDG9P6zX68yfRgSR2J8e1iID1pBqWcXodrjvHl2MTSftcV/jwhwLOJzRbsLFMj9iv", - "Vvzr48WFAmf3I/ZrOKQBYAR8v7hQY9AU6HSYwoJNZJv0BtnBQivttJIJmmbDKwBPjLZ2hdF6EzPkRn3D", - "rRvgmQ5Ojn1KVrWMGgwrE+QBcSIdwrQxFHwRTEa07CE7xgR7MCmKgiSUmPHchmvSWKZjSo14FNJgGZEI", - "CWmN8DdpqS4gZmB9yvjcJ7hwc8plPbACFAoJz6O0s+xaGGAlZObGFUDjSQHpDIfsJb7tWWbnmBLHGUyb", - "tgYN3Y+FE4nD+Q7Za8y9Vy7fBt1qZcsoA20ctrzN+aOiJ0m8LApK9oGzfo7+zWz8/+BzzPIvPMvGVGWr", - "Bk5nqbDOXxhjFkGf+IPMzdcS9nvOcxFy0c2EEgbeRuqccDxkr7WJGqPfPeGvp552KVU05c9ke9CcUk8K", - "Y1lhfQEYnRQLoaAXPq6P9/s1dj4GLB4jzmmziEUWF6GEzNhrSv+O0zrGxsTU+jFVHoxLwJs4PUVC1Je3", - "teY6mKgXgnFM0ujzoNfoacje43uXYVaolB02nEc43lxbSZeBbjSJGU9qhIXPbURGAsjM+CdsPxT3mbWH", - "7JxfCgv9EpHiQPhwMCa8GZPgxVdwGlhYTOdsNTIkMM0OjPBoXA6XCQ44WcsgMyCQcEJzaZ02S9p69Jcn", - "z+fSYb5GBLsVMsDMguNdEH7IPsCsiKThtdUy7tjTw2dfP8cOEZl5hRMA4dnCTHki6LmEEgkisc+M4C7k", - "eX5aWeZKWADtSHOMUZb1fr5NNMAdorQ6Sfw3HYTRF1dVYXUFcKKUgn1wJpRjkQN0EvDeM4LcNgboVrHV", - "rEuX54rfIPWm9MYxzS6yXtS7T4776IBqc56IPjE/YeiROqZFXgjHYR+bk4mRDw35qOCz9UPaetcG2xQE", - "H2op+D2oZHq2w/tzYG+A3uERrd9WSjv6BOORpGwCRwLYXDlJyiBW/h38RcGRIwTOawNlA/xfQ8iUWv6G", - "MMJrZ1B6oDO7krzyQDisgFjpBA2hLAEmyobhC4sVH9ik8pjo++xZIdgY/R/H+97ZiarCLArrmAAhwyla", - "lp6LxSJ3YJ82fHmh9BS8CaWSFf3mxw9vAq7afh1J2V7p8cQV06FSlPcPIUTa9xm+w2qmhSL1iWZHex4L", - "AnCnvR/LkL31o2JmeDRau+j9EjQOS8AVxdagMm2rjli6cAM9HcQEaNTiOcNMplH/wFVJ64sygHqWCJ/S", - "+kJBPjLbMHQokICWMqlYg2cWuZNob1hhWgkcirzB6EYC7fohvSgwDGATCDlN8e+ad86ZcBdUamMEQp8K", - "jkUM9qVZoLnnTjHTLK2wzG1I7cvdfn6hwrOENt4Sx9M0uJ+F/NIEneq9eshaCbjLhD/L5OdUGliqovFq", - "/iL4Ea5ys11u5t4XDVlfkuYjIh/4q5rpgoqgSpdFUur1e6htQcu4G72jXsW3DcQVEk7vqPePXy8UY5dS", - "pUfsAga66PXhC+LPEfu1MNnIBwjaI/aPRl+5g3+/6P38EbvBlh4xhMnwMACqETwdwRpwon4AxiocC1rh", - "YkLG39qShrELpss/Q9o7Yr+CNIWeVGUU3M54mkoi1NNY5tQ/A9H86L+eXo8ooRLbGyHcPvsVVy3sx/3o", - "lLfn14ITOvIucP+0e3tlk0A0Q2zTZ79SLuuT9MgzF/uPw5+HTucj+gGi8PdpNvA/H3++wFJbPeCc24+5", - "wmbvdNQA4KHOGlfS7bChKa3sHk+ZeTa9AUZe6fmrP9zYjPSzCziVWIQMN8Sv6edNyFTFHQ+4jiHVU//Y", - "NSdjE0/5TOFYOypPpbpBcjBWicA+yEi5VJbsBsjDxXW2pLYVLesLM5SDAnY7la5FZz/4da0g8KruDr7X", - "lPC/qtRNljVFfcheqIoki29PlZjg+MzFVSIyiiOvS7gPFbf3EhE6JQjZkhikEoyeuBHEo/8M/zkc/Pnn", - "X5999bFbTHqDJbeChyF/7PCz5qiCKTDegCO7oQg5vG96Q7nCMjKUo5Unjuy3tWIyscY3Gca0zkZGTIfs", - "nVYDsKnYYgKmolQkGYcuV2TMpRCAUNAlmpqENL4eDBlpdF5knKpLUOZdlKFSzUYIl95IKAPTkL2nBPwA", - "90JBO1+u1gmzgDhan5WzqgZ7o6/iV3Lm36wr140qJZBQsIxP9JW4UM++PmQ/yO/i/ENO4GpZLM6cKRSV", - "m6GhY2GC+GQtFwLzwvgdKGnrQk3ETFJhD8Es3uDLuhyFS/RCjAp1qfS1Qr2YyokZ4eJbBc675nLYpHDS", - "IdcI8SGegWgAGmyDXzGyd37NVv2L8cWr4lz8FD2A86yw7Gs8CD0tH2zgCoDmcO98HL2OP6nPb7li6r7B", - "8deXmisfi6hIW8lnVcqERMwqSYLuqRUaw0cSbcrCMWuoP/wyslhBr68f7Bxe07to00GUjdhEzLjq46ud", - "xNoq/gIPdOdrMSrt2EQwPUHqTIcrbJpwnfEYsyTS27PqbqY3HsuHAT1UBrNVe9xk6W/BOhcKb0xYi2vJ", - "xGIiQHPyxWAUhbLgpUFbvFtRIMh7RY9yaCb2RNoPDyI+MmShlXTarFV+gthAHC8UH0ILPoaqkTJxoXBa", - "3AjPp0MedRi+H7rRpzBhFuYLXYXPs44g8BVrtaLIEIwPqFNWaoXEd3nYEG1K2PQSidOsbKKbiwXltUcP", - "fS9BhAUJRXWB8BnT2xdwHZaMQfxfhYiCkuBGIUrBLC2ydsXK1L9QsAeVAC4QTr7AF21Tn3LIQ7NohGpa", - "l48BSimbPBRFKuenfTW5UHprtZxci9tt3Xyx8bnp1Q1uT8266I9jQ/J3Qb1G1Ks5Azxe6zqlgL9vtt/Z", - "MNxU++9zKpfHnlnVuYfXk3asQ/Lx4/9/AJEO1cgp1QMA", + "H4sIAAAAAAAC/+z9i3IbOZIoDL8KPn4bYWkPScnuy87IMfH9bsue1rYv+i319O6M+iPBKpDEqAjUAChJ", + "7P594jzEecLzJH9kJoCqIqvIoi52u1sbGz1WEUjcMhOJvP7aS/Qi10ooZ3tHv/aMsLlWVuAf3/H0g/hX", + "Iax7ZYw28CnRygnl4J88zzOZcCe1Ovin1Qq+2WQuFhz+9W9GTHtHvf/7oIR/QL/aA4L28ePHfi8VNjEy", + "ByC9IxiQ+RF7H/u9l1pNM5l8qtHDcDD0iXLCKJ59oqHDcOxMmCthmG/Y773T7rUuVPqJ5vFOO4bj9eA3", + "3xygvUjTl4V1evGTmLx9eXqudWbDScFU0lQCCJ6dGp0L4yRg0JRnVvR7eeXTr72pNokY6Sthro10YqT4", + "QticJwJ+TMWUF5mLXeuze+H0QiY8y5bMiDzjiWA8y5i4kdZJNWMOZsWkYm4uLYuA2bV0c/o24S6Zs+u5", + "UMyZQgx7/Z5b5qJ31JtonQmuYM9rM8q5g6PpHfX+33+8GPydD345HPx5NBz8/OvT/tNnf/r4byUI64xU", + "M4BgdWHCgqoL+E9+xc/wbyZuciOslRpmyx0TVzwruBOWOc04U1oNxCJ3S8aN4UumpyzB/cdFslRMpcId", + "t7CGBb95I9TMzXtHfzrE/1ub1Md+z4h/FdKItHf0j8oa42x/jn305J+CyOA72K+XepEXTpgXCQzY9dRX", + "js5vPazDg2Mc4eGCxY1ICieYBeDKSTjjYW8VdXyH9X19b1JhRMoyaR0MsQ55yF7hP2C/rdO5Zbjxgk2l", + "sY4JIAgYUDqxsNvIp74hsE8LqU6o59O4i3hwaxsf1tC420ZfW2Fe5PIlz7JXV57OV3cSKICQJjXyCjBm", + "LtiE+vbZnKs0EymbLPH7pTBKZAO54DNhBzyXzCKLOYrnMACWYnQWdq3PTjO+vDZyNncs0anweyi16jOb", + "GCGUnWtnGVcpSzKZTzQ3KeNJIqwdMpi6pektuOIzgdP421smlXWCp0wspGPjPONuqs1ixHM5ghWNhxdq", + "7cQT7sRMmyX8W6hiATvop9v7eQ3H+72Uu63Mr2GXj6FbjW47AMCeZ9TjY7/nTKFguun6kZ2bQjA5xY2A", + "GbKpFFnKrrllsRdLCwH4auUvgmVyIZ1t5k6uAf9xKszJhbCOL3JggT8qecMWMjHaikSrFKHBhnPXO+pJ", + "5b79ugQvlRMzgRcOfSl3OxxPw3avYLazAWC/PLfN3KXlJHZjLaeAwkASOV9mmqdsqg0bR7RiAuDadW4C", + "qL2+lXSgzBaThXRwLk6zsWciJV281KkY91nC81ykjDv2p6d/fsYmSycsy+SlgEHNkmk3FwZauQLYE23c", + "kL0IHYHnCyYtSwrHtGKcJXNueOKEYRO4hrlZIpkJleLFNh4Oh/+IOPPzeMheTCycPay5OiYsFCWDYdP9", + "lBb042jRgEw/8SwbJJlOLlloxzQhL/EWAzNZyCyTFdTyY6hiMSFEijMYyQaSeAu3gUiZ0YUTT2w53z7e", + "2ynjxNaIWeE3y6SzcQp7YjgbsvE5vxRnkSeN+2z8qvGs9hv3wdBd1jhDQCv/O5MpXEpTKQybGr1oYayh", + "9UKmaSauuRGNg1rHXdGw79+fn5+yIH8zaoX8d9hAqCu0V1nIys7H8eqnvoEcgRbPHE8u16f48viUfSgU", + "MJohNjk3PBHMiNwIQEMUwuaCVeQcpEwLbYFM4EfojZe0ItIcstfADi0rrGAwguILAJRoBT/jRW44YrWb", + "c8Ws4pdilHCL/HKBYgXAfTk3eiHYsbhC6ZSdGu10ojN2LY1gxPqa75gse234gv7aLFjgaqbYuM8Adc1C", + "W0dCRE18WBlCZ8VCvSPaWBvk78LowYRbkTJqyIiKUG6VJKZkUjXiQb83LRTe2+/4YrPEGRoiMfWZNowE", + "TMJM5CBcabVc6MLGxrYRhWE2HVYDzRrWQq2bV0O/naTNuEd/V8ixcXaFyda7//jhDSwZ1h64mYc2lVkT", + "oa5QWG2bK/Ok4Wpb0q+fdxOp1UXElRttDQlzuglZxiciw4PC6SNROaRA4obcLlXCEl5Y0czvcm7C2zHL", + "3k97R//oJOmUHOHjz2u3L4KsTQYxCaeCX+1wbTMrJLeREeUumfOXc55lQs3EyXHT3vB/FaKCEczOuSHx", + "ly5+4thaCXYlrZxkgiUB4JC9UAwZ+GBmZIoXdTLnLOGKGeHMkl6OnE2NsHPmuL1kuTCMOwek02dWI+Bx", + "hDiS6Zgt+JJNBOPW6kSibIdgFkXmZJ4JNgZA2BLvfwsCQW50WiTCYGfkpuZKMOkYT4y2lnGWgyhtBEo4", + "9IAFEdt/kJbl3LiI2YDlcVJM5NLCPcJOHEu1sExpx6RKZcKdoGVpYHTABrSpdASUyASKEcg41xCq5aQ+", + "CFtkrvUBEw8i7Hcc0AiOYgFnwFolIL0uXKIX8IDzAplWicBjqJzjT1w6TxjS0sH3a5cGp2UanFifOc1S", + "QUPQ+wT0EcDby6nEccd+miOrsysxso4bJ9IxymUrvxH4MaMFTwRu8pVMC54xbGFwGvR0gpPWSVKYEjNQ", + "gg+sEjCrXGLXxxHN566Pow0H+vhWan0rBWQo2QEhxF3fTv7odmCVq+d1ixdVJITas6ptiRueWb5H2Kzu", + "2HcOPT72e1Xuekv8PTm+1bMnCvvlbsDDjRvSNuKDZJVR9VkCzARa0IPME76/NADfJsJdC1HnqeXDqe19", + "cL4yUGD2DdfaGMdMx0fYAG8OPcErJV1ZTpIJbhifoj5uZapD9lob5vSlUIFVW2KwC8GVZbx8rVAjIFL/", + "EniO6AJ/2AFX6WCusxSuM+pZnwPOT/ErOUPi5td8OWTjKZdZYURYQ7gfrdP05qYpK1CkZjKRrjwIvwoP", + "AAXdmzkvLACHE/PLs+x6LjOxMhkjFlwqkQ7ZGHiELtzKDJ7YsvUgE1ciY9dw+0yKdCZQrwtEvQ02n3CV", + "aoVnREdDGCdU6uUFXbhwIimzcoYnv3nFEQOnuGYOlzebCBQIcSrXEucI55RKu5DWwn1qSiwpFJC6SIcX", + "KuBQvMxWjq2PUgR8mmb6mnED+gomHUgzVjqBUpR1MsuYEcCuGAd5R6aELH28A/Gf1m8aylOIX5JElNxo", + "xHHu2PWcO4H3Z21HYSWzgpsUyM0WSSIEzb7Xj1yZ1gEcnRACaI5OttfvxXNY59H93s0AYAyuuFH0PPxH", + "L3KUswA1fnkdwcdP53Gc+OlFOeDHfu9aTGCvRnNtGySl77WNIl0eNKmrrAglokZpPwDPuZuvAz/lbt4R", + "OPv/FsjIHHG1myQrYJe3vplqrL+iiKgx9B30EggNN36LgOkHJrqInHeDcPkZZKvVdTzKVVvlqqqQ/YD6", + "6E0HtLsgFbCvUYyqPxt+tyIU0SG+nAC/1t92557rA3byws21kY47eSV8VydBJficpRovBnirXokGOW3G", + "c7Kftj3a/NPweq6tYKnIJIpocBWR6TEBDseNwGHgZuHKiXCjrIlqaDYctRkS4E4e2FwkcioTMjGSPQ1m", + "7IUTr8Z+9eHD+w+jly9Oz19+/2L047uz92/+9uK7N6/G+1HDrxVdcNbupFU+X9vrsQczPgpygxGuMAo5", + "Y2E5yJJWZ2jwq8lha62VX9SeFYKNy80Y79ekJ98vlSnuKvWvKgRBHYSCVUWQWpGRqAlLuEpElq1ILXXZ", + "EfTvAxxzRQ6gZe8uCABHIo1Nq/4pCIcDbkFUE2mDRsp7IQhSWQOetSDpxsu8o6RwPRfGX+k0BnJ6HCe9", + "D2FhI/z7lhfuJiAA366yw3XNsl/BpVQpMyLXxpECEZZHyDsEa8KVTKsEjQolMkwRwzALnslf4OyV84Ks", + "Fe6ICeWEyY20gl1xI7lyFvbSCE/vLNFZxnMrQkchDbsSBp1DJkVyKRzbu3rGDtjVV/t9NsZX1YirdASv", + "qjG9N+3qYyuyfEuidqEyiU8gWCZNOa6VWzZGu+G4TjLzIPLAOYXTuXpW//MrONfCKJD14dhmQjhhHd5i", + "1Yn2+j0co5HAGo7wjMihm5Bn0P8gdyTecXv52US66rQfZbqOMp1nfZ9MUdZ8UrsLd2QSaJfs6nKHLZXY", + "qMFfwV3rUbdfqrgrSmN6V6tZ1qDxwbe2v4PYgqsl9rD4oE60ssVCGMsWhXV4A3MLX1DB7CdI86tr1Zk2", + "LOfS+LkDQ+TGyCvUQ6TAE3+CRXiFT79i1ki0MSIjZ7aojw+2lCj8NQvBfa9Xr1lUZkYXuaVFbbTnHAeJ", + "zmsQNNlvjxhfWemC+9UIr0mSzkbrAMxASDQelK0ngi2kteTAEfeBcZDOErwKjZhqIxosLElhyEgWxGDX", + "os//zYj5n0Te8SfeYlq6s8AD7p4Chg1SyVs6RbJ6A7HWTDKoZkq4MUumNMEEmzEJ6BUjoS0mSPZ2/2Hk", + "qLVp34cwtZ0jPopGv3XRKM1fFE5PZZa9bXxw/jSXyZxOSk+9axn3PcDJIQNkesmVVjLhGTXw3DQVV+g7", + "Pci9z8z/51l6+PTP4j++qi864QbmytMUpt9xtudGzmbCvNSLBVfpLS7aM66kQ+wZB5hDR0DHjJtZsaC7", + "tVybVHnhjpqaS7VhsX2WS6XIoW/uXG6PDg5m0s2LyTDRiwNyMAr+RQdrcA4mmZ4cBGBi8tV/PE2fpt/+", + "+U/fpM++Tb/68zfpf/xpkv5p+if+7NmEo8v+gXfbHQUYQ/g6ZK9ILeHXRhxDWpbQHrI5J+uLQ3MC04YZ", + "kfIExT2RSKQOqVgmJ3GWudE3ywPAvpQ7fpCk+ajcuiVfZE03kj/oEcqVo0QXTZI4ubnAHH1zEkO9ucDP", + "OODfOVKwZw0qDViIXAL1+8FZsnYrVORID7DxcjovB3xi2X+evX83+HD6ksnUWxbK6SQcrHDsnxr3jziL", + "v/6r3tSlrgOuC7RtkDLGO2AIlmQS/saPSit/r3eQhxOtlEha/SNPwnVK2wjOT3iCrOxXWxDJMinTql+9", + "b9N85DsEf4U0H6XSho9Ddn6t/SIsupMHFz50IQnbAMfjgHNy9DJB/i8trbUSe/D02Z8aOAIhzwZhYsKT", + "S6FSpnRa8+Tx9yT291YgwHtP0+0ogv55mwbEBpWRhuxlJtGq6DR7+uxPpReufc44y7SaCVM666IIzYzg", + "WRVGt81YCDfXafUhtMqjGrnqwnP83dy2Vm6Mdeetn8Km0oYegYRm0jFDB2oi5jHSbKBTNxcLK7KrVpKF", + "xy6FtTQeAOCx/7160lVMxjOmsfFAai7OHiG93dV3sRvOr9OxrEhO/owqmLtJfErz8C/UTR7ra7Sh3st1", + "5yEPkxroLZdeW6fHq2+Xqy/MDuPtbtxG/kVNmW/6eRjL4734pd2LqafM0azYgFzr92HoV16J0SryWS+y", + "Zr7TeJ39fq6I+iF2uycybcX9Xg8AseutQG0fL4NdLoNH5vqlMdcN7AkI4HfNlTpxoTPhXlIqAXsmf7lf", + "fmTrsDtyprVejzzqkUf9nnnUXEB4agOv8VTAqAFgx/HJaZu2o53TrRDU74Tn9XvXMm2yrcRtw9+37Nq1", + "VKm+bly23z5GTdYk4y2RuFEyLEfoyo9/wh7f6UKl9r75cRV2d35c7/XIjx/58R+RHxMVdOPGmZi2Q7hh", + "ubZIxwCFUqmwRGuTSsWdsLdi8VUa/d2weKfz1l1c3nIXW64ND/XTXhoRFjqD3EazT9M+w+4Nin2aBkIP", + "eSlEyvbGZIqHPBkLqeQC7gn8g9+Uf0yLLKNtRfdjry/yMVDIaUsfF0xEhcqkFov5ne9HfxO2ugEGFAxZ", + "jCKjqbE8HWKHAON/EpMzjb4DyKqO6OpjM2FdYYTtB4diTEeSSp7pGeUdkWrWx3wBzIrMMzcYq5IVacgg", + "jZycBdf0QBPYDiZw/P7tgc+hwZzhU/CXiHPN5MRwdF+yhYg5qqJ/9ETMeTaN/ulhy4cX6r0SFR+utj3x", + "IeMUBlO5PsjGE1pZZwRfBAWhxTCytM8SzTNhk3BnetcqjKGnkaVlGbrlqGxZXjx04PBj8F1BtiwyscAQ", + "+6S6Xf2yX3k/xru2dP9PdEopLLB5knFrwfHEbzlX0OpSiJwVOWT+SrLCYh4R2Dk0Y6MryuotM4yzGoW5", + "jp+HG9dt7pAajEv81FmsVgjk0eG03eEURQzcqk/gZtpwLI0ZhgLN1X1Iy6kGz1HgQ9B3gXccktCYKGs8", + "ZK94Mg/+U+jCJpF3ZOSmVZIPz3Ojr7yQSP5uNMpRad/Fj0WWMvSU4syKxAjH/s//+t8MFptS1je9iHcw", + "mLz64Cpn+8yIqTBGGNv3yVVsnzmxyNEX1HPOnLs5LMfwGUvCkw2ARl8lPxcY0rtiZTyhNXOWodzQZ5zo", + "GP5BHqgJBKLyWR/DUlSxQOdMmBdDdBc4xlxbnwOosp2UWHPB8xxQAZJdrprkO9vZG3yd+m2Gka1At9qV", + "+ytKzc4QVy0Q/VadQVeQG9SJ/VZpdQfgbW/jfu/4/dvhVCdFB3DHevEaWq4DsInRWXainP6bFNcn03cY", + "R9wJ4llj14YhhHstM3ECogb8o9t8z1Z71QHj94BYhs9miMHb4GKvl7VOTWBTaXN4oUEbL351gny82m8T", + "8B/E8jawQ7dNoN/qworbAC87bgJ/rotkfhvwZccm8GJRALvERq+NXuy8iletAJqGkwuBtBsZesdRTlb7", + "NQJXVhh3Lm66zv0kdmgCZ5fKzQUIFqdSJfO/krzeEfRZY+fNwxBt33acWu/NA53z/LajlF3rQ5zymRhO", + "QLo516+N7oI+0OW7So8GgN7Xq0y52A3qy9VuG0Arnu8O2HdqAtvtakRg6/cigqCck2UqvWN8EnaD+X1j", + "34ZBQhBrN7DvfOsNgM7199I6bZavlDPL3cDW+zYMkhup3Lk+PX7dDfCpb59OG4BRErNugD6IdSkIgYBw", + "ISZv5FQkyyQTpBnpBPKsoWfTAI4bRxiccNsRP8/qnRrB6vyN5mmnm5tAxg4t4HafZLVPHeg5NxCNzRMn", + "rwAx8M/tYKndi1qvRsBInrtBfVl2aQZpBHci9CKnvM6wG/puGGTHiVf6NAIF0ULbW079uKlz4zA6FyqY", + "YrpCf1/pUwX6MSo7lpSBNGj4IAWwEjvpNDsIYR/7twLWJC7uCKpZNNkVyCap6ZZraxYnbwmsUWbfEVb7", + "y2JHQN0k2R2BbpcDbw2wVeC7NcRm4a47uG0vyJ0grb2dd5vH1ndyd3CbBNXdoGwUTG8HqkEU3Q3QdpFx", + "N3hNsuLtILSLhbvBWxfiduvfLE3uBmODZLYrIJ3fF5wGuW5HJFx9wuw4hy2icHdo2wTAXSG1CH07g2kR", + "wW4Hp13W2hXeVuFtV4Dt8lpXOFvVz7uDuj1ybtcE3wZWm8q6O6wNiv+PPzfZg95GX45thmywVHvjqbe9", + "3yy9ydeSwdYKFyLcKxZTy7hifCZUU30gzMrwfNXoevz+LZpHgl16ovUlmE/R3g0/kPtWGeD/40llNIPJ", + "sq1MBXoelR5llSpVR51jzFt1uK2a4wZtY7t2c4MWt13v3aJo76Cy3aK63KZy3KgpbLMrVG0iG80bTUrC", + "Vj1fi5Zus4psVbe1WUVVVweta5paFDHNmo8G9UpNI7hJbdSm9mjUWjSrBDZrI7a8+Jtf6q2WxFU7YLvF", + "rd3Q1+8WiFzlZ+gC0eaXo5i48TUNvW8LZVKhKnbCsLPjH6qVxvrstMhz4YQw+8F3sPR4bPDaIecYadnf", + "3g67elx4h8R7cbooV//odLHF6QK36iETtjacxy0y3kf8aPLG8L6p7cXEunvJStvoJlvxh4WjHtdAjoMv", + "WJNzCLltlJ61eA0/tL/sx43ncRx9pLoziNKvSqSUl6YD6bNTLk2Za0ouFiKV3IkMy6gkIl33L9aq3Ajy", + "dfsMDGRlgx55yEYeUqLGw7KRplPZnZOUs13nJOVvj8zkPkoSlgvrVJVwIazlM7E9lxG9vrCxZUZkfCnS", + "UIxpfVyfLTCVhr41FzczgtumAl8/zZerMLEOBNQewk0fUdT2UTWSA19WSLf0UVvI7VzkxNGgQIuaYepk", + "fLvJYoFOrJQDETMke7f/4JdMGOQog+G1ioEoNBr5BBoR8JrPuFSWYlCUuGZh3OoUhDHajI/ib+hKzbQJ", + "+8ryYpFTCmlaq0+1EdMZ+AWHuor+93rKA7bnlrkvCu2LRdp54WAJ+yvJyypb2ev3Vneq+gnn1Ov31mbU", + "yPjXnIA34ZUt8pBFr9lJ2xPgtaCihdfcpKUc7PuwSeFC8h3v+yzSfq3Ux78KUVB9DHDnZ7ps6b2kc65k", + "cinSEDAlVWLEwvtx+6wQ6M7t54X+mIUq5w/foks3KSpIGTCVmcOqiRNKiMnThSxxzU8b6I85DcsjLua0", + "49mQnYfNhMHJi/W5L6RTjUgJhUWILuu7M2Qvsmu+jLVokIlhmc7gAA8rYNI9p+yd1Qa5ESmPdSzxlgSf", + "dJnMgz98ZHvcsl+E0W0BHuu+5JvQojzpSHBVbPD5NlOmdBPTrp68NBWXe5/XED3XCc2GSZoPw4xG/tjG", + "q1EL1dJpcA4YlyYRNYL7PDF5FNPGbW7wW2Ilqzx/lTVHbrnlwm4wS906XjKqTbZESFbaPcZE7pRUiTK9", + "jZRORZeMcKCXXM0KV41Nc6gleUwW+HvO21HqMpvu3m2YdFcMIp6zaYSgMzdioZ1g1GHrcJ8uUdMfI6tJ", + "JweDO10MzTr0DjdFW8fHq+Px6ni8Oh766mgxfT3eJbe5SwzMvy1Nwvf4PehloGltunQQdIfUkTfVxQTT", + "o69pa3C81rj9tMylf3+j3ayP9F9MT6dWdFpaH9+kWLnMUztgzG5TWK5P4b8/3RT+OPLCJsfIu4kKq5C7", + "SAnrfR4FhEcB4VFAuM9E9FkHxT+0spjuozwQJNQhex3j13coWNAilqyS+6NE8od+3dawc8vVFdzSmkv2", + "wM8hFcycW1G9cDrWfAn5e5h1sGLcDO7PK3j6oVraCoccLeav8alX8sKhE6KZSIf5bGjxsYhPMLvX7DMp", + "rEs5YXp9/Pf7K/9Pnfsv5IrasVgO7MNbuRAvK5b8FS6tc3+2b0/evmLBVgxMgFN+CunEol+6Ipy8ePeC", + "GTGTFuwTVR15NTnS82rvJxYKRsE0fdETMitkVOw85uiIY1cSKX2mY/AOaGgP6fV7vEil7vV7UOEJ/pfn", + "eeZNSHi/oKp+oVM8l0WROQmcuVTndzwt79NIzgzNiI28kpEZn3FWukSmIXMT846Y9svBeTHlRQbb5cB5", + "FLeysF03bUu01a1l2CZn1y0ibHOXRwn2MWPkH0vl1EQHf+Bk49tjS+/IpNZ89TvxqYZej6zqkVX9rqvN", + "GD4b7fIC9rX5oV/wYrzlCxiHBmF4+9DQqmXoEycWlYRxu42+kAsx8kK2R+GVV5O0TqrEMdf4KAAM0NNy", + "VjRPimgYg8QMeVNRZIZ/VGRkyKB6Rg8A61Pnta/grrlW+z2c1w5OyKtvpNKpmxvDl3H/gPZxPXa04PZy", + "ff++k877FMPrKcv0tUhpq8qubO/pXxKdL/vs2V8yqS777Om3f1noK7Hfdnb4jI31kHdNkVt/KK8nyV19", + "KR+xcXyDjvv0x/ur8G+dU1288iE6vnty3HYRYj0IraUuIMoGdsuJzOF/Q2N2KZZ4GC8yB2fx0pmsz77+", + "y1vheJ/96S9nczl1rWfyJaaTbjDqgDUQzoTdVHJHA+d5eXbGcnkjMtvZZLLcAH55V/Bt+qIKbewggzUl", + "QrknESyA3kkCKzs9CmA7VeYtnB4ZkQvelG5+LrxqKiSFBqqbCSVMSB57KTCWWHBXo/NKlEcQ8bbe2QJQ", + "R80iuYZrkVJkv8iy8b5PShsrh+OkHg0rvxfZ8m7XdGABLbf0D2K5cklfiiWEvsK1fCmWP+bwD8Ovf/Cf", + "8ZaGK+Je7mdpR5dimfN0M5kBPcmYsF0VC2FkwqhnG4VJO7JLC3LxpVh2oWJ0zKcuOOA6GVWgZ9pradcA", + "/yCWE81NykITkAUyMUVhwAfjfvUXVSxynu53N2u1ROf/RsQWxRcibd5owLBqNmwiyJzPRF3Hv8yjPleG", + "cOZxlBbP+QT+54Ux+jqg5+tvQP7/AeZddeNnvBRhGt4BkHJeW1FLVj9Z0jtjRPmv6/71X3itj3JZm66Z", + "Em5tyraYLKRzvrY8owK8zopsiqbFDk/E+xWwmnOU3ZOIVQLfSciqdnsUs3ZyKimc0+o2txru+XfUff1S", + "ox/QJBiForA2KNKiUI8APHmMpVrSNMMvyJ3hH+DFAv/r44buo1BL3692G1P2rYg5Q5zdkL3TagCxUEwr", + "xtkYbVhv9RV4OS8EV0Sx8NKnK8wrdty8VQTMZHK5XfLEcGOS5mg/MTIww7A2tvfMD4bvKvq8/yhz/m70", + "mSJzvMlb83tt5C9aOZ55p0iGTfsUgo2o+dNcgPam6/Oehmp65AOjSO5voLvJ0SWXb5GkscGKLI3TPKUL", + "f9z3f38QmeDVD56WV9d1Dyxnqn26gxUah83K8ArMYXKFEX12iCJG593cJqGW+/VbkVFzDX+YW2PAKfVv", + "OX7/K0mipTKgfF7s0eHSOef3U/3rCxVJuZrBbHg2Cui3EUfL9hV0HTzdDV+dzBrdz0+FYvBb6Yf034O/", + "szzjSvRJnJsZIexu4yy7jPNfdxvnWlrXPAymcriWVjCjnc9BtzrCOnk8anE3p3y+p0dGCXynR0a12+Mj", + "49GY/qjwbE3QGiml5abGBiuCGvoHYs7icd//9Uql8d8godHFjX/eo4Gyu4QWLORTaaxjOA+GIs29i27l", + "Dv5WRDfDU1nYLe8RatS6TZ23xw+26UVyb0P5+3nE1SxrQIMP/vcNZ38L0eEPKjNu2MT7EibPQcBrG+ah", + "JcyOg99R7ASQIwS5XYOE+V1FdRp25VJFu2Ub1beIuC/XxNsdyOMOcm8rtTO6UcqmlmWwbqnQr53uDHwf", + "2rEXLKSFa4GuDbngZulPqWoR4WGfPDEFUef+Re478rEO0ncT4nSQyLuVKLmjZN6eX7qThL6p+6Ok/hs3", + "B9yHCHcP6vRHxfkfVXH+QGry36xSnE0EbLpnmkhNeDM8pLNnO4d+9Pp89Pq8vb5wY7m5Owola6U1Oski", + "Db0eRZBHZeEfMUhwjRQaeb0RecYTTMw7Eqphpz6UDZjhaiaYUKlPF9SqraoAtY4b1wUsNtwCmHx+4VAb", + "53oWfq7MEXP3y3iaYTO2j9Ay8XKM6oR3HuWP4EfXsB/37URXnVSXC6uxyOpdb6oItNsVVWn+eDc93k1/", + "yLsp0sDvJHj9duwRNuEBPIt3ZIrbKxbfkUE2F6frxCzbuj4yzkfG+XtmnD7j0IjSEd1aPbWe9mhdQ1XL", + "e4Sr2Jj56OG0VM203vJqoQykI5sL0fhood+Zd3lk2A6NYaQmYTl8xEI+rTJ6wjMxmvLEabNhBGwWDEg5", + "TJztXRSHh1+Jp+wXrTHdwP7v2jL9+9OD7XRptlblv7dbszbCjtfmSt/He/Px3ny8N3+v92aN2BsvztyQ", + "hn+awYfWmGD8GW8TW+Q5XSdtgcAU5t/BFybyQp8ZILqPkd1ugzIR4Kci48vG6n3H8AubCHcthAqw+2vl", + "+n5HqrgWqefsWuaCRJ2dJJ0HvsBvgAk4rhLRySjs29YHe85IhXgVsMUyiF7cYQ5Yxx67NhSLLVFzXk4o", + "ziQmv8+5L0koVNp56AeVX/q95YbdXbOMd93bIt9h/I47exUmcy/7eg+CW1nq/kGkthL8jiJbteOjvPYo", + "r/2uvYV8icaGW93/Ei929JLB0rEwWfyryDtf839swbBkKb8ffTvPO7scauZ4vhqx73i+/8cJBdx8M9Zy", + "JDUmsPkSM/77RE69fg/zOPX6vTKNU6/fA5TrmAm96l67tj34I5us+Njy0sP2C9kupRWgE8jVQICYFAT2", + "DMtx9bEADuHfNTfpLhu3AbXW3CO/mN2qZjYIefVDYoPwN+Y1CH9gUoOO23bKZ+I7+HyuXxt9T87+AHQ4", + "qUDdIpc2tH8URx/F0T+Wv8IaEfyBs+3DXrwkj4SzxAih7FzfI2tKVkF34U8NnR6Z1E5MijZwNBFLrdLR", + "lZdDN+eL9J2YuHFCpVUNTujfmvY1k3lriU9AaSyApBWjNrcUsHEUtMxuHgSTMGI7Robe3UZoKR1aHQGb", + "3GUVN5vh3wQH1DsMsdw8xPKOQzzegl9aIUO/GburR0o2/JpgNGhHFkBzNASDK0hY4Gl743/mYgb5JnI1", + "o0wT12KS30+OKHhBjGxhpjwR3Rgb3MiOXwpVho37/mt12YDjtXG7Fnli7dJqFCp07uRC/iJGU23aHF3C", + "3IVKdAqYMOVX2ojUW4FANc9AAdQ2wX8VPJOuiQHoBdr9AG19o5Bm4/CQctBl2tqlP8nfkXntrpKR4vnD", + "yEUe8C5SUezyKBM9Ptwer6zGK8vTSOuFFRo03VmLuVtk93NHbbkq/CT+6K/PTFtxj5wVwHXip9TwkYs+", + "ctE/oPoLsf8Pznm+5yrNxH/yK36GazyWPNOz+2NF80b4XXhTW89HZrULs+JJIvItWq8Ud5awFpvThFJp", + "F3KTh+QjI/ydMMJmUmtxtNWL3I12jwoUygmDDpxOM84Ijke9W0cK/n44dT9Q6naW/Y5fyRl39ygvKg+x", + "C1su2z4y4kep8Xf99jZ8IRoX+T7n/yoEwwYVzrKBMzxnnGVazYTxD2pJL2jAPJ5VYdyJkQfibAkunApj", + "gEB0JpPlbZQKHzyIU4KwrlQIDRiN8WCp+cq1GAE4vEX7XU9LirtO/enmCX91u30qEtAX6WBouKKsJbfP", + "xB1BtLiK+isKlm4Et1qVRxlwgWeZMKEaHJQ1xpzcy5zKpxiRaX5P5ZkKk41wDQ02kjP8HmtUC+ukonn/", + "+OFNmB3eXzArPtEF5hEHvj/eD8hjY3Ze6NSCPJVz+erZvT3fgixwrr+X1mmzfKWcWd6/ZFCHv4ucsNrz", + "UWp4lBp+1zUOAM0bF+npgGGL2nICreAd0Llw6AYy+10rtSp7vJ1Bnhqp3Lk+Taf3xxRzD/P4dRdGWG39", + "yPwemd/vOuxJ2hzCmeeCp8KMplo7Ydplc86oIc6XGrNrYeB4VCo2yN3UduTEIs+4E9tfATyAD11iEHgm", + "y0xV/qddXwGhKNwo1Qmi9EgXLpNKbJpPaMt8W5yQWExEmnYYyfHZTKSjPJ1uGoNasT2eJMJaOcnEPjs9", + "fo1DRXNv21j+DHfZY3+aD7HHGdwnCc+3+Dmh4yMMm3GZwtYiIwp924AvuJlJNZpo5/RifYDv8DujVgz/", + "P5nvUFrDg8cAlDXgb8TU3Rm0afY7/QCf7wzc6byB/+r8DoCbZZnypmxWPfOZGGFOVdsFGX0hcjVbwcMW", + "HMh5LkyrB+8p/Frx3d1xwQS8xa2WYEeH2l1Bo/JilFg7wg0Cr7jNNIK+rrA50BT3JvcKEO9YR4SUb3Gx", + "w9MaQfTUzOhCbXDiK9uwmeH5XCaW2DyCaD+SFkfnUz4LNwT5OP++6yMZriyc8EKnt6tumk7PPYy3Om3S", + "1nyvr3Gd5dXgJaG98Qf85wv7Hbfi26/JfzV8O8PosfvQ0dxW+/EBtUT3J9h7rVMHoT60fBToHwX637NA", + "L2dKGzFKeDLfcqsQRbDJMufEHmGB0K1VotMoX26wr0QRmZr+piwttNxmPQuu5FYpxaUCRidSRh0enc/P", + "hPtJTN7IqUiWSSbO3L3avW0D9C7cv7nf413weBf8AZ2Hmojhd5ONxeJqbiF1r2/JutwdGzAchnF6obK9", + "8dToX4QicZtqbT6cmB0W2YEZO24cBXcl3N5jJJCtA+7Egle7PHLfR+77O6+dbpYj5eYjdDtaX+tr+AwD", + "5plP8iLMFW9NP3rXYFigutbYIppLWzAssjUIh72fACN+06q2e8tv5KJYeE+tUn1XDfVuMLXymzZdXR1g", + "1NltgddycdZZWOOdebs41sd3w5nT+RvNU6lm93lNRaDdrqhK88fr6fF6+iM+Dkoa+IMHWgFHehjZuQq3", + "K196lJwfWdMja8q3SF9/EO60YiBsSGZ/zTgLvicp2gllaSb8YlJb1o2ZvX6vbsnsmsOSSi815/30P9Lk", + "yx3jilgwZQT9snKBAgcUquPmrASINJSXaokP4cEJFqupfjGZZcN6ev3KHz/NhYJcvDPDU9g+beRMqvgP", + "+Pml0da+D9+B15V/OCMT1/jnes9CWT4VP5quCVjX3u4taoS1pzttqI3dv5gzAo0DoLCa7bRFldQpR792", + "S/VV3SLo/mVuEWQn67pT9RQz66jUvEPke+T7fjm8EFLidNyYc25mwr0AxT245uNf9yLxE6ghr0HeIvO3", + "9HmU+h+l/j+W1N9ICL+juhGwnE3uNNTic3jRtBZ0jnPe/ELxHDTT9gGYaVKC7cZJax0e2egjG/1DstEK", + "FTzy0C+HhxrBnQhftXLi5n6ZaQP8jly1secje31kr7/3gEltxUirUSocT+bbEpkoypJlme+Zltudikkx", + "m8EcA28lkMJ2T+O9gRjb0oHdLEfk9D3KpHWdIrPwsKgTg07I7ROtpnK2KQaQBrPCXAnTfZwV2BiGSL/4", + "++X3ne6lUPJKGMuzkRLuWpvLEUWDjkgZub3WHLWzbGa4Ao4VATIPkBFA2tnQ2s3FworsSlgkkC7J3G5j", + "u6jeag/wNKjA3eUWe3wc3Ob26hJKCOTkZTCka9zuNIRPlBDaKDjsgGekm0Q937TkuZ8j+uTxRv/y8r/w", + "SQZlh4C5Ugo5wCCjs3as/g4ak+HFt0XsJlAp25sLnmbCWqZVttxvT4qQFHYz6ShxXSUf7LEpy4IZOT7Z", + "nGFgEgBW64d4Jf86pbYnG2h24PxJqlRfVzw3j09O27wb5zJNhdqZd1C3tok1B+37ad34CuPEAMnyUylz", + "uoNDaMP10ShvKXE9usbBN50KHDO16pbq4Yt8q+u89VyWtzyXLyFTXL/X4prs1x59kjdQCuHG6PbBLdi/", + "LazFTwSh15y/FdwTGezKQiosAYS5/hb8pvxjWmQZHdjnCiwn6jum59XDaUrSpgG6CZktXR+lzZ2kzUdJ", + "8FES/Dyq80b6/Z2n7Gsgty5s+H0uVOBK98l9dQVuN6Zb7/HIax/10n9I3lUlg5YsXUpkjdsTujFswgCS", + "SDfwm/u+QR8tkr8xi6QukvmrK6Fcsy81/k4e0yyfcyu+GF9BBzPHaPlen/54pdLwz7f6SoR/v+QqEZ29", + "CutZ19dV9h2Trn8x2whZ4T0fht3zxDeacAN/FU6PJlpfLri5DH/bYkLR0YC8quBZ9Ut0xw+tnc6RXj3z", + "h7YLCUfmk/v0e5diea1N5V+jKpAuh7aeB6I5n13WnAviizkrylgBO4vpKrruTkWRsJ52k5oFTdaKPuEL", + "ChIArQdgZFB6EGuN/y5VHp12TSurM/HKGG2Qea5v3IvqixUaMwGtmTasUAkvQJVaFnti4iYR2DVEp7xa", + "SIfu2rCf7lqzVFonVeJQpLG6MImw7Fq6OUvldCoMbBGIg8zOeS7skH0olJMLMfTjvzg9eQmsJ2V7/suQ", + "ZgQMye6z3Oi0AJhIjn2sBNUHsdX2UQKyjieXI2d4IkrYcdrnc6OvFduLa4u/VEETzEwq0WeJzoqF6vul", + "jAqTNYzzWoos9fcjEGMCyvggdlJPlLE4SgGNYi93YqbNsipG+fU3nnDqXzZdlHCrWICvIhBycGIdoWDP", + "M+qBqSZhC11TPe5zA9KC133CSU9hd6iceOjF0gL3B9OKZnIhnR02qptdg5UCp8LgYK3ji5xJxX5U8oYt", + "ZGK0FYkGcaqblO787biy5SNEud7P2+QYZwPUfnmCcWM3iTSNZ7KrehV7Bp3Ax/6vKzgFRNFA8VkWaT0+", + "x1iihUlIDqS12iE7JbcJtCTRi4gW5qm9jXBh66UTCxx7XUqlD9wYvqR3EtBXU9IK+M4oIWsw2lIDmIsh", + "RW/JjxC9kLo7T3yFKwwbMYRu/cZHQNhF6ERXQ5/x7JovLbvoIQZd9O60i2ub15wo/I1U4vNvVMkg12cI", + "FgxvzPAzm8rMX6BubsR1fY73MLFaWq7AqLsyTJ5lZ9ALuiNtrYe5FguuBkbwFDk93VD+KrI1DUNAkmtd", + "ZCnzSe9R1fBaG1a74vb26ZLrI4CpNNaV+pgKgXJPogSi4SrreyOImMobvKxofgthLZ+JPkMD1EXvx9AT", + "2dARm2i9uOgxbaq/7UmFBRilFfsMHhO+8U35IJwWChUWF72aEamNZ9YVmIE1/rzGHN/oWWehBWqS0usv", + "Sg2ZnvXj/ko11eVf19yoPhMuGe4PP8NNHBb2eA9vvYebS4ve8y1cO4/f1h2801W64apqFbIBRp/FPLxG", + "F7M5K9RUZlSCFdktaaGHbIx8ZIxWVF1QDSJWE5mICC2TyjrB0+eMZxnDdwpbvTEtiMqCGwZ31JCdCdKC", + "2lwk+NpCHlhkGQOcaGQsD8TbXyPjXT2e9dMZbmV1QWOwneXVsKj1dUscLpgWkehKhU1giQutpNOGaSye", + "m2Wwq4Nwe9LxDNmK+pnUcH1KVUbvmzLEnolcJ+gmcD2XyRw70Ex0khQm+iLUEb+9Iiac8mo5THwhSlWZ", + "TLP8054HGqC2J4HuMyOscAxWw5N5ZXWN4yh+NbLiXw053bTSjjQJ2ZJJlRjBLTzrK9tlQe2gkiCS9akZ", + "zEukcQJO514BXOnZuAkduOcttNWBwmicitWhcT82qJYDbq7pltmedSgccbgNbGWdNiwUfcL2N40Y7oUO", + "lE1GByoyie45zWKoEZm44srR61xaQuXn5IQGDWBnKmcCtIC/Een0g1apbOs9mz1pbWUKlcOqbmx9ySUK", + "bri+qqLAbkbOU6OvhOKApAvhOEoH/uSWgM1E6F4fYpjwSp5I+etSk2iW1E49iAGwdTmVCfXHXB7BEart", + "bhrj9la5l2/ht7oZcS5lk08wiSphQUO0k42P/MXGorXpNPgN0Qheq1Uy1yEbXwoDRiuey/ER+wH/YC9O", + "TxiFGrA9I/BfZFGkj4MyuUuYORuLGycUIML4qEzl7ucTf4NypzrhGdhqE2Ht+IjZpXViwfwHZgql4MQ4", + "2Gq8VrKcbk25mKQ5KqfD/OGnMFCv36sN1CjpBlRpR7YGIWUbPoTbjJABuBXRwYGnkwO6Kk6Oa+cdaGGF", + "tvDwN1DM987l3wu4G2z7Ipwp1gjm+/PzU1+yyrIFz+F0r7lJ0Y1sID2mwOyBtenCMVLlyl/okmF/I7Uz", + "GlqXub8/vJTHJoVjC74EizVXSzRsQ6t6OYS1xZwoJwxHpv0yk8nl1sdSAf9JoGmQJLwvIbuSvERCyrmB", + "ELq9jmQ5kbu+kBrX9PhOan0nVbZ+hCf7gK+l9rO55zeTFZlInG4oBgjlqMKvLOduHnTsuHaRMpGhoNUi", + "UswaFDnnb98wx2d0I+lpEzQ4sCLPhUm4DbfWdz+en79/12cv+uz45G8tMkyjMP83idX1UFtE3E+5loH7", + "zBm5WLQoA2+aYIvrXBvHbgalC3MNOKwFdtFnIW5EsuUGwMvbA17Bw5sejNQvT5tOaOMzqYKCP4jlVoZ3", + "KZYTzU36JbC7sJ5HZteJ2V2K5adhdbVzuWdGB4tY28AfxNLbmaP0+YPHY9pbYkCvYIp99h1PLm3OE3i1", + "N3OhW3DTwPdQPz/nKQX/lE5xl2IZagFa28KdunNbH1m0iduevDv98bzPzl/91/mLD6/aee6qOCjuwGDO", + "EqOz7Ew4l4l0K6ux2JpZau4ZTng38akrm8RwE+t0bsHjSkEgdv+3zZ7Wd+ORUXViVHTqI48Yn4ZntRzW", + "PXMvYE+jm6boJ8Tzm0HEdO68xws3rmIHhFYzYQHpu4glON6ydbzlfY/n9TG34J801jZxVDdt3mupeMbs", + "+hZOnfcxDSsIrKbLSvRouWWo5b0MtYLLHkPi0flF+wmt7/BG1vxGXgkQQ1+SqrKVI2fySrArKa6jQxZ1", + "KP3A4R0/LbLAu59Y9pOYfDh/GXU478Sl3h+y7307MEI/R1tnYOig24mBthJSfNrOhkSvZ70rb27ajkeW", + "3MqSAStGgBXBX/4BOXHr0eyopAU1mdfc53yJJTMB8cZraxlXlM+rT+l2y8CbSCjr9oEhO6sp743wQ1nv", + "7IilhpG8gv57kskc4y6ASNAVkCZFzn8x5GBcTmm8k7K8w4Yfx8CH7tyhDJaIXow7sIhTLsl21Xgqk+Xa", + "cj8Hi1jZlkcu0YFLlGjxCRhF0wHdO6+oRAW1sou0MKivHi2akkPwLBskmU4uWWgXNUARZ+E0FjLLZOUg", + "dqqtvokrPafQJ2+0TrQxwuZapRgL1cYVd7TIVbdgw9G9JSv7cYV7tPCccx/eVdkjp4OlB6gi09YN2TnK", + "is4sA9v0BoHUaAzQASNZFoz7o8iPRQgNA6O+Akf2GeapAkpGDw1yhackYAlZLKrZN3IOb29k6rGLn4B1", + "Ep6rgvY3GIzR4q9c1US6F7JFyTRDZ5KZGGV8qQsXnj3+Y9kn/LDvsxpMpRHDxtXFCH4jrNPkzbgYshco", + "pBrBHaQtQ70BZ1Mj7NyveMEhRs4/AmzjAuGyMsIWEAgnph42U6CXXTEAJ9zAwSxyt6z+FGxXdDZaCfKI", + "6CgL+tXelcu3YeIjm29l8wHPqnf/A7L5jSe0jc/X8YiCtZpqZcD3SKTlwtD4mCCzGQEFceNEGg3f0Yoc", + "fhlW7cUrvbbvkJ/d9q04UdK95jLbyjTDHZCg96zSDliiVNJJsK3SfD81pa1M/pHOttIZHNhoilv28GTW", + "dDy7EZl1Im9HSYpdZdqUeOj9vpzISWVOS/W6a/+EsIWZQqwQhnp20F3jJLav9kO4KjuRU6MMUqMtIwYC", + "/baknUfNtbiZ88I68jPJyscg6doc3It2yN5pNi0MiRarwsw1iBIkqDCtyPHK0/bnIOGmXXuk4610HA/+", + "kxFz60E9yLVZQ2xYYgFSablqTwdwgRIdAIYHAmDXwgiGlqwij25AtsCEp+DIvPQibMjAUCfI6s3bMOI9", + "Xr4fxJ2fLCuramAZfFUGeUWMIGhQ0yLuw4zn6BdF76CXaw8XI0KM7YpUHjRPzvDkEqB5UcW/A7wyR1qW", + "a6ncZ+UzjzxmZx7zSdnLXVhLoNWuyhPYvlU1CXP8UiCVRXgVO0ydlLrs7xpvaJrk9v0p65u1KlRzYaRO", + "ZVIpZha0QsE2fuWdh7pRYAnnnohwZRGPNLiVBjcewT2TYNPp7EaBuWrwNKG6nQOhEp2KlJ2++2tHBI3b", + "Nlk6sVVKz9Vs0xrf0Q11kmZiqwdJuM1AidboP8LZN4eHC8v+VUjhPN2R7UFpJtVgmmHiW3RV9kEKHTVR", + "fui70tuKv8Ajha1TWFVT+oC05fHOV1Pf+DRcR8CMeoVXrE/0cTL1IjIiFu42z4zg6RL2x+MeeoiB5Ehq", + "WXgDK81yI8EUEdbuQYwRRtWiLt1+n40Lg2lfQ/wY/DuGfY0pNm1shI82hw0YV1JrPGfjBmTEiMWcG3it", + "Z0uW67zIylzw3LGEW9E1K8c9EUvrET3eT1upx2Pow79CNx/SPftTJZjga9uZVQkw9FgNAdVm1W1w/eiE", + "MdqMml3U/bJ92oDKb16lpYQ7Onr14cPo5ft37169PD95/2704dXrH89eHTf7oPpJtwYohkVVogdjkkMX", + "K4Vw1ECtsJFWIx+MWuESzQP7lQ4/+KYQPlhRB+AIa+HR1YgfHxn9g9LXKuSWkirJilSwYx+O2mevhUvm", + "ffZf33/oM8qk1GdnbpkJOxfC9RlWCe6ztyKVvM9ea+hzLm7cObxs+6xC3X1wRDjTySV0e8uVnOIMT42Y", + "0hjv3VwYYpMLbcR2RWPlbGpY0S8RcqNflt/CDwSm8y0Tjs+ioNMcVPjw7Lc660fGu5Xx+kN7eI67di73", + "zGtDpPjWdDWhIckJpPEPobB+Nxp5z7wSZbjLvKsRiuvp8v22hEjEIYzk5wRk28rmTkKbIbRhUqUyIW56", + "TeJPYUV6LzzPeu6Wc2OBD+WUH5EYEiaCaNwuaUdGpNKIxG2iHGnLq8JWc/rqKeMsQBhuKWDWENpJPzJQ", + "bVLaIQR+LU2IQPjrq/M+O31/dt58weXaulFgP81nNtHpEq8WgHJw+uN5fKT1YXH8issMXO5arjJaWjO+", + "Uol/nmFMesWVIfTCYyjzGlc2G7fRFOKebu0+K5SETLOVTAYVM8/jDX33Gzqmzq2xsJLhrDGEbpe3zbWy", + "YofbmzowIxKBian9M/G1NFFh4emTGiL6w6F4mwF166PdEbHSL8BbCT+PMFDZhUdpoIM0QPv1KcSB1ZO5", + "Z3kAsLPxkPxJ1NC4ZKeYnm7qU7+xtydvX1Fqo08qEviZVWWCLnednlafVtlGaWYhF208Oi46AIxbRRcn", + "7MzB3C2yfkiNCh2xEsHjW/E3fxNhii1X2BZUimdNrViiU9GSHRIbtOgbGmFVsoK8/6HP3mnHXutCpfu3", + "vTD9SkpC3HgzQqbtl4aDSbvd9sVn4ollRqhUGGGiO11C/dgeV+yi9+K6z84Uz/+vi15wKtiHDDtZLVdL", + "7CydFdkUdmEJNym4NQ/Zh5CdPZSF8CP4GXgZq1+JtaAveLYxNZOF7mPC3mHI5jKG7Ng+8tSn2wxTGwP4", + "MQscm8lYZ7CrshQA3PV2Xj2Jx5u59WZGL2uPGw94KzeeyG5Guw0ZxcocQFUeHyINKoj/aROHwegwKmKC", + "Vv4p5drJfzufas/+BbPYcgDHevGSsoeAerqDfef4/dtah5AwFfYbAA7TCBFhoSjfMUHqfdF546IeCX4z", + "wad6MfKJZNA08uC0335K920SSfNR3LcGTkEeaYuQlJGRg42vV6OY31vGnc9ot0YCU9iPPjMi405e4RGv", + "3sfkUrantKNTw2yY+0P2oxVs7Cxlqbuuu/c0RD2t7H99ZVslkTcYTtM1GQUF37Qko3jqt8U/0pGlAdZU", + "XAmcMFcC08oFSHM5RT1VqTi8kraA8HHHJzKTbjlkryCvZbUDee6Rnu7pwI8Kizafjqk8+iR04yH1eK0H", + "5h8emwFHtuJyUiwKT5w13Np7+eZs36N2DNs9FQY3QCWCncuFyKQSkJ3x015iq8t7vL+64R5s2CfGvAex", + "LXkXy4aqdithszWEFsqZ5Zpf6J4vKHGI10y1g2W5MJgue78xyLa6q6NUOC4zu3tUcSCnysYx7pyRk8IJ", + "u4XycEnrtDfnKbj5griChTM3o3Rtk3zWqUSk5PWAKS0RSDA5oI9cn4kb0KtgwSXPH16+OWtGeRQXGgKR", + "q+PaRJug7JHWn9UeFuCHnQge8m/O9puv/jWc9NqmHbNkh4xZ+L0s7lHbopiUu/F1JJvqlTceXknvTdi6", + "Pcx7NZ5pZcF+LmXAdQchKMm3Xhdv4BllHfNiHuRwOOUSnjlvXp7+Vu+LJC+Z0eM90X5PJPlDXw/Vk7jn", + "ayFL8luyYY/TJUoTRt+VDfvkVI3cR6Yl+ED/b16elolJ5TQYQVoT9Y+amQ28vBBJGuB2yh6hdNrOMo/f", + "v2XQoIFrVsZp1lGTIqdl2h/wx64Tf+4vbEB8OyCThE8UFUPDzuVCqtngRZbp6wGZ8BvXC7TYnkaWG8Fb", + "JkR5upj9V8Hr90EJe5v7SxUirAeXwDS4zKdCh59ast4/7KVXnRrwMDq9B7j3cKAm4ezWl972m07z7a/8", + "8uW+qsjLQvfPocKLc3+8zrZcZ5o/+EO7dha/ceWcm9fQ+UtRzZWllLtRbLVSDCXWWKNf5BceLtAve8mN", + "kQJrqMSkM1OqOSoVcq0JlhxwzJcN8WXoQnmTqiZutbDPp+UOK7v1yCM284jysB6YUzSdy24Wvdvd6ipg", + "ObXYterTO3HNNld+YtxaOVM+xAhJYkvxp5wbEIvb13OKDdaXBAOEGuKVQexzH5xEM2go/GRbEnfvWtXp", + "3mo3fVrLaokDTt9b/STyiqxIXiUWdSaFzfaWUPoaDcEthrhYPmpFwc7m/EqwiXZzuueiH5Gt407N5BIt", + "0NKyCniyxGA5GfQfZicqFblQqS8sUY05fM44g3plmYiJ3YJvVEy0NsG7UrpP6ePxaKbZ9T74RKaacz55", + "nwu1weioxHUUcByfMB35CWyrxs4k2xA7GIbY0HNNHxD3Ea+pH5THgoeLDa7svJYKTNoyutQndIYphBKG", + "Vtdyrm6LJPXyUj2GtCI4RapA9AO5sim+FNKWKFsshLHMCAqfXZHTsAZYqPs0x5RLzgjumHQgq3HU5Eue", + "7RSLel9SWf2UH4WyzUTo+GREeP1Jie8WMhnOsllyOm/zsAIaxmAnT7pIDFoJilJRy12FjGZ3rnDfKXGd", + "LeNQfPIgkoeTLmtQ/1BUVOZ5D7SJUqm4bp1MoxgTQFVUZ+0w7s0LLOMOcPhFLqFiYiuHBqZDR7rgClWQ", + "Vb/Tv72tJYRNjbwKwoZv0mdzrtJKnDHVEByQPnPAc+nTYh8xIxKsDjVjmZyKZJlkoo+13n3ZQhSH/Oud", + "JuPrXMWEcdCiUt17KmfePjRk53NhUeHJFto6COT3GzCQKi2SmHEvNxqGZJZfiT4zAiuu++oq+7XF8hkm", + "jk1ICO/KdP2od2a8Dcf3yHrbWa/fLihdOQKUfkjm23Y0u2flRuKrpeReW0jMx83ehmKs4Ih9xHjEcKLh", + "JKiBNLwz/fPDPzhQ8nGoHcfC/Gyc6FSM/QlzW/4GPuBx6Cakv20WcOISppMRB8ajQZrujLeY5julKuNP", + "LIut+1g5KqzHsx38ho7zcQq+tOwpsZpXNyIB6Q9zb34ILGq8e/wJHGhD/Ek0v60zxtB6IdM0E9f8IaMs", + "NkVB1Pa7EgvRMR/YqdE3y1fGaLNByclVKpC93ywHGV8KE8IdmJ74orj1RBVDVntDwy9wCWgmKIn5XFs3", + "QHh00pbxOAzlpiCH7Lm2lbijQCUYwfBfA6rRO8AVDF5RAXuKADnClErP6P2xPmvbZ9owzr4+/Kqcn39a", + "PLExFDLXmUyW9GqmQVNhnVT+0nqjrwdXOisWImYSl7gQ2OqUzpKdOBsU4+jWM6iGb8DfIFcEg6z0GSt9", + "G0tXe0jG4+85L4LQFK0zgi+OaJFxeXiTYsQHHQ/W+yiDP0BuCwASnfkyRzKWHPYMR1r4xhXTuRtIxYyY", + "SkVWuRAQxq9XimTX72CWiikvMjeA9WbCoK4DdHY8+8Q5eVaw/PEybr+MYadGSIMPeQ03nMd9G7F0KhrL", + "lkduQIwG2h1tYimmHodZLeHYyLTqDLGF7cW60QuJPTFbA7THX9Gl2x5V+c0I2ZBI+7WPeI2OChVzDPSj", + "UpC41ygVSkKv3Giw7JvRJOPJZSatq30tlBE8mROI+NUIqlXY97GXI5dZtKDpwsVvYX9GUsFhZcIRiJtl", + "fWJGABYBuKZpFznxshJ8/JIqO/KsrfK1nrB4yF7Uz4f4Fzo1VApNJHqmgOCkZSYE3nHLCnUJoZuVKLsa", + "LGB+HKqPpKJeeL3hfHr93sYD6vV7jSdE3HDtiKqfK2dU/RwOCWSBtVMqPzYcE0Gpn1Ov39t0UPB2XTmp", + "6qfKUVU/188KfqENX+cw/d7NAHZ3cMUNCn+wzcflhn4Xd7ny8QPM8sfaJH1I7ylu8XHY4VO/Z9/VNjh8", + "/bG2v+Hrh3J7yZXnPLPnceX0KYRqn1S3FplIfVYf4s42TPlHv1sl8PDlWNnXcVPDx5fV9NlhOGRZP4bN", + "3S1enA6njHdGyQghNUvTniIayjZyJR3UcNgspBFxrYTc46AJunlFskRRi6rGpn2WzLnhiRPGMl04K1PB", + "/sEHvxwO/jz6mVQCifAhL6M+A9WIto59+3WlIxHxgt+8EWrm5r2jb78G46BzwsD8/98I79//7aHj2DfF", + "5t9b5PqWk9zpiRITrK7de3vfHD5DwfouYvX+rs8fRMG4ho0+HR9EnnlXy6ZMO+hjhhmZjVzAdLA2k38F", + "ixuRkICuC5cXjkknFihjVTpQKdEFz3NJmWvx/tkixsCsMPI/TC2Ul9/aC3IDhE4fozC9fMcXMKbzKlKt", + "RHeZah1s5261Naxue+3H3TTdIECPJt9+Df/eksJ3JZ1FhaLxIA6aeqxV+F00W15WJV8Sesvx+uVEN8i9", + "sBc+bdSOGiffizntcVF4Nklk5uGzD69O36w/rBrZ9H/yK05pKJgAVhzypnKWC2OlhbNi70Dm+Sc+DdHH", + "6kKdRzeHiUQ7sw3tfbUsmM6L05OoDRY30tk+fobZMWkvlM/8r031M3PCBMILiZEx4hrb0a04ZKfl5FBA", + "uFBYYkBeiWCYG8wyPeEZ41jKQBt7xJJMW3oZh0BFG1QXLOMOtHkiyy4UuZSQ5yt7XSgqkZCKJOOkTbGs", + "sKK054chsEhw3+f8kGp2oeBnBFofuzbAd4YnIkONeZE5OQjjgC7xipvxhQK2Ro64zAjH6bCl8Zb+QfwZ", + "l250Nphm+ppZseDKycQOCQ6T6kJV3FOEjWUYCLY/QPucTcOaqQwDNByQ20CmE55ZluoLpbSr7M54COdA", + "mXiNoNfPczYOvw9zo50Gghg6fYbUtLc/hiJ4F0rc5NpvJ1pRPQoC1cL5ZZLbIXsjbsC6SqeNqo0wCmHJ", + "hcqkugx6C1+6I0gzlaMjmYCj+QZgAVYhHkYcHF6oF6Fj5kctS1IZlgl+JbxWBiF44js//vvz6sleqITD", + "JlU6M+mw8qqTScVRSC5ybVxYFMmZzxHD0qXiC5lcqDG12dsfD9mrm9zQdRqSzEBHetm4wijYkcLpBXdk", + "jh6y9/6yshdK58RpnhPfgCKEudFgXWFKl7pm6MjGRuTZ8NpIJ/aGw+H+mGlzoeirWEiH7Jx+6eN0E62s", + "zoSXKEm/lujFBN2uUYm3EFAPX9oFSF9vqQIild0r5T46jZC4DqxClPM8ZBhDNQk5B/yJvZXf9S8U0rNn", + "OLSDlnGfiiykiE+5WGgVxTJ9FYov4PcnloBdKN9ggG6XOFb06A+cKYhwHltapDbh5QtUfrXw83MPUdRq", + "LwLcvvd+DVUP0ULr16kiq17VFVc1RsQqR1YktXl8e9hf08bfyEWxqEg3oYRFUCKxY+oN2//t4ZDEZujT", + "O/rq8BAuQEV/Pd0qtuEttPVutEW2+9UYMkVWb0FC87iyhkuxTRL0hMK0Fwkx0ZWPjyB68oQTlTxxlOdM", + "e723Nh69EbOVDl0pzpG69/o9FCM7KiCr8msZhMGN4Uv4O/indVFMihvHyqCPcmahJqk265rK+BIgbWXl", + "tqM8AP3Dw8MBrAc01QydoA1fBuiTYjrF3ZwIdy2EKvfMNiJxV1PVOupWLVSNKk9Sbq4rVeEzWwhrYVNk", + "VeaPeosGas+z5ofgjyfHz8ITcBk2SdzwxNHNO5jrDDcPkTUIS5iuNfizXqg4hdWy3cCmSaJAb3xZLCqV", + "vJ/DW1fNhA0XJFeeQSJngRjaPJOJdKECU30TvXLPUxEIYK2sLs9GpdC2WRGO0OKTGEnHbx4pxiMYIqoy", + "IeyF2ouzQlki0RmWCC5yMhyiLaec7AHgbTGbOwgVFjm9Ki/UeagA68GyjP8iybfSOBu5LcKpSAp+jrUd", + "qKCpdTy5bFCBwGcsX9UZk3zlrQZknwtvUxFVnibSWrGuhtmtutf6AUqk3cKMqw/B3d5sgH5KNHjToEjB", + "/sJK+QJuuxSu2L8EIWKY6dmBVFN9kIpJMcMGwphKg2tu1AFRcamLRWioCUhJe0bdGi1HIVnd1tcgNuz6", + "GAyr7q92W9vdM2GuZLI1Cx350aRoUZCJwJcUKiXETY6yIoh4J3hAdGNZp3PrTeRkF9ZmUKa2tvPCpfpa", + "7bNUo9gYBMCKW+T/+V//mySychQc1z+diEqzwEoGM3klBkUOqK6spBdSqrta98h36K7GvYbdfDTwtRr4", + "PDJ9gmRybedyC1cbAFH3tVlZRulp8+pGOuKTgLBkbY7vJHpwRrmtUKkwGd7Odd81E2uZeqLGtyXSRfBO", + "AYKk68wtSbsRHeNYPuf+WUszD5kbmFQkyu+hVBi1//vY9vTk2L8EyTLVREUIuam2foehh2yMRFvkY7YQ", + "XNlgcMSFp3gpk1+2xISqhqE9RKSMs7ngmZsvg4sAiTBDNvZ/B4Cc5UZcSV3YbBn71EaoM6/xjF+JUfOE", + "wknESpk+J59/HYXinHjKjsRWZ+AsnzNVFqxtQxQqXDuV1eQf4VhJj2U1vGYr1SdtDJ2ItETbCVcq7UOv", + "3/MramRqeaPr0cnxWg5E2oIhezEpk7s37Q0Mxop8vZpv4zaR+1imFXSNtTU5Kc9OT45bErz6DVR80WxQ", + "nxm+8BqV+jLCfnqfrcRLquCwtSicEwb+teZZNe5SQ7k6p76nik2sCC+a93rxg2x1pwUB8Y1UxY139mLv", + "378dXMosEybce6iZjIcgFVqfYMV/eztkdHOk5BkwPkjF1cHlws7GIeYB0IyrkhwQ9Irnbbg0FmKhzTIe", + "qFbV15aPv43ZKW0x8TCDciqwO1vksFFWpJ/4Rl7b7scLuf1Cxs0aab0YAUo85IXcfCy738cwz5XruL6I", + "eB03qV2sM1w2UeBP8zotiESmpO4LpDhkY6WVCNeFV/SvUctzNl6IRVK5lpKZ0UUeWnrlHrdsLqGyXJIX", + "VrgxO8B+2iy9bwYFD7378e2LA/owACd6MKbKLCvZs1Z+ypbpLA3ub98MD338eyqpCruAUWGB1pkiocTM", + "Y60XuLSjMcukWnEwgcViputFAncLzZM+lLNspNaFWIymRojR5WR9o18bIRgdWdgSqdgP8jvmvZCqyVBg", + "cn2WCiOvAneDz2OAfvQu+CF7VTjtwxPL3orF4ERNNUuLRT5kL6wtUH3PvsZxyFNK/iKG7Di454SM6UYk", + "GZcLVHckIIBYlL44swtQTpNPjn+iZ9zMBJ7ayGnHs9HlBG0LzDrAUTh+2nFa7DWnoVDwY3NuUrRZWCwH", + "7k9TTisrqZ8dp+o3OLO4QOur916oRnKvTq2BccEvdz6Kd7ifln148Zaw6A7H8TC7sE3y8ZdhEHyaYdCP", + "LYLIS71YNENjvOLtVb9u9xb8hj39Bn1DbL9yV9SatbiTW9t4pB+ExXcBs8LRZdM8K3/Me7bAeXOl1cBY", + "S1E19C+UbecLsYA/98EiQk65AC2fLy1aqDzWVMVDQPPConDXjETNG+x0PnLcXtomPM1ZKWSg7o5WObDC", + "DXCVfqiFrroIE8Za2nsASbHJK9JSDVXH5zAFemGMmY98foW69A1I6QPcoO1Ljo8B7tg3TChHLuOaTXSh", + "0nhrIbIjsu6igq/doDBPpHB+c0IwvlnXyjsjZzNhRtsIwLerPEW7kCJdJlylwMnGL09/PGLvQJKH/wGC", + "OIrOVuXd0nDuYY6dCSwiGtr2eAbGYWgWlauVwmN+3k4zqa70JQnMpWw9ZO+nLjgLoU3dsnF1JmO2VwHj", + "iaji3yTMPiZJSbhiqQQrQ/le8p0Smqb/Gfb0SiZOLobsbRf6b1R/r9aLru4d8bvIIrqKZIhQu0ljL2LQ", + "vz8Ryme1jarwFliTzbqf+1345jZK2HgHdGe69Vt0nSt1cDSjQ/Qnuv0sK6Gpm2JlqyV1KEB1zqMqljA7", + "VrOphYP3exIj3nv9HjjSCdPr9yY8uQTRVqUj3yY8jWMTO+dGpOXfWKuvUWYM6wghmy/pcSGFfYnxmrcK", + "kvMVRso40BDHYoVz6D4ED4gQGNr6bOC5S+a7BwmsrmXpV7JebukljcCszq5E0JswXbhELwQVX/L2NZ8B", + "+KHmkUlBOSB5Mj9IhcPk61G/F5w7AaEoVgCEBNTgQLH7ME+rM/GQk6QRgnF3L9OzPgOzTJ88QvdxVuuG", + "uLiPzujsDvMjAK3TezEDycS/1XwQMOMzLpV1tRBpsHbAeAW6gBFUsq322WnGl9cGq5/XXQn6zCZGCGXn", + "2tk+SzKZTzRcwOQN1q9GOpdA9WLBVRrKUF6JlWP0FT+dMPyhMexHSq0chwoa0b0kk8ml7bNLsQQzkcWF", + "6gz4+McYtvCAE/MOx3irH0R3g1DOaEgpnGYPidenmHkxElvYmGraHip6ulI+AVIQ0/xCCPlDMqoss9Wo", + "f6+BXAv2r1eh2osR/NW4/X64bjtF6u8P2dvmAP3nTE+ncPt7byOEQYGDuC8lxTzk6QkjdSoTNuFWfPv1", + "IDiAAWPMtXFVuh2y7+VsziiAc+vsca8ecObflSkbyGrSB+P+nHEMchjo6cC/8lDxhNPzxuFBULKT0h0Y", + "7McNIkrLjHa72F9WcYL02kEMrV7zNML6Xe4rjW3ydJC2VpvMiwwpWLtZtcAusyKjGxma0YkdkQ8WudxI", + "6/VTe/7evJ7rTETg+6VPZ/kRkMFrnGAsP7gl551sWW0rhUWJ02nvswjze3H+8vtKCeC22Vifpour4AiJ", + "p8XGv34c78NyOFN6oPPn9cmRHzAFxQe3QW+NO9e+ihvThqXS4j952fVKcppdny11wRYFVWlPcQrBJWgM", + "CwGHTzbGwx83u750QrI0r9/Uu6HZWVVARD0XJPD0F2m048EPx+LqXOvMeomIlD0NUiTVDhDpyPupNuQn", + "oB/gQBEzgPyCsF4fnqKwhux9eIdn0rp4sJVTVWKf3OeQBYkrYZZgmPH6KJoJmK2TrIhpsCp05MXkkDhC", + "sbCIIFJAB9J2GpFhaUGfPCuw8EKRO1jaZ9IxKxd5Fn1/0SLoK/xCclWJuJwanSOIuZzNhXUhzt1vG4pN", + "4xOVF26YSptDcNNbXfgqrvC6NGRYnBcLrjASLClM6SYPuIXpUD1pnUW2PPaaWe5ZdcItuaRER9zCqOBM", + "VydloNrdFTqIoriNdPLrjpWdEP026H1essoGfhoTKZytc7gK0oUzvhTLJtzDGSP6VbMHhFvOCnfEMpBw", + "rwX8t8zGwTPvOWF9LQyd9Vn5/OmzID34d9n+kP1EVTrGfkbjfukuUWGWwHescKHa5BGyTbSyBB7/HIyk", + "ZHcPvrSw8OmUHMJBYK7A2/NvnRj33Mc3db8q3+732dhWUAzTwwUBhkw8Ddc/cseJgC2noAQNMcZxef7Q", + "Qm0tmrBfFUsywQ2xJtd8yrSY8UIr6SAkMmIx5tMrszKQNLBPpntXwgDOPhdGPMcqKJm+tnXXf1SBoQ8H", + "r25Z/TZtsAn75XVNxtWqKQA32xtgcbtCeoW9SijWaeNl/l3AnFG3AKcjEd/6qlqXiBDv44PSi0LsjC8E", + "G3s0GZeBOpgoUC0Z6mZi+z7Ls8LWFSUVol9/W9YVA+EabDL9p/nOR7x6mcMRP0pyfwxJrkaVu5HGa22u", + "OWWO09N4/hW+6DTN2kd91XLsrCS8xSwZFSw6YsRk/A3BCpVRxCHtAMYAEUeeCyP6KOiQcYCr0LUyHoL2", + "lOxRlBBnD1ysQ3A56Lbi1eSBUIicz8XuvzlN6Fc1bIRuFaQDiQYaPqfYS8K5ygiEZlXkDqjiBcMo3jUR", + "unbZzpT+/vzNaZ0Nd0GRtV67oQl0P0AFkN++wPVu8X5sQDKJ3BMQsZSPy6NmMHod897XJIIh+56TqDyd", + "AmXvhUk6vrRMKhA0rsR+DPbZilu3psT6xbbbHh97wcHfqS30CIaTYDUin3BoL4bsvarsiGerIGyQzskh", + "xvraBEQPl0Lkljmd8uUTyyZizq+kNkdMbqcrAkDeO/68+0De8hLuT9zdcd+bH5v63A9BsfcgwvqHZtwq", + "yqQVNrEsnY6SJHyGnv6cMAGqLfPKTKWxLoCKmY9x++bcMulKYCr16AUg4t2fyWm0HkllHVeJ8M7JCT7f", + "AEwoP8GjPRZH8BcJDiNtjDil2X19+OcmBnJLYrs2sNlYO68ZmXxcoS0v3DPhGKItfALUCRvvK+OjjYNe", + "3bg5IC+FzWqgN3h9gC8ABuJOBLMRPEY3x80rNz8kWgu7F0547+vDP+93p9gQkBVkQvEqxJvtcmv6/Hpo", + "yJ34pInBgbZkJPg29n5T1nubkQe4T4u0dp4+vq0x+qXFuTyONiLQC45UHXyMD0ptsveSO4DLXAFmH/iM", + "rQeptJisFZ5oz2NdAA9Qhuh2H/sGdxR30pcfrphBV2aCxtkqpEarpnUi3xDlWe4lNCRsKDev9PTW+Sjs", + "P+UbMa76Af8pyCMPtrrfi5tgKUsIrD80lMViNM34zNL5wBZt9/sMaw5H2GSKfgkmHNTFdE0zsfL+K5xr", + "KnCKIBn9Sq4c9LxG3lHZp0xMXa/fQ7MZTBWTY3o7NbnHwh3ceE5ofWrJdXPubebYxlv0KqOCtQrzTfU8", + "mMYBIOBydCmWTWo/nVKiHvgZ1gdtgx4L7wiEWtEttYSOlY4/qliMsJetBWE/XaX0d5g5FVm6XAhPWLnw", + "fgth3HVPiJv1VfwXSzSaeHhZ2492LNcUnNUIabkO6b9vA2kFXW96ALoFScliervowhC9t/IE97d4aY6F", + "diGxwfZc3W0hey+9efhFaZa9hXtOMDJ73K2mceGW5dzg+4YTq/fKIZhKcK+l17Fn8ReqhJJTpbuYIQAj", + "Y9F0ik8u6g2bgE9NaOD75tzwhfDpsF75B7FW8XfqWUtcBROKejGff645sgBJeQE8Y9vjY51hQaiB4bNu", + "3Y8Nn632Xugr0a33W30lVnujPzCwiW2dT6HhD2JZ6Uvm8m0dz7BVtZtwI1KQb+0q3EtsWO2dCbH1jXcG", + "jTwKV2IQ1iNggnfSGobV7uHK+db2myCPkJiqWxm3pna2tZWHhfzckqRpFMh+0zLhnoCw5bg9TZG6jVRu", + "BHfiWBpUuy5vd3kuGvMsRUkjDdAZNGR7OkHfb1xln2GM1H98881+XTb+j2++QSGukp3ucPAfP//6Vf/r", + "j//WXOTKzRuCiSdWZ8BtyklAQxghwaWvDHIw/PftLo8wUuNmFtbpxU9i8vbl6bGYYgCyVjtuJnkJVqaU", + "uBEk5vvZZ+f7+ddnXzXvwKVUq333wCjw/0vSfL+xB3K5rZyqsipMY977SM6BNudJs0DttN7KDQggmC9D", + "jvi1jY5uiDSSX2GYth9m20G8DWvc4QwKk438LuLf7dLPQirvA/20wYBWXUwN5rZJw7bYkF1zx8nDrtRn", + "3fV0Kzj7cctqaJCmZRyLTDhxyt38dsxkCx0H6k1xmPukXpp4TKZ/u9k3+fierFWkKYuKRE1IWFGf5CJr", + "SV93EJse4NNryF5k+ZyrYiGMTJg2bL7M50IN2U9zEXU9/Zq5c300af1o6SqP5YNfXgz+fjj48+Dn//Fv", + "3WogH9MTr6Nmrr5dc7S/tgu14flM7coS0C3VrjGVychwJ7aD9K0ZtAbA3/8C3t2Yn0uBdk5O0fKYCicS", + "DLDYbxz0WqZuvn00bLZx/o1buyrlPcyjFkSTlgdtfMjSy7YxPlbAA7/61lvLt3UMTVZzFMWMSH4i8JgN", + "2j9Kme80AxmLcQjd9n7jDsu7xvRbh01nsjGHki8ThaFpZcGP1bkFtSNQrhG0QzCXRQxLtwut3fwvpMND", + "vwToE43R8KqFNUw4ULJWfkBkXxmm360lFXt6eFhLK/ZN48Lu8pKHJez0kG9mxCFfLHr96Cn7x02fLX+u", + "PptzLo2NZ+fmRhezuVcewyRmGAf1Fp5T/n3GuGOZ4NaxZyzX0jvCx5muTrkaZBhDkJ5V7+Jn66vZ+COd", + "ZQ2H4VwbHIjJtWeA+vjvxC+w4UmBhTwCNuMJX/MlLQTVrYJjsulMKsG9B3KuM29wQb6No6Eizo5yYUZW", + "zBDTiBxEPkIiGy0o86GcKV2vC1/LzFRpXlvSNzvSZSxUjfNaO8ETmsU6NWylz7V11jVFh+2qojglxC2a", + "Vy4MC/vlwz+RTbRPkL2l6bGntbluT+XXKjtEVXdXpfMK4E2qzVekLynd8u8tke6Kp3/H/Lnw1qT8uQeV", + "VLrQtgKbVDn4EU0MGCEAvz+BF8mTPnvik9Y+IQ3OE+/b8YRdcSPRWkPqmUWeiSN20ePXXDr0cRrOtNN7", + "T+bO5fbo4EBQm2GiF0/2n/uMoKzS3EmXib395xe95mxuNOPtOohyt175Hphx+gtMPNmAUXdKP9kaMbKG", + "UfebgjBMel2bQ7HyMTusj87Dye1R0cf93seYKq0pjR2FluJ8y6jC6sIa7C2YgK0dmA8a6gjt3tPi9XuO", + "T7oj+TmftKbSa0Yqb/b5Mc80T98WmZM5J0e4VW/kaCBqSOhEYkXZhjnNCgRJ1k/wOOCY8S7KBV2iOV9T", + "hgr4ESCi5d2fgh/Ju+AezPVCHFAgZ2nQswcXxeHhVwn0x3+JlYfTi8HfST8zHA1+/vVp/9k33zRraX6R", + "+QjtXmtT/LvMGTfJPKT05lJ576pC5RzKf5RJL8tZ73n+wL45hHS+z0lRHXJKgB/yVFg3/KfVar+aqGUi", + "FTfLrc/lOF0fENp09BUp7HAXlUgFEZrAvpaZgBwL60cs7SiVZjNtoByGPmhR9dcsMC10iiVdGpCRWwc6", + "SzmVPswb2tXS3aTciQH2blKvNd6fsCzShE6k81kL++yil5rrGzOA/7/oMW3YRW9grgdmAP9/0WuOKW7G", + "9e+4FbXEVHCA5FG3vhOdNajh7bXWD8KOR5OlEw30fOZDkvHnITtk08o0pLAdopFDZDnH92llsH7Ag8oZ", + "+k1vQycKO29JhPW6rOpKjjBlPPLu6MfRYUqk3fHwtmcZh7rtoe6GJc0mFJ8nCrLdV5QILz+8enH+qtfv", + "/fThBP/3+NWbV/iPD6/evXj7qnOK0VbB+weo7rLmtdl8vsfNJU5iqffQPfjfiOBfRdID+fNQ7ugyJQmP", + "SY14xhy/0UovMF7FgwlePCV078pDPlxjUHyTU702C7zstIpnjbIwTGUiMn3N9sgaSlMiM6l3sx2378O4", + "z4yYcZOiiyg6k2qWF5NMYq466cBZKMuEGZQf/Qagt+37s3N2EGd/4H8KmdZiWqvgXojlizAVlRWCjVfm", + "EvUq19IIZuc8F1gRTqax7qr3rPP5Sqrhy9LGDQ7JYBJfpP6JDWm6g/fMhdpSoyYW3d3sHVorRd0P8fij", + "ZA7TVDMxCmLo5nAb6vYy9CLZeRUohuDvBPAMemwC5n26doB2Rj0iuDL2q3NIUb0vBs906YsNq33h+Lp2", + "P45tIwSKkPE1HbcAoLaVerBl/0zPuvV+o2ehbyUKh5xhtkA4KdujY0ATHDTNd4Xyg1g2wSBr9MgK5zKR", + "dgdHpvsz6hYAg2PiCGKMOx7yG3kl/ibF9cpJl2A6n3eAtH7oPrCoAmrrMt9Sl+NKj1VoUslYxK8TMKie", + "TxXqVkHFbPU7wfsQem0BujO8dVjViPUuoMogxgAp1HmUabatCJiv43aSZmK1N3B/qWbdtsnDeUN96psU", + "AJqgNusCyWvL1mEEk2w3INQ6QAF1VMw/vRkChInW0qT73qlejLxrF+5QJ0DHeuE9zt5glxpEyujQkSUA", + "tDfYYYUX1EBBcojugKB1HUySd+md5PVemneaveb1SZc5Ljr0fhcbt8DYYR9LWE176fhkpHOhOoE655P3", + "2DaCWK3Ivw2Ib78i7VSLIu9UaLqSj6kbvjdVBuivpYjdNfvufZUHXL3gP/Z36VbZlo4dm5jQrl2rrGe3", + "vg1cdDcAJTvv2G8Ve7p2a6DIHbo2s8UdAJS8ZIdOK7S6Q88acewyzVU+u0vfJN+9z/oFcasDvQ2EZkF6", + "985Rft69a4Os3BFIi0S1W+91OXa3/h/E/XS/BftoEZ479q7dXV0Rrune68rdV967u3SrvFm6d1t97XTs", + "2fjs2rHvLYdu1Svcon9Vy7Fb90atS0cQjTLFbavzUHlgMHGhqrlBLWuwcty0QckrFdkcMG8dJfcdds35", + "Eg0pDV4+UaZZnwzL9Gw1ryrPIcScXFc2xditGFL0LFp3wejfrFgORQYaTLpyQca6ckbVeoJdLTItThfV", + "oZt0zG85yFOfyy10wSG5y705hQI4YVBrnFZiwlt9RXd0EG0zY7yrWDBoCn2q+cdJkfv2FAvV504Yhg4b", + "w3ql+mfe9yH8/XTb4bYaK1dOs5PjQxcDc3WFtIsi9UttRHc9nVrhGl0UT42+ktYX48Rm9a0rybFyXFTh", + "cMWXq88WglsMU66mAcXG5HqC2RTNJf5BTju8cHNtpCNHKz9+0Lf7IyIAIdgZIkelwnq/nWqBNBv4yg1p", + "PDZdWHHqg/CqnvH1s+kaHRhib24fFdgGoXM04FoQ1m5YeI9OrhiVdEf31lRSWHnNY+mbh3ZqhTnv5NR6", + "d09Pb9At3TolBtS7lV1stvFuQ8/SazZgGHP6VmjaFdJO6Hr7qI5UWDfaFqJVyWIQnA22BXf0e9Yk2wBT", + "haDOMFe2JA7Qr6yiaYe89uPVzAhrT6lEzW4udT/Nffjz396yS4XJzSa6cJgpyd/HkE8CB2CUc2DI3mnq", + "Q39DW5FN+z4pAmbpmGosOaELVy3ctSa+TWXmhNmc1kqsz0NScTojE1+jnCusjHCdSetq/s1+ZUZMCyts", + "mQILcw9c6yJLqfJeFRNsTIE400T15E/uM+bfLKm3XySWqtteEjautOkY3192Dryq79JfhUL56/0PsWb0", + "+ibry63M50SlIGILGzz6OqxIXzau5RSC33yAzu0Ity1C57g9Mify+2dfH+4ep3PcGp8zZCfTUpgtrLDV", + "XJ1lVUnqEi43I5ALeFHWe6Z8e9j/6rD/7Jv+08Ofm6eIW+tNWNvOa+rxmxDbpwgBxye8SWOOehDMS8kd", + "s/+gIwMlUWq+MIxYybhx9Gv76Ni09BGk4ojl+oNXk9NMKFtQvUue8pwibpW4DpWpShdkxAncy7ng6bTI", + "sOhF+SVrQc/WwKjj1oCoiDZfPTvsFh617pG9c5oCkD3TqgNz9AZfD6ayy3bOSBmhkBf6SqHe76cCb32P", + "KAQ5HXEksG5OhRm3blTY2GttPspLRhZfc5gaAqa2Mp+Q7aezM2N49dzSRR4F0uaK8ZC4ETUD2IaVFVHC", + "XJ9YKHHUr6V60qpxloXJ2oPxfvzwpg00Uiqlh9K52F72xr9ZEClq57hyQD93Qts3ciFdt3RJq67UBMA2", + "u8GHV3089JAsg9C+7N1RkbQ+8yYZe+eol35lHV03bOeLrLZV97baNY/m3dbxbqMqgTcxJnLXq6RWwxyL", + "cKDAekIEFH4MXTD/5oUKOdiyrFroH3sSAqP0xJ54rHmCP9k610BhyxTKIhx7oYJ0xrG1T4rS5BdPbvHf", + "tmRvqMcd7JhQmkqg+dAi1AxSzTOnyxrHMN3VymK4FeRfEipAT6RPaQoQG1O8EKlvTf0KHBfNfKFC25C9", + "RgKs7qW0bM5zzJQHz3NnWeWMuEovFN3h8EsoMI1LhTUmmbYipQTUeAIV0NJVAPusyNUUuhdqzlOmNM6R", + "wqQa87zdknE7PtnKQUvAkX82E81KupnbaUm2xCf7VlHFQLW8lpaCklf0JlU5FGS6wz615QZWnuekkN4c", + "ArlB6RHzpiy2aT8g+XmObzALm+O1L92VIc3jhxAcgG6Xi4nOcHAcaMhewfsMhmB2ji+2iWC80raS4n+y", + "ZDepdlpnF2rPCsH+6+lTXMtyATeTTzUB9R19nJ+NYSsXvQ8Yu3XRg8gINF3TP186k9G/XmT+0+tvLnrD", + "C4o5IfYnLYUnJzhBnlkNs0z0YhIelT7tDMH7Hy4EXOBfONr/OOcTBPujpXkTLwR2khcqcUXUqNXBhuol", + "HtZCqsLWoENmawT8gmXSCfAaJ2U9vgRgqjxJBOZex9zYjGeSUyFYD2Fw0WOYFt0sUOWKfK4+3ko9gC2I", + "sEKYiBXNlKgTYS3cXT5N447EGOJJN166NMi5LzyOyl5uKSPJRpXnqxgy2KbvbK6sJ26kGzVHup6G2oI3", + "kiIbhy2VbttTS1LM32hDCe/32MLjqs/ZiSF8ZYZRX8Cbs38V2vF+TNApjNEGy0rwUGMUFJHAJugOy2Uu", + "Aov3qv/UcKlYCk83qURbCHkqjBlNvv26OR6lUmKImrJJAQUmh+1hkV2BwUXWCqwpvnVzWsgKyt5b1DSP", + "BUjsUsG7XOnCZg31friZ1QPw/9FQT44gcTMrFmI18cFWBs7tyGhdD59vXkah6vVLQf6Driw38kpmYiZa", + "nvHcwlumIdhpFST3KZChNYCCJCqgjQk6k7XFxKiCZkoOWeDtXGQx1T+cgylUI6Il101SmTaXQAulIX2P", + "V2Of9j1EH01Cg0jVtIDtqmihrtrRq+E445n9+nH1wF6pK2m0QntMjIiHuWI6X22qWz/sNWD+Wkz6TmHo", + "fRwDfqYUFDm/VkP2DvLiaMN+EUaXSZXJfOz5CSQeTkRGyS2AUeW2hiVYjv45o/KOZWlkDHLC8uWFuZJX", + "dSvSn589++qr/3h2+NW3damqBcPaw+EJ37byiTvFwvMqV4gYFTd6yDy/l/6RUo1Oj2nZw275iHFk+w0J", + "4X+j9+HjnXe/d14btoJL0u1utTOscUTsREUfkAo7qeMZlUSq3TK981cf3vY2w61GgvrmP5y8edPr907e", + "nff6ve9/PN0eAOrH3kC0H1DXftvrnUq4s9Pz/x5MKMa+dRsSn1dvRVkjrpkjaRWuqaxYKLstrUy/B8/w", + "LbCgyY75aRBqnya6YcfOgJ1XN6xTcccGWQpc4VZkHiqJLkbOLbeLJS98ayBbK4pUD+Lq907P/3t/9aYj", + "0wVKBjGq7UqQiNAivzQfGriYSsDUlYPzRVIqi0DPl9WsRjsc6dpI0Oz2w6yzg5/XzvUW99dJxbuQTM6c", + "Lv1N9NBY0Pz9WTysk+Pm+8H/3qhTAq9JYQbcAt2LlMnSSa5B6omWi6KQaTMjRiNHo6nkPDj9ldqxMHPf", + "bQe/wlZSc9wVdteqWpWiSIUlqaKdK+XFKE8a1vfKOrnAUPeXpz+yAp0vc2ESoRzo+8plKEyvteXufxXu", + "/KA8DXsFxhjoR9u1TSaD59qiLVlEOWMTytr78q80+5hH4pZix5lexNLd19xXlguFuVqkgkYb9WmJJ66W", + "8MAb/3q0laI54b8rdRsjQ8qNWytFNqJeKtXtrsVj7jjw2msjyZVohTgon5HEQpjrUil3vJPok1ZH2f7c", + "j3B/3rrmO0nwMB2ffdICuPUVer/HNjQu09Vhg+AmOeyY9DMuxQhepirZRbo7exXSJzAjciOsULiilWeF", + "Nmslv+96mtExtUQWWEWjkCya3c7f1Ke0llMECKuRrDoxr8jqCbgETS10vOi1MBV0Sm1S0vN/YYYxWyyi", + "gx0Za1ALgrvh68u+AK0u2p28szMckEw7uco+FFuDU2mChI5y9HMw5uBSknmhLuuFYeDd0gsPp8/J6NZb", + "H/0a5xmEDa8P6cUNzeRC+hhXbJCg4kKkZQuKe21a2CllSkHivJtecaLTpbcqIMhQTpGwU3nWu5o8pkEK", + "8BUS2zLzlKU4o3kJ9Y7plbTaLI989V1wOgyj+zoc5PNnsKQqSmUrpSZr7uIZFdGnBKW2Ui9yyE6Q2tAa", + "iY7/MGChaMAEk5AjqVv0xSDfJGlZuADIolGph2Q15SQjn0sfNV3PdkE5PJzRWSUimj76er4xxLhXq9Qf", + "k6iUaREa0QAoo0GurOcRCqyYCuojgXUsTIgnRyTZJfFSRVbefpm2FoSg0AhhmhOvgdHOzrsJ1GVsQujV", + "Jk5vVRXTS2H9s42BHJXf6+KbcbvOdotj1JbJNpUwqM6zac/LgM8PYrZ7xYg2F83v8XsZkzLzOsANKdRb", + "nPZ+gs87AeoYh0GwwAlL54NMTOGWNkrcKTJjB5iNzu9hF/phY7cd2W38Ekw86C0Vc+qI0XgN1uvq7OqX", + "nzk+utnsHvG9NvIXrbBqC47F+EIXINpQQM6V8N8tQxeePlNixmvf4RyaJSyawZYE8n+DGScdxgd/jYbh", + "i7x58LvEnsTKPt3tdduogjvvtl+WH6oPtTtR7Ayyc0DIWk2mHbmWTFOhtuS3RfgVTxPfaas7vG/XMm2I", + "hz0VZiExksHebv5oyWpW4eJPPmmjYX+t6cF2zQ7aUCzp26+/3t+tNpK+VsI0zxV/QqNtmO+PLfPtkkmS", + "khrm5d6SUxT53/jisrcs2bIhs2e1yNduYvgpL6yoZptGKdjmIgHaT6PpbEfbW9WfDKt7NZneqnm9Dw83", + "O4ytqkIqgzduiOPGvbY/QfTHfVbhiXXCUG0D0IfNmbmBcOWV2G4BiNTu4bHYN1t2CHtpjcXCHbhj0PbU", + "8IVoDlL5UMq2oREc8TQHir0SxshU2PBs8juwXz3zZ4fbzAmNyvXwdltTi+NTaSV020dYOx0cNGUl+bjG", + "bS8jyZlQqS9ZsWedzvs+8BwuVHi+9H3FoH16N0J8F/RaYJpvLPSoQj3pCNPeW7WiikJ+p2D0Bb8JtHii", + "zoj22t0hyqGrJvMQLbv5YDee5YLfYPZh+Ys4UW+/a58B5n2wPmfy2+86ItNq8ZinLWFXsLoXRSr1drp8", + "6St1c2hOBXgwdvBKpkIP2QeiQVvVDoCIxK8E+ixiLx92CfhyWmRWvPBfk0vhqt4OewAE0+oyKxz4Rbh5", + "peL6vscWXyO7FvUuLc1ogFWvOxaqPnM6vytr0CYRAGf7Tp4sFiKV3IFuBAirjGc0PBHTImN2XjggM59U", + "eIHBb6iNxkLuiTamQIdQXCriSLNa7w5ZJojkP03pMRgrv5fSY2V2YXUlMp2LW0QOCN+VRZsjup1Uiymw", + "lczI69JA1GVvLNJZz0+NBVD/1WpcGiy00k4rmUTvbkaWunKmPDHa2lgfH5249LRClEMG/svo7QfJ7Ac4", + "8uDk2McoFgsRFdJe6esvCGmpEhPp3dbU1Dv4JMAag7L/541n2JaGZiUxN2WpuJZGDDJxJTL6SsmkS+dp", + "71TlTy7ebsiNQmJvrVZWP2QvzEQ6w03Ir+0lb4v9fLLuMjU1MMiUgFF4R8glvj2DeL8p9TfOWJgBDM0I", + "bViqE3QNFWmI7Rl7/eC/+5zaBytfjhFuxcO+z9YThzfGtnRVIn8pqtjyNP/z7P27qIltOqpMWr/Fm3Op", + "4xERnLWjq5egbjoUOlPY+7sqgzeYg4QLCOdv5mj0IhsdFrgGQ1EEgpFS0ueGAekDjSPNl4xrEKB+VPKG", + "xSRK9NgB1rRS06jcKC8pQhd2Xbk9OtrEPo0qPJ79WfACuIUPR8m8gsTT8qDEzFptUb08ywZJppPLmLTH", + "K3Uqm1mDj+frQVL+FhcqoZUzkjbk8PeiWPfSJkms9tkBd+NG+hqhQK8GZYARUV9TyO6i8KXeVGlORyfJ", + "sj4Bj/n/2UKi2DIRCb7o4aUDbuMTMZc+5JUUKLZYLMqLM3Qn9l7fQFJXwBOGGWmBoBPQObKF4N4E5m9M", + "8OQV3ryO6cjYlFsyBPMQU0wNjODpc6wYIXhKRecJmtIOLX/gSzMRQrFMW5S3rvkSI/+srySBV4dPmGFE", + "ro1j0j1nfBIacN8GOqXcBV0l0nwlJ4jSrgwT5RY9uocbL/rmQn63k1+8iJJx69ZEK3asBc0PVu0qJ9Vw", + "NrvOeM0jHID2aB2NHGClrPrOuvW7FUYFzbMz+lLYxmKGjT6Dzed0q6xHIe6gnEfI+lTJfgT3yQ068mcc", + "qm7UWL0pBNsLOLYI+a4O0lDWdn/I4LaC2yfkmbhQPmYQGDmMRaHKiumg+6iMV9sptoff/nII++KTMu0P", + "L1Q1AY24QXKEHcK7/lqbdGAxiA49HHxkTFy5VM7wAbSiAe2FAk6hONV7QQmHfs6B71iSTWludM/CXDYc", + "XVvUra/5v2pZvsHNgvZBeJ1rDHRc5IUTpolTu2WuoVyJSsRmXDwVZpDMOUhswsAYmkn1T5LOMKXKc+Cy", + "jl8KknxR2kGhEvcMvKexTnuJBOxwyN6DwZ8uItu0A2zPykwoly1r+3ShymaIG/u0VVHncTh82oj1wZlx", + "9ZKHDW0icap8TlXQoer6WRTKPknN/k119DdXw29fzIm60pSi825hmkHE14VL9EKMvLdGo/wt45ijFmN9", + "56wQHcL6Vtd5qzSOwhhtRoHSbrEichNqkoadKSzV/pqJQW40KG5C/cdQbslSoT5nBEfNLOhetBPKSQ4q", + "B4jtTTDe37tZem/UokFYwmKnUCvDFhNvePGCBWdKqwEvnMafHEtFknFDghXaAjGPqs5B2AL5qXB491Jr", + "L5CXTz0I0ibXiIq3FO5jr980i+3hHfVdjkvcfOiXt0yZiDvZ3qfpSgSWQCfQp0cRPZaeQqlF7++HT0sr", + "jIRo7Cjcbw/IqxSJLTW52+0CcDeOUOb+tZog9emzP+2WIDXC6ft9ad9z2IQdt7rb27YEX3nZ+sG69Xsr", + "HMe3/8rOtHhrToVBQRSMJoB6lyQgS3Bh54mjXF1GzKR1/p0GfmsTAfwPKPGKZzINyYJs1M2wij4heL6i", + "RQbLjKYd3qDlYcA/e1E5sPlQXiilHc5z1xAD6F1ypomY8yupMRkBmoCimegfb1+eMhTHvFGUiPXnvVB+", + "eaFTkflazrnRTic6G0p9UGt+8Ozw2TeDp08Hz745IJ3EAcC0/zf8d59kKhyNlsZW1lbRZZUDX4vJgidz", + "qUQmuAGv++FMunkxgdHhxyQ/+L9TmbhUTAcwDi8BgjBxPhdW+OVyI1gRuTYFZFN9u5g8cbL06rsmxVnJ", + "YJv90OCdiW8gYO7fS9XSLBVUS1BeifZGMhULuija2+hcqJ+0ydL2JkbwFGSz9hZxQ3yRjLaWHzei6Gvj", + "UxztanhtDA96G96UeEdKlRjB8W3eZBAVi4nAHNcIr+q6E1QmKzS7PcZrY3oxGgaSjMXcTFPDqTB9Rb+1", + "mRPEtdNgm+k/cr/diZ8tfF821WDMtSW5489NJPcgtP4Bua0wIm0ddydSNxEeDji8UCR3nZE6HRO8hZek", + "NpTACOYUfJBhro00Xue13a6nKoNejfFvlDnjRLeJKWtYEfLztYipt4SKudi3y+w+HV51ffXVbMbjWz26", + "6MC6ncXa++5jnyite/jrKkv7uJbM41Wd33glXcBGRHrALgxeBy/iUi9Pnqpgy0J0rHQiLXzd5/hjKBEW", + "zqZF8ww/x4xctRFa/LtmYtQ1f+LKjHdheFiH/o7cnRK+3QdH35LfrExtRq5hFS7xxPqDCr5efPI8LDuy", + "llLGIsbStB3XUqX6+s47EpZO4O5hc1ZovJxmPMEaIlYwKBDXZqq3nfMs1wkfd7JzFsdyvK2Zrwhw46SN", + "dOJlJvOJ5ia93etzs06vFmoZqpCHAbe/H5rVWx/xTqFADs8tet4IfUKWhBenJ71+70oYS9M5HD4dHgYR", + "kueyd9T7ang4/MrX4MaFHIRkxAfTjM+Cu2DS4C/4VpiZwCyT2JLYhLiR1lGGXGH7rMhT7gRbAdqQzhiq", + "UdsiFwZDltI+iRKgdADZXWa4c7H1sbhCHGMXPTTtgtRw0cMCMplUAuWACconMfejwZRzMLOQdxvFADhD", + "8iBL0WPUJfMwymtcPx2FsO47nS5JgYYCc7TqecHonz40zcareEXsDbu5wobCkmgPnWYL3NY9cAbus39c", + "9AaDS6ntJaXDGwx8Zp7BLC8uej/v3z4THE2oGa3Kdv5KCinPcZxnh4cNrs04fzpvemXFpfnDFmnN7wYm", + "+PXhYRuFxxEPvuOBJimJ7sd+75su/bBqm+KZ7wUqtmKx4GYJWjzCyzjFjBcqmftDgMn7Off6vZtBtKkO", + "Sh+K0s8BAJf4jXn6pdhON4UVprw/4kQETDo30saU/6WTYIwYnPD48xDwrn+hthIU252eLtSuBPVSGMel", + "YmEX2IIrPqMH9qX3j1FTw0NVfY/n7NWNE8r6qoDgkdO/UJj/f2AE6S4DRFpHhB8QFe/Jl8enB6GGiVb7", + "+MyfgF1dpBcKlR5hL7fS/mk4xtuTf3c1ZJfDH7IfQhZS/xMaCy7Uns916a0yL7W+lML6fbzokUfvFc8K", + "b9ipFJOgr8MLdSYEC88xxGRRzmQ403qWiYjYByQrxXT84TttqaBcn7D+77iVyYvCzd9fCfO9c/krzO2S", + "hj1onDCKKtDY/pjPDE+Fjb38tfuW37yMfkX21JcXhbzy/d6pzovcQt6Za5G+1uZHA6LEP3phbX52w0Qv", + "ej9/vC/OF3Dli2V+q2gHa7kLDyxycKAaiEDUxAy1bbKmYFN0ltCGLbQRLHZjv8iccZPM5ZWfkLhxBhS5", + "bi4WrFAppDo+mOuFOCDmclAOeXBRHB5+lQCR4L+gzhFGTUG+EZVTMqiyOXn7gXIOT1BW3HqBBC8UPBeC", + "b6/fF2B9YQ/R+yJD6pKGGWCxCxGuE6BZYSz5oAH1TAvkfQgF2SbxFEY74ydD7j2Um9LLVDlKdSERAYyk", + "QMAsC1RTEQp0g7tQr8rV+dcqonYDl7FOZllDiYlwY8CcwxUBVw1PpRLW7iRa0UmXc9rIWSnwgBt3AOg1", + "CFqwkrluehPEMWjItwFWNwJ/2pRgIm4koXZQIwd8+czUjCRUnVCNnhqw/e4UPeAqHQT+cHfq7jeQNutK", + "2f0LZYWLRFeOQOQn1S2eHxH3L9QnfH6s0sgLlX6IPPgLppZ+w3VIWxx3Eg1qPF3+FkhpC/WwPfCpk7nd", + "r96ScYmdicu79RxMwjOhmYhehczEimHuBpFS/nM9jZ5BjPywLYWUgAopE/D4D3UR/K/+IoIpgERcGq2y", + "pb++YqJNxcRNkhUQqsdAgsYU5Ur7wDLU/bKIu5YlXJG7VCb4lcC7JwRdUpZY789EBRAEbH2sVhKOhslY", + "GYs8GWlRvoQD2vQk4klhMbAGLqVkziUSVSooHQ1clKVLImZXo8p9MNqlWKLCJWxXWd8i50uA4p3cmdGF", + "SgfOyJzB60MllMUFq5fBLK9kWvDMg2ki5O/wLeFP50Vwgb/tS2KjE+76SDF/4y3lWQQZEmL/hsTWSAgM", + "KaaRAKo43U6IIVqhTocJlJQfIbpUqbF+slh3Ht0bH+hAywHueo5vCfGJiiLdf9YjPJPo+A1nSGSJex7m", + "2OL0uOshklb1AK6T9nP8IHj6sqKBbdrO+zpPGsQL+XScKwqA0Ib5IfEuXKO8O28/LJrcZKMLSIMy+pb7", + "jTru9g2vK9kfiHiaNfm3JSDU3ocyyE6Xm/Tb4Yk/kWEhuA7fx4FS6ePWc4yJQR7oCNcSj3Q/vXsZv1Ig", + "tIlScWoMCnhPZCbdMip9fjMo8b1MfWkFfV0vZr0THoAb//pluBoMIixpZjB9TmDqk8I5rfrRFSNblmoE", + "DvMyjrzoMeBOUSljjELH+c7klaAawV6+zgS3gpy66LO0jEch+B83fbb8uZoVJ+fSNL6vjkNowgPhboR/", + "V84DgH4jVzZOpawjTsfEmc/ashNKgSkeoYxyX+q9nc38VbhaUfiHvKKbq883Uz+a2mkr4iLuY5v/KlzN", + "mk9DEOnGke5FQgJq2yblxur1D0Qoa9Xx7ybj+m2ClX1eYnkbirLXji/czDHxUMmr7L0caW6EtZDpbAur", + "FnZlIhhZNaXKhdFxLqZFIpNTmZ+rUjPuQjVVgvNVEHEdRsyFIv3Besm5PrNCXCg3p/Jr62XjGHelRWom", + "3XBqhEiFvXQ6H2ozO7iB/6Cb4sHN06f0jzzjUh0QsFRMh3O6Mnyc9FwrbWw1Fs/7OIX1WlZYn/Qn8VuB", + "6Z2s10fSMem00Xjo6xg+EL2slkm8LbnggSK2/JYkFlxdTeuGeHkflFFJNtDK7M75pShzMT6UWLuWUvKj", + "P8SNlxqG+x7klAK1HCnGxU7QotXgQbR2d5UToBjiz3riMQERKw8oOB/e9bx1lrWzQcqmya58xknKaHyg", + "gTuELJjwzVUE0Qqzrou0NY1prZynl1Vr6SxJ/SoVWAlgaOZkcmnZntLOp1r1ybdKFIuRG5g16Iqb5XPm", + "CtR3LjA8tppAGQNhMblSuRSy/fu1MszFSdMIfif9WgJoH8eJJpiacngvwkB5vRzAe3yjPo4iQEPGlsBM", + "xyHglzQ9g4ERueCOvWODAUXSHjIy6NCrAf8dEpisvDxDUssHos9KmtXb8lePXr8RZRtNphRH6Hi4Y/x+", + "JcqQsKOFvfow+wc6uNUo/jspeyh0/DdzMcLaSLlzp2PyCUDauWJZlDhY/xj8h3KMLKNnMZB6yPRVT9kg", + "FV7fIU5SpMwf9fBCnRo9lRkwT6WVWORuWXHmip+8YdZ7eUQDoiVbdjQfWqfzA5wVpS27UFRNokwoN2TH", + "0uYZX2LWOJoztATXZfrkp4Z5B5cYFIiJCi7UOI48AjvgCJ2/xWz5lxxjC0dJmo8xf5hzMGnsCk5nwe6O", + "mVmAQa74lfgUH9Vy6jltSuOeaLOyLUP2KrpsDLzLRnUIcDc6Pr1QlWlMKTYcw+szjN6HicNWBnMlzKVa", + "Tj4cGOY4+FchzBJwgC+EE4ZJe6FCAP9kyXSWCkNihA15R4xw3MMr88PRUOEaG16oiGnjeChjlkqb+xuE", + "s4mwbiCmU21qji3k9FLHOtIOeWeUcnd9pHIZAERpob7jhgjI+vi/aoXlcXhsjCmfDuMK1+/YUhcs1RdK", + "aceUgHw7LxzLBLcOt9M/FdATDppj2PcknnlMpriagMY6kVtf0x8eQtKSdfeoggjlGfdxj1Bj5gkFL2KP", + "RcGNgs4uJkOjTDAXyhmubHjSHDE5BeUZh+2M3pMwG8QZGJWbTApT4YIMk0OK6VQkLmQwXHCkeXrDUT6O", + "RJROUBiZ/uzmxtt6c6NzPuMO3QRPkZooik+D4GEFYJoTbFw6avz7mJKyHfiFj9GW7ZNMxLykHsPAVDub", + "CRB9LxTtLHGuyJfqTKvR/zPwmJehEXrFewqwGEHU4uhQpf/AMzwaacy+zMZ+ouNQax0kLlYoeIV6J9E1", + "akH8jbwKWLq3dZdoMWTjKmvyfMkSY6pyA22YyORMTrJmjwbY6inubyOroBIKXtTE2K/eUQ95RC+EpvVa", + "eCcmfAv3eFlgsnQtjMW14pdySU0ZBn6+kyfMSpAZHLkYBYprcGA6fz34k08vV3fIZQues//zv/43MU8r", + "Flw5mWCh5NMX5y+/Z+su4c11jX2rUUt8QGUG5KbKxr9ekO/+Re+oGh7w88dxxwnRpdI0G09sXaaxAI6N", + "En6zxgJ+9jexl4vGbA9rLxxQ5YUD4ZJhSP9KdfZDtpl1sqZ8O8T34GdMohtzoHm+E6WEMg1p3Re3zDXM", + "tEpEeOf5aqYNNaeqDqxtxA+eQGhyCLPHeHDwfrkSVVoFOvHLKNMmbXSs26/VC6+jbggIreZYfTH4O2Wk", + "GY4GP//6tP/sm2+a89L8IvMRXBzdVAn1sJHY11N+U0DVamUEf0+N/D21vpuOm+Ev1oWLrMrtSKCwuL3j", + "mksgRlD4pJ00QDCf2yHzl0x0H6bc9UZrx4RyRla94X1n+I89CLXEw0vYigz671HJbPQfZ2Pvu35wGpNO", + "2PE+pWMdw77lo5IkxlQWCZkoHbf3sAqLRedcqZKsSIUF0QIbXBue58KwynxqGdHajqvfi5JVAxl/eBON", + "xV64EiuildgiKQVBqc8yTEYCRJVwojXHnh1+/ScqjNcvSQ8OMMEIFhIVkUf4A6BZTDLRUmq5vpcbni5l", + "9rmwg2gqLPtSImQjc3J+WMHJiBV7ILnEEiM+XBJIFfZtv1MN59+UwbouMRO/fF4q+yMWxPw/tefv8C7v", + "368P/7y9H0wwk8naq/l+nG9WZbrwym7dJxGeTsTLY6BSyvI5t2Llgf6C3sf4eCnfxqgS82/mutSfZ4Vd", + "23uybnbyGa3czzG4rCGKyd+7D2WMWL/aPzXO+9FDxtH14/zRe2X4Dasfw2fD6TuH7DQvpyPyTO1BYgSU", + "pA53CiFS0eTmiA1jRZCH8nWsj7ITMj3dVMCE1vkb0uTRShnHcOm0sq1dT47qc3Q4uWNs+NAnR6Occje/", + "s6tLPDRaYno36vx6e7932r0GB+979JHBmTN+l5MN8viGQ31NYvdv+zxhkr+Ho/RvnM6n6CvpAIWOfpFY", + "OmTWVFv4AwYCWcbZ309OWXy1VF474RETiz2UBasCeg3XXdv8+MfS/F3m21RXsa5XhEjSstPxVQJCTFhU", + "m87HO4HVsaSq8NlaCuznnYQEv693soPDroc1xpopiHrVDf4SMdcfVpUNMR4QzS/51hhtXdoBpcM7fs9x", + "U3nML4LLCcrUAGt/I+ZfqA2oz/5uXcr0dCqMZVbOFCYnwxzDPjV7GNDL4hcqFdVP8G9u6DULQYikPIIU", + "ZOIKZjIRbhUKElqzS2mF7mCPvhTC668lIqksF/2ihux7OZsLQ3/ZkACf2QVmuC1VK5BWFhJHM3ANFWDl", + "GdBJWHfE/iecNoFgT/vM50KFg4XaUP/zq8PDwTeHh+ztdwd2Hzp6FXG941d9NuEZV4lIqecBngDb+59P", + "v6n0pYOrd/2Pvv/MQpdvDgd/qnVam+bTPn6NPZ4dDr6OPVpOpIItIwTTovgO/yoV336rev3KbzRl/Id1", + "rVrw7nzTU++dGOf5io7uD8I8V1STOzBQVC+FBE2ecdaZB8hKWIq7K9dAXuE3HsAzbepCwW/hlt5N8ox7", + "0IBy8BuTipD1zg/3z4JY4NddWQHjE3IAWDu9HRArk9bhe8G2YtYbabEQrr3lhfRl4lK56gZkKh+aGaXT", + "+AKxCRZIdgoK9b4N9oCXfOtDExzYT8szfgi///t4ZAKcinLnCzxJXAEa+NEueDeGYARPowKhkR9A5KdX", + "H3RjBzidIJoC/N8KR9CJE25A1ZnuLNPgBdMYa/uFoROcL6uZQHdAHyvoOhlVSnu3coj1CusPFwjaUsr9", + "1om6SlAhbPMLPOoz4daZRbUq+wFWfbdzme+AA2SZbncRfUFpxEsDts8yok3pjUUXk492MmKhPR+hkORh", + "S7qbIKbcm1dPlIxaXCdSYd1oS717aCOVN9p5LuiTuHrRu0ul+37vtl4WXvtYTnW7m0UDhNum93zarNat", + "pL/6wtllQ6KfqUfD3QgmqHo35r/iqGYiT81KFjvp3fqCc8KKwmsFA9vIh7S990Y8uxJHyYGcjiuDlUTv", + "Ft2NUu7JJ2kTxdwS9f8u83reN7/M3w0Z8GouthUUvQVFeGXTFpLYVVXcRjkXajvpbFcZ1zTEF2pFRdye", + "q83rfO+N/Fo95M7nIm5Z2K1wDXXwCftsZN3swdVWpfBddycunwHfzw3mvId1LQGdBgNsMyj77Q93Kx5a", + "avsegKG88Hv4O2cqq+h6a8ZyvZogb+VF4rhxr+1P2OqB3iKVIXb3UrllxnhcdmPhiB+VhIpnDWUiSrq9", + "9tvRyVtxtSC1S+bsvtMWfyZ0pMVU1fo+caCa7STv4X4e/BoO5SOdSiYo59UqRuq8RMgVhQsqUbzWxOtQ", + "4klv0qNsV5t83VRbnI6SnOG/8KOEbSW8Rg/qW6nKVo/xoKxR3qg4O0NF02v76sorVT7Zaa4qwZy4cTTb", + "Ru3XNhvLGT7CcRmN6QHOXoWS53paebX7aO5evzcXPMVV/9r7r8HZ2auBT2g3OG+s1/9WpJL7YsZTBuCx", + "HhmBY3urjHC/Zi8NttHVVk2m0I9fIiLjRq/tss+QFVh3Z5w2cpsDGeaJ66IAPq4IgXxNGfwJ/RHelxXB", + "M8EWOhVsTyeOZ4z69BkWPvj266/3h6xal/zbr79um+aCig83Tusfh4P/+PnXr/pfN4XMbI46u0f19C01", + "MzFL4Zd+WaOKDe7n4C+7ixtepmf2oNz6ZsOonlkivxZevoIyvlLrJtwOzMoTQZlGvLFAcvMwVKax2Wek", + "VryvUphzFRFicLvE2nJTRnNn0oZsbRtIt/1m2mWcytqbRysbjHydst5nuxXf6FnH6xAQ6zd9AzbdLjBp", + "iq8+O3vVlYR8BuwDMTPCWp9sYKvjHwZRYo8QJhu8+YzOWJ5xJVjGrasWtcDwbx8xM2Qvwj+Z0g7Fuzm3", + "bCKEqvYxItfGWTaeyswJI9IjhlVhGtPF/FW4d7SaVzi1U1rLA7ofNA23IYtgbcda0gH6XXliV1p3OM5+", + "r7F+/bmAMG+A/be3EJRICd2dXR9KWmYEIFni66JzxTiwqUyGPBHxT4Agsin0iUWVdeEwcQCN1S+LLFdW", + "A7V7KFJQWpaKTE6EobIrSjtmYZvmwoijEKh5s4SG8AdyIT8W1qTEpAcEizNK8MYSnS+Dv1RVvUVTVpXp", + "sQSz3CHU1MipT5EsIYMJZXP621tWUAY9aQkZp4UVZYQ+hnFeIxSjCyeYM3w6lQnjmE6efsclDNm5TvmS", + "vvjlQBqRRC8WmPTgHOtSDukS/I4iyV5SZV7Ig2AMZqsfI7AzTN40Ztr4D98tc24teIqMQ26O04wvrw0E", + "XTNxk2tYBbds7GPUhkpce+h7v/pN/rg/PiIVbIXW4CIaV06CK3stjGWSsolQWhOsG+zTPkhlnQA7yxQk", + "22tuUKUnMfw0hObh/p7Estf9MgkW5RpZ5ySY5CpWVw18A7mJY0WOAOBngUmtVBVJLeMplesk3wvMGEkn", + "zZkpFBXoCEzpvCyVJW1ZwgdrIUjHbGGuqDRRzJTgUS3mw4AaDP6ee854wBU6+ARrDgewANB4dgoOsYYj", + "Ybo5V57t0Zs38teIbBPBMm1dEws8LVpZ4P3ryFq536cLC+zIgF/VriqPa583Vdfd2T3c3nmk8wNfvqFD", + "WREzkc5ws6xyiUSngjzMpkbYUAzCp1DBAHI+44Dltdq0noAuFHBYnfBsrq07+vOzZ8+IlhAq3OscHylA", + "hU9yPhNP+uyJhwv/9OCeECt4QiXAn1yoK24kRIrbYfg4BKrG+jF7+08i+VSmNLgGDu9rkWMaOqt4buea", + "+MyFCoCkutKXAkDtQbMPYtqnKif/T5/9ypxcCF24M5H8P+zj/hNGrS2VSeGJWykVPDe6mM19ahxIkvTE", + "MrtUydxopQsb5vPi9GQY/h04Q8zbBECuGfe/VxEOee0FcBhX2Jc6FX3c2D7OKvHET3s30enSp5ygEzDC", + "FllkU3ge5dFK67cQisP4VE4BfZFLv7oSZol5eOCoyQVReQDaHIFGTlAJl5S906kY/tMG7kcXhHSW6WsV", + "TgfsbKGS35C9xPwzaHsCQx1KSB40JUpKtPLZkbPlc58OSFcyWIXW0BhwUFCqOzg8EDD9IfZZYridY5ot", + "XxySRHKWaZ2HjEERVqqFRVmEY/qjC0UVcOLMhuwFpk/gAT7OJ3a/FCK3uO6wERjeYbT/2rATeL3g0fAJ", + "V6lW5T0YhvBXBwAHYeUqxM+ECz3M6ULhWhlqldYXS9lUsIQcHipuJi+33Reoi1wgVJYGXKDTCim3noQu", + "T3xKq/ouwOMvZU/8i/ZJEEt4ds2XlsrbWS8EXqh4nhzerRazSD4pkewiPIwvek+G7KSecSw063vGAjg9", + "IelLM658ijSqL063Km0uCiMCwZFf08DX2fYMGRPPUPUhGG6qjZh5qY5PKIXNhYp+UPVa3ZTnQudC+TJY", + "Ir5jQgIxP6M89gnFkS6UFZlA+dv/IC0rVDR1D0vGGeZWFxfpQPW1Z4sB2oXCQvHsZOrHH9COoL6PAp4S", + "YYNU58ukk82kX+EY9ZRRsL+1UoWUECXw86GfKfJqp/1cMFs0TTWkaxM3cP9Lly0R0045Us3S154CXILu", + "gGfIxABz8aoiLAsoQAyPCk5hG78YJa6x5YUi8RrocMhe8WS+AoB2jdMJnzhbhQWnaT0wWH6JDGwlB16V", + "wGGV/lJbx048KACgFZCoWfocbTR3DFGTDlMWWhx+yN7nWHiOQZG6yKbokHAKFczSU+LU/nAIl56D7qY6", + "13AQcEUr7Vv1L5THWlq0VoQ3oUy/tCzJtBXpGjcp98hzY5VGzH8Cu+qj9Olh8QSqAPudR+6XcBULU8Lp", + "0PE7PrHlDVtiP+5qkByes+gC6V90Mf8Mdw2bj3j2ItItjDznV3h/LLR17E8rqGGfN3Kd8rJIdKEcXDqw", + "ExeqIq0Hxaa/R4LM8vXhnwlBq3zTPveB1Mgo6No/fvXm1fkrti7qaWMPfoVpfhyyd/XZ+iw+Lj54QpHk", + "pExkTHwX3itwtT+n9xUg3LxwFuMR8XyXCCvCIS4l/bEQHjQ9ROhkRSlhviRN/EO8Q9bG+kw5ShrmAcJX", + "c/KZKIjdq5X2z/eX8yWuIhDpG7mQrjWdznngzCtYX9LKRCw1oQ/LhRkE2ssA7L2WiyunjrmCz3CWXsBa", + "f8R0TKrbRH6tatI3kvRDDRwD7xSfzRMarPCZmMhksmSn78/OG+herDuGwnjrB2YfUvXZhB+2Edfh1ioX", + "eH9RUTUdV7ni2x6m56V1L48VGwFWtqwy7CdRzA+8PyqVNHJTTLHqJRHllWSWak+itBfx4prbkERjyL6L", + "yY1XR6tdwMxpTVIPTB1vsYm4UEYUFlJ+1W9n/x5jQQgiWSaOz71oG5Sfa4jrlcPkIlTR8/mr4aj25inz", + "MfYZ93fiLhvDavuyUkL2X4Uo/F2EEtOFoqchCIha+YXFYznx0rDSsD58az3B7Rs5PnkSRB/KdUtza4z6", + "p3Qpa0jfyT8E/2eTQXE3QoPLvjGgH1bVgDB1azmM3WYuj/uyk12yk1/SqygyffmZYho4T1fGQ1iJXKfd", + "v/GUWsGWPVh5mTjCZxKWajNoE5PKosLGt7kD0jx79hCTf036u82z97wwquRC+WOfATSh4ihoQMsLh5wN", + "04or7ajohzNyVYof3nOJ3WCLqugts+56aI/XNufXaitin2GrB8VsHOLzorafQhtu48+f2Qqxfvr8Tsf/", + "q/8H+lleyizbigo/yCzrdIeWkDfepNHnqiiw5a3dum515LCa32QV0/c/fJFxr8CO5EzxjLLoB/eh2+Mk", + "JRLfipUfqNnvBi9pPY+YeX/B97CfIAme//dgQsUV7gM9ycTX6soYLhZq9amx84FvS1pU00Xpf/kiMwGF", + "B7ENZ3YX5EhlB9kKW/1uOBcu5zPLcTSFNjnuu6UTNrhjf7Ee2OX9yqzHoDthqi7cumP2Cuenxw45IXCs", + "BVIoJzP29NB789lYqQAz1aPTANrtSts5MwKUefZCoU8X6nXFTJKmqVAZGeAhEtgKNDi+4dYN0At4cHIc", + "HMFyI66kLiz6614oMpiTdzO6CoGlStIX+IVmhcq+MHN6uQ3ZCzLB0dLtheKZ1Ux4/zRoLhROW9zk0ggo", + "W3H+374zgOdXXGZYW8pbvBh3jifz5gq0AT3BU2WTh/uD0H1/3TfYFotYAjnurNQmLBD3dcje+4o6tn4Y", + "bUopOrte49ykct9+vTXQd4eZ1p2245TIEbycU23in8+hPaIAdOvo2h7IvKJryORUUFW9x9ivB4v9iqyi", + "wme1PwDrUmHMzr77RiRYqXZ2UFosmoUDUl1+CO0fNKd4HGV73eNVsvQdP5+O+DMVe4ia5XARYbwN7IZI", + "GdTt1TuFRVXwwmc5bX1ShDSoVdTYGC54Uoagx3yw4diCZ7bTMZ9xPzh1kQ92ZWpo0vHFwPRCOhccSspi", + "kqtwpY1w28vS4WXVHPDHB7+8GPz9cPDnwc//499u9czBszhY5F/fORFdiez+ZGscN/46eC2VtHORDl40", + "hXbIhbCOL3I4i+ggbyqgqfOQ/bXghisn6Bgmgn14/fKrr77683BzJFhtKmdkhLvVTLwB77YTgak8O3y2", + "iWdI652HJJbJRG/qPsszwa1gzizJ9k8Ww/p2f0BqQg/KBptvMZtRtmOoMooOmTBCEFAnYqoNaeiXRD3l", + "IqJQ8rRBKPn4BadMpgLTFkkUnXPvh1ll0rpWRgUmfzpscXfHhpgnbtNtFkajXMVrydfWKBpmSAbxMMt7", + "c3Wgp0a5+B03dsHNZXtcAK3TRn9KX0tWEa77rDtcBe/CCBbr4k6lwkpxhBPcXAoT6t7/k9xYZUjX5AXO", + "t6dfw52QzHnuhAl91n1a3nJz+dACS22MB0zzssMc2tQMb3GfIqH9YUSjF2kaMZNwxQcmSjUIbL7Eyd1p", + "Ay+mLamGHhoN64NsFJufbroC/SX7BVY7wx1gnNnECKGqPOY9ePNSbeKwzFwYdnLs3Z18JI4wVI7SR3/c", + "Bg90vgkNdP7wWFAZ4/ZvJ+9r8Hmj25zO6wJg9wPJs+0hbP/Jr7h368RAgBCpqVwMQ/JREezDq9M3Q3YW", + "K+BTqey5yPIjcHUbj8f/tBcKhh3Cx73956zt/w4OGN7GC+HmOq31uuglmUwuL3pN3Q8O2BlYMV1hRD9W", + "++6Hh44vnOpLzdahrgWrwQg4a3Rgj9pCPyVYUnF4+FXyfw0G7LtXfz15x/766t2rDy/OXx3jTrC3r86/", + "f3/M3pycnbPBABsLKIoCPx6xcRx73Pd/YKqZ+JdYSHcCAW5j6PRdWfLSGZ0dsTFUJe+zcWq4VJRACf4E", + "yfm1NvgB/p5pp380GfwTPPNBwIJ/U5CgnMhMuuWZD9uDH3Bv4R8ggp1DTHQfo5SzE5UX+EduwPoulvBv", + "mxidIXDvV3OGTCUAwwhCPsGJ+eiycz7BjtfSJXP/hxLX/l/oFOf/LZQtjPggeOY/yCm8lSl8Oyz1bXXR", + "bzRPq3uQYex65YsPYT1JM9zmf2LnIiZKhr/mzuV/FQ73nMIDj9h4NSBy3I/fSnSpfORp+rKwTi9WWwOE", + "5l/ItbP8bVxFr1fvjrsh14XyeDLweBKwFeXEUuONUd6U4StbIkloFUPWx+Q7hWFiU6N/EepCNYV8Jpn0", + "uvsSMLdhRWMEG2AO/ce+98QC7pngYi8Uho7yNO1j5gCiUNqOMPvh+hHs7Y9ZKm0CejyL0aeVyJXxX1+d", + "swPqcuD8TuN01iNS98c+2nFMPuC+F7WA3Bcv9WKhFQPEmUKa7iov4/hQ9TS2d9EL9Zs9gxkmekFchBpW", + "8HQPviYaHeSNEOwvjJo0EmalcSbVJfsL9hkqnQo7nEqV7sE/2V8IDRj8MTQ6E+wvf/kLu+hBn4seg1+f", + "fUv/pTboykxt3mpTqwYzHA5p5nLK9v4vgLDvw2aVuGZ4Ee0RZPScm4L8Wl0q8pE97Pf8QoXZY8LRsNQ1", + "lrF30Ttwi/wAw9tyNbvo9dGFts+efnt4WMKus8e9XwHqxwqvPtf5gKpNTaQCVPOBoUvFFz4sRy58fOJC", + "p0UmYgICbxYzwpuwvAKZbgpOyTDAQhWreV3xrPDVtuVMaQPO4DC18ASjNA8le98bDof74z7wcavhCvIo", + "jiGzK4yf2g7ZqVQKCrRjVWL0hfXEVfrWDxJtxJjlPLnkM5rPhVq3cPktYGNa/95+oIskzYEScqOv0FpU", + "qEp2kmNxhTTnkTP6rRvYrIUIkawZ/0V6biIxFLmMra2kahiyD8IK18dv3tu8H+OHfVBtn71//7bvD4CS", + "XoTK0SnMSy8pwtc6inxJQ85J/Pryx5PjZ7SZI5kCDUf3UDopK4ykouvA6qRlQqX+Kb6y9NUo7jKrSYw9", + "hOwr8IK94pnwj3lTAKUiBvoHeTVAec2lGSC/OD2xzxkZPoGgLFfpRN9sjPjyvP4DyHEPIydXRqg92eui", + "4n+evX8Xg+wnOg31/zHciJSPf2Jv5XdBg0e7i2mh6eFx7lHECFBkWMbh+WnnPBMpS7lYaBXBo90GVdf4", + "/Yn1oJW4zqQSg1SEUX2PAXymqVDNMaXVAJGoICXL14eHw96n9HWobWq3qLU9H7bGMG48Vk33NLF/p1fo", + "068+r0Ns/YFRibJGQaejs79NeCac/kUYDXXcgem1P21OjTeW+uxEaJUGCBgRoxlA6cNjl5sUvRr0lH1/", + "fn4akw5R6AomVQhBNIC+GOIvLYC8Bu34NdRtlI5NRMILK9iPSl4aPnX060qcKLTFDJVqGZHdM4+/vW0M", + "k6FlnsHKz/XfhdG9LsEh2H7g9ABWyfxepfdyomWioWwZIOO+irCrlS3qrDeoHq1Qm0/2g7BOG2GZAjkm", + "Y7a22PAcrMyiTwmMysxJ9emSHYPCddNM0JFT32h4+dtbprQvz8mUEKn11pa5yFIQdS5FIw9Xdz89oR7o", + "8Ajw3c8uNumU5c4/EVnsVS/FP2Sh8deHX2N4fWwnQ2Q4NW++Nf8q3HmczwPy9zgIeFM2OuKeNy/wtgrj", + "9eR2LfC7JbYLCeFXmCY3TiKroupOdGStR4W6RD+CFLaSd4JZETl9RWig4HcS49LnwUxdBUFeHT4mPuCK", + "Fc6BhL8TcrAz6uVzQcSpA86HXQG09/TlEyGyJBPc2JA0rRkx/0yMYWydNvCM8SDGMAuCgnWTyyxmmL4A", + "8zZlRvB0WaaGJwjP18cDWJmYwmPF71ejzxqcYx3hH0xAjMO8xHl+au/RW1Pc56tU9pmU/z/ieu/IIJoy", + "X54Jt4UjBBp5dvi0Tp/XnAi04pBT0urzmMXj2eEh9EM1igUSzrxbqrRM524g1dFqFkAiPoBe5SN7vExG", + "guPQIz3kRrXChdhdfIF6HhHYQpCY9lvZwfOYzkjGO9WLC5t40m+ShxTu83GQ3zzHuE/T9O0nZIX7Eq2Q", + "dxNTasJlpcxE87PgRHm9gvIJ2qKjRDkF8trts1lICVLN8rQy0SozOyxTC3ELEXQiZUJdiUznonwkRDd3", + "ngb/u2eHXzf8HhLCsj2lw/DBJ0+bsu0TW7IkaUuuhCzr68NDRrpJmXKfTAw1Bc00PsmkLSUF8m1+oEgT", + "GguH+EyRJuU6/SE1hpPjceQ0W1TphhNNuMFLpHbeFpaiEjEkrtCUkgEB8iQROaJX4cqT3oxrz+luDFMZ", + "3p7Wa/TnT6IDSexOjtuCUXzuMrQO1x3my7GJpH0MChr+8ILzCQIXbCzTI/arFf/6eHGhwAH+iP0aDmkA", + "GAHfLy7UGCQFOh2msAAa6Sa9Qnaw0Eo7rWSCqtlgBeCJ0dauMFqvYoZcw02RLWpZxrZUgmakJTqEaWNq", + "hUVQGdGyh+wYE1bCpCgAl1BixnMbnkljmY4p1ehRSCtnRCIkpAnD36SlOpuY0fgp43OfMMbNKTf8wAoQ", + "KCSYR2ln2bUwwEpIzV0G9BSQHnTIXqJtzzI7xxRTzmAawjVo6H4snEgcznfIXmMuy3L5NshWK1tGGZ3j", + "sOVrzh8VmSTxsSgoeQ7O+jn6N7Px/0OhSH/hWTamqnU1cDpLhXVlGEDAcEykQ+rmawn7Pee5CLkdZ0IJ", + "A7aROiccD9lrbaLE6HdP+Oepp11KvU75aNkeNKdUrsJYVlhfUEknxUIo6IXG9fF+v8bOx4DFY8Q5bRax", + "aOkilGQae0np33Fax9iYmFo/pp6EcQl4E6en6Ij68uw2J3QfwENxWL6uQI2ehuw92rsMs0Kl7LDhPMLx", + "5tpKegx0o0nMIFQjLDS3ERkJIDPjTdh+KO4z1Q/ZOb8UFvolIsWB0HAwJrwZ08WLVnAaWFhMj241MiRQ", + "zQ6M8GhcDpcJDjhZy8g0IJBwQnNpnTZL2vo7xjL11/UvgPi7IPyQfYBZEUmDtdUy7tjTw2dfP8cOEZl5", + "hRMA4dnCTHkiyFxCiTmR2GdGcBfypj+tLHMlLIB2pDnuKMt6P98mGuAOkVudbvw3HS6jL65KyeoK4ESp", + "pMHgTCjHIgfodMF7zwhy2xigW8VWtS49nit+g9Sb0oXHtNXIelHuPjnuowOqzXki+sT8hCEjdUwzvhCO", + "wz42J+cjHxryUUGz9UPqetcG25R/IdQm8XtQyZxuh/fnwN4AvYMRrd9Wmj76BOORpGwCRwLYXDlJyshX", + "/h38RcGRI+Rs0AbKcPi/hpB5uPwNYQRrZxB6oDO7krxiIBxWQKx0goZQ5gMTz8PwhcUKKmxSMSb6PntW", + "CDZG/8fxvnd2oipLmAlKwCXDKVCbzMVikTvQTxu+vFB6Ct6EUsmKfPPjhzcBV22/jqRsr/R44orpUHnN", + "+4cQIu37jPlhNdNCkfhEs6M9jwU2uNPej2XI3vpRsdICKq1d9H4JEocl4Ipia1CYtlVHLF24gZ4OYkJB", + "avGcYWbgKH/gqqT1RU5APEuETxF/oSC/n20YOhQcQU2ZVKzBM4vcSbRXrDCtBA5F3mD0IoF2/ZCuFxgG", + "sAmEnKb4d80750y4CypdM4JLnwr4RQz2pY6guedOMXMzrbDMFUrty91+fqGCWUIbr4njaRrcz0K+doJO", + "9ZM9ZK2ExcB2+rMsJkCltqUqGp/mL4If4So32+Vl7n3RkPUlaT4i8oG/qklWqKiwdFkkpV6/h9IWtIy7", + "0TvqVXzb4LpCwukd9f7x64Vi7FKq9IhdwEAXvT58Qfw5Yr8WJhv5AEF7xP7R6Ct38O8XvZ8/YjfY0iOG", + "MBkeBkA1gqcjWANO1A/AWIVjQStcTMigXVvSMHbB8hNnSHtH7Fe4TaEnVe0FtzOeppII9TSWDfZmIJof", + "/dfT6xHl8mJ7I4TbZ7/iqoX9uB+d8vb8WnBCR94F7p92b69sEohmiG367FfKDX+SHnnmYv9x+PPQ6XxE", + "P0ACiH2aDfzPx58vsHRdDzjn9mOusNk7HTUAeKizxpV0O2xoSiu7x1Nmnk1vgJFXev7qDzc2I/nsAk4l", + "FvXDDfFr+nkTMlVxxwOuY0j11D92zXHaxFM+UzjWjsJTKW7QPbiS4hGmxKWypDdAHi6usyW1rUhZX5ii", + "HASw24l0LTL7wa9rBbZXZXfwvaYCGlWhbrKsCepD9kJVbrJoe6rEBEczF1eJyCiOvH7Dfai4vZeI0Cm3", + "ypacKpVg9MSNIB79Z/jP4eDPP//67KuP3WLSGzS5FTwM+ZiHnzU9GkyB8QYc2Q1FyOF9kw3lCssyUc5j", + "njjS39aKM8Wa+aQY0zobGTEdsndaDUCnYosJqIpSkWQculyRMpdCAEKBpKhqEtL4+kqkpNF5kXGq1kKZ", + "rPEOlWo2QrhkI6HkX0P2ngpaANwLBe18+WcnzALiaH2W26oY7JW+il/JmbdZV54bVUqgS8EyPtFX4kI9", + "+/qQ/SC/i/MPObarZeY4c6ZQVL6Jho6FPqLJWi4E5orxO1DS1oXCREuWFIYWX/BlnZvCJXohRoW6VPpa", + "oVxM5fkol62NMvRKUtsGgZMOuUaID2EGogFosA1+xcje+TVb9S9Gi1fFufgpegDnWWHZ13gQeloabOAJ", + "gOpw73wcvY4/qc9vuWLqvsHx15duLI1FVPSw5LMqZUIiZpUkQe/UCo2hkUSbshDTGuoPv4wEatDr6wc7", + "hw0ppctGkOaMqz5a7STWKvIPeKA7X9vUp4/WE6TOdLjCpgnXGY8xSyK9PavupnrjsRwf0ENlMFvVx02W", + "/hWsc6HwxYS17ZZMLCYCJCdfXElRKAs+GrTFtxUFgrxXZJRDNbEn0n4wiPjIkIVW0mmzVkkNYgNxvFDM", + "CzX4GKpGwsSFwmlxEzN4+7oEMHw/dKNPYcIszBe6Cl+3AEGgFWsttzcoH1CmrNTeiXZ52BBtSthkicRp", + "VjbRzcWC6kSgh76/QYSFG4rqbKEZ0+sXfCZyVAbxfxUiXpQEN16iFMzScteuaJn6Fwr2oBLABZeTL5hH", + "29SnmgzQLCqhmtblY4BSqs4ARcbK+WlfnTGUslstz9jidltXX2w0N726we2paRf9cWwopiCo14h6NVdU", + "wGddp5IK9832OyuGm2ppfk7h8tgzqzr38HLSjnV9Pn78/w8ALdzyDfzeAwA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/server/openapi.yaml b/server/openapi.yaml index 94f66857..46b63c75 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -44,6 +44,12 @@ paths: $ref: "#/components/schemas/ProcessExecResult" "400": $ref: "#/components/responses/BadRequestError" + "422": + description: Execution stopped. The response includes captured output and must not be retried automatically. + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessExecFailure" "500": $ref: "#/components/responses/InternalError" /process/spawn: @@ -95,7 +101,12 @@ paths: $ref: "#/components/responses/InternalError" /process/{process_id}/stdout/stream: get: - summary: Stream process stdout over SSE + summary: Stream retained process stdout and stderr over SSE + description: | + Output is retained until 10 seconds after completion. Each connection replays + from the beginning unless an offset or Last-Event-ID from a previous data + event is supplied. Exit is sent after all retained output. Active streams + also end when retention expires. PTY output is available through attach. operationId: processStdoutStream x-telemetry-category: platform parameters: @@ -105,6 +116,18 @@ paths: schema: type: string format: uuid + - name: offset + in: query + description: Resume cursor from a prior output event. Overrides Last-Event-ID. + schema: + type: integer + format: int64 + minimum: 0 + - name: Last-Event-ID + in: header + description: Resume cursor from a prior SSE data event. + schema: + type: string responses: "200": description: SSE stream of process output and lifecycle events @@ -7375,11 +7398,13 @@ components: default: false timeout_sec: type: [integer, "null"] - description: Maximum execution time in seconds. + description: Maximum execution time in seconds, for exec and spawn. Null or zero disables the deadline. Cancellation stops the process group; detached descendants may survive. + minimum: 0 + maximum: 9223372036 additionalProperties: false ProcessExecResult: type: object - description: Result of a synchronous command execution. + description: Result of a synchronous command execution. Output is bounded by the configured process output quotas. properties: exit_code: type: integer @@ -7393,6 +7418,36 @@ components: duration_ms: type: integer description: Execution duration in milliseconds. + output_truncated: + type: boolean + description: Output could not be fully captured due to a quota, storage error, or a descendant holding a pipe open past the drain deadline. + additionalProperties: false + ProcessTerminationReason: + type: string + enum: [process_timeout, output_limit, process_canceled, output_error] + ProcessExecFailure: + type: object + required: [code, message] + properties: + code: + $ref: "#/components/schemas/ProcessTerminationReason" + message: + type: string + exit_code: + type: integer + description: Process exit code. + stdout_b64: + type: string + description: Base64-encoded stdout buffer. + stderr_b64: + type: string + description: Base64-encoded stderr buffer. + duration_ms: + type: integer + description: Execution duration in milliseconds. + output_truncated: + type: boolean + description: Output could not be fully captured due to a quota, storage error, or a descendant holding a pipe open past the drain deadline. additionalProperties: false ProcessSpawnRequest: allOf: @@ -7458,6 +7513,11 @@ components: mem_bytes: type: integer description: Estimated resident memory usage in bytes. + termination_reason: + $ref: "#/components/schemas/ProcessTerminationReason" + output_truncated: + type: boolean + description: Some output was not captured. additionalProperties: false ProcessStdinRequest: type: object @@ -7491,6 +7551,10 @@ components: type: object description: SSE payload representing process output or lifecycle events. properties: + offset: + type: integer + format: int64 + description: Opaque resume cursor after this data event. Also sent as the SSE id. stream: type: string description: Source stream of the data chunk. @@ -7505,6 +7569,11 @@ components: exit_code: type: integer description: Exit code when the event is "exit". + termination_reason: + $ref: "#/components/schemas/ProcessTerminationReason" + output_truncated: + type: boolean + description: Some output was not captured. additionalProperties: false PatchDisplayRequest: type: object From a6baa7c51663344ea8236c6bc4bd6acc481c0083 Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Wed, 14 Oct 2026 21:58:52 +0000 Subject: [PATCH 02/10] Capture process output independently and enforce deadlines --- server/cmd/api/api/api.go | 11 +- server/cmd/api/api/process.go | 511 +++++++++-------------- server/cmd/api/api/process_output.go | 201 +++++++++ server/cmd/api/api/process_runner.go | 270 ++++++++++++ server/cmd/api/api/process_wait_linux.go | 23 + server/cmd/api/api/process_wait_other.go | 12 + server/cmd/api/main.go | 1 + server/cmd/config/config.go | 7 + server/lib/scaletozero/connection.go | 23 +- 9 files changed, 740 insertions(+), 319 deletions(-) create mode 100644 server/cmd/api/api/process_output.go create mode 100644 server/cmd/api/api/process_runner.go create mode 100644 server/cmd/api/api/process_wait_linux.go create mode 100644 server/cmd/api/api/process_wait_other.go diff --git a/server/cmd/api/api/api.go b/server/cmd/api/api/api.go index 9cde7723..5c84cc4b 100644 --- a/server/cmd/api/api/api.go +++ b/server/cmd/api/api/api.go @@ -72,8 +72,9 @@ type ApiService struct { watches map[string]*fsWatch // Process management - procMu sync.RWMutex - procs map[string]*processHandle + procMu sync.RWMutex + procs map[string]*processHandle + processOutput *processOutputBudget // Neko authenticated client nekoAuthClient *nekoclient.AuthClient @@ -160,6 +161,7 @@ func New( otlpExport OTLPExporter, s2Storage S2Storage, egressPolicy *egresspolicy.State, + processOutputConfig ProcessOutputConfig, ) (*ApiService, error) { switch { case recordManager == nil: @@ -178,6 +180,10 @@ func New( return nil, fmt.Errorf("egressPolicy cannot be nil") } + outputBudget, err := newProcessOutputBudget(processOutputConfig) + if err != nil { + return nil, err + } screenshotEnabled := func() bool { return telemetrySession.CategoryEnabled(events.Screenshot) } mon := cdpmonitor.New(upstreamMgr, telemetrySession.Publish, displayNum, slog.Default(), screenshotEnabled) _ = mon.SetTelemetry(false) @@ -189,6 +195,7 @@ func New( defaultRecorderID: "default", watches: make(map[string]*fsWatch), procs: make(map[string]*processHandle), + processOutput: outputBudget, upstreamMgr: upstreamMgr, stz: stz, nekoAuthClient: nekoAuthClient, diff --git a/server/cmd/api/api/process.go b/server/cmd/api/api/process.go index 38a458f4..2db90150 100644 --- a/server/cmd/api/api/process.go +++ b/server/cmd/api/api/process.go @@ -1,7 +1,6 @@ package api import ( - "bufio" "bytes" "context" "encoding/base64" @@ -22,7 +21,6 @@ import ( "github.com/coder/websocket" "github.com/creack/pty" - "github.com/google/uuid" "github.com/kernel/kernel-images/server/lib/logger" oapi "github.com/kernel/kernel-images/server/lib/oapi" "github.com/kernel/kernel-images/server/lib/ptyio" @@ -31,40 +29,26 @@ import ( ) type processHandle struct { - id openapi_types.UUID - pid int - cmd *exec.Cmd - started time.Time - exitCode *int - stdin io.WriteCloser - stdout io.ReadCloser - stderr io.ReadCloser - ptyFile *os.File - isTTY bool - outCh chan oapi.ProcessStreamEvent - doneCh chan struct{} - mu sync.RWMutex + id openapi_types.UUID + pid int + cmd *exec.Cmd + started time.Time + exitCode *int + stdin io.WriteCloser + stdout io.ReadCloser + stderr io.ReadCloser + ptyFile *os.File + isTTY bool + output *processOutput + reason string + truncated bool + durationMs int + doneCh chan struct{} + mu sync.RWMutex // attachActive guards PTY attach sessions; only one client may be attached at a time. attachActive bool } -func (h *processHandle) state() string { - h.mu.RLock() - defer h.mu.RUnlock() - if h.exitCode != nil { - return "exited" - } - return "running" -} - -func (h *processHandle) setExited(code int) { - h.mu.Lock() - if h.exitCode == nil { - h.exitCode = &code - } - h.mu.Unlock() -} - func isUserCmdError(err error) bool { return errors.Is(err, exec.ErrNotFound) || errors.Is(err, exec.ErrDot) || @@ -83,6 +67,9 @@ func buildCmd(body *oapi.ProcessExecRequest) (*exec.Cmd, error) { if body.Args != nil { args = append(args, (*body.Args)...) } + if body.TimeoutSec != nil && (*body.TimeoutSec < 0 || int64(*body.TimeoutSec) > int64((1<<63-1)/time.Second)) { + return nil, errors.New("timeout_sec must be a nonnegative duration in seconds") + } cmd := exec.Command(body.Command, args...) if body.Cwd != nil && *body.Cwd != "" { cmd.Dir = *body.Cwd @@ -166,106 +153,86 @@ func buildCmd(body *oapi.ProcessExecRequest) (*exec.Cmd, error) { // Execute a command synchronously // (POST /process/exec) func (s *ApiService) ProcessExec(ctx context.Context, request oapi.ProcessExecRequestObject) (oapi.ProcessExecResponseObject, error) { - log := logger.FromContext(ctx) - if request.Body == nil { - return oapi.ProcessExec400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "request body required"}}, nil - } - - cmd, err := buildCmd((*oapi.ProcessExecRequest)(request.Body)) + cmd, err := buildCmd(request.Body) if err != nil { return oapi.ProcessExec400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil } - - var stdoutBuf, stderrBuf bytes.Buffer - cmd.Stdout = &stdoutBuf - cmd.Stderr = &stderrBuf - - // Handle timeout if provided - start := time.Now() - var cancel context.CancelFunc - if request.Body.TimeoutSec != nil && *request.Body.TimeoutSec > 0 { - ctx, cancel = context.WithTimeout(ctx, time.Duration(*request.Body.TimeoutSec)*time.Second) - defer cancel() - } - if err := cmd.Start(); err != nil { + h, err := s.startProcess(ctx, cmd, false, false, request.Body.TimeoutSec) + if err != nil { if isUserCmdError(err) { return oapi.ProcessExec400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil } - log.Error("failed to start process", "err", err) + logger.FromContext(ctx).Error("failed to start process", "err", err) return oapi.ProcessExec500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to start process"}}, nil } - - done := make(chan error, 1) - go func() { done <- cmd.Wait() }() - select { - case <-ctx.Done(): - _ = cmd.Process.Kill() - <-done // ensure wait returns - return oapi.ProcessExec500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "process timed out"}}, nil - case err := <-done: - // proceed - _ = err - } - durationMs := int(time.Since(start) / time.Millisecond) - exitCode := 0 - if cmd.ProcessState != nil { - if status, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok { - exitCode = status.ExitStatus() + defer s.releaseProcess(h) + <-h.doneCh + var stdout, stderr bytes.Buffer + var offset int64 + for { + stream, data, next, err := h.output.next(context.Background(), offset) + if errors.Is(err, io.EOF) { + break + } + if err != nil { + h.outputFailed(err) + break } + if stream == 0 { + stdout.Write(data) + } else { + stderr.Write(data) + } + offset = next } + h.mu.RLock() + code, reason, truncated, duration := *h.exitCode, h.reason, h.truncated, h.durationMs + h.mu.RUnlock() + out, errOut := base64.StdEncoding.EncodeToString(stdout.Bytes()), base64.StdEncoding.EncodeToString(stderr.Bytes()) + if reason != "" { + return oapi.ProcessExec422JSONResponse{ + Code: oapi.ProcessTerminationReason(reason), Message: processTerminationMessage(reason), + ExitCode: &code, StdoutB64: &out, StderrB64: &errOut, DurationMs: &duration, OutputTruncated: &truncated, + }, nil + } + return oapi.ProcessExec200JSONResponse{ExitCode: &code, StdoutB64: &out, StderrB64: &errOut, DurationMs: &duration, OutputTruncated: &truncated}, nil +} - resp := oapi.ProcessExec200JSONResponse{ - ExitCode: &exitCode, - StdoutB64: ptrOf(base64.StdEncoding.EncodeToString(stdoutBuf.Bytes())), - StderrB64: ptrOf(base64.StdEncoding.EncodeToString(stderrBuf.Bytes())), - DurationMs: &durationMs, +func processTerminationMessage(reason string) string { + switch reason { + case "process_timeout": + return "process timed out" + case "output_limit": + return "process output limit exceeded" + case "process_canceled": + return "process canceled" + default: + return "failed to capture process output" } - return resp, nil } -// Execute a command asynchronously -// (POST /process/spawn) +// Execute a command asynchronously. func (s *ApiService) ProcessSpawn(ctx context.Context, request oapi.ProcessSpawnRequestObject) (oapi.ProcessSpawnResponseObject, error) { - log := logger.FromContext(ctx) if request.Body == nil { return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "request body required"}}, nil } - // Build from ProcessExecRequest shape + body := request.Body execReq := oapi.ProcessExecRequest{ - Command: request.Body.Command, - Args: request.Body.Args, - Cwd: request.Body.Cwd, - Env: request.Body.Env, - AsUser: request.Body.AsUser, - AsRoot: request.Body.AsRoot, - TimeoutSec: request.Body.TimeoutSec, + Command: body.Command, Args: body.Args, Cwd: body.Cwd, Env: body.Env, + AsRoot: body.AsRoot, AsUser: body.AsUser, TimeoutSec: body.TimeoutSec, } cmd, err := buildCmd(&execReq) if err != nil { return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil } - - var ( - stdout io.ReadCloser - stderr io.ReadCloser - stdin io.WriteCloser - ptyFile *os.File - isTTY bool - ) - // PTY mode when requested - if request.Body.AllocateTty != nil && *request.Body.AllocateTty { - // Validate rows/cols before starting the process - const maxUint16 = 65535 - if request.Body.Rows != nil && *request.Body.Rows > maxUint16 { - return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "rows must be <= 65535"}}, nil - } - if request.Body.Cols != nil && *request.Body.Cols > maxUint16 { - return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "cols must be <= 65535"}}, nil + tty := body.AllocateTty != nil && *body.AllocateTty + if tty { + if (body.Rows != nil && (*body.Rows < 1 || *body.Rows > 65535)) || (body.Cols != nil && (*body.Cols < 1 || *body.Cols > 65535)) { + return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "rows and cols must be between 1 and 65535"}}, nil } - // Ensure TERM and initial size env hasTerm := false - for _, kv := range cmd.Env { - if strings.HasPrefix(kv, "TERM=") { + for _, env := range cmd.Env { + if strings.HasPrefix(env, "TERM=") { hasTerm = true break } @@ -273,188 +240,20 @@ func (s *ApiService) ProcessSpawn(ctx context.Context, request oapi.ProcessSpawn if !hasTerm { cmd.Env = append(cmd.Env, "TERM=xterm-256color") } - // Start with PTY - var errStart error - ptyFile, errStart = pty.Start(cmd) - if errStart != nil { - if isUserCmdError(errStart) { - return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: errStart.Error()}}, nil - } - log.Error("failed to start PTY process", "err", errStart) - return oapi.ProcessSpawn500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to start process"}}, nil - } - // Set initial size if provided - var rows, cols uint16 - if request.Body.Rows != nil && *request.Body.Rows > 0 { - rows = uint16(*request.Body.Rows) - } - if request.Body.Cols != nil && *request.Body.Cols > 0 { - cols = uint16(*request.Body.Cols) - } - if rows > 0 && cols > 0 { - _ = pty.Setsize(ptyFile, &pty.Winsize{Rows: rows, Cols: cols}) - } - stdout = ptyFile - stdin = ptyFile - isTTY = true - } else { - stdout, err = cmd.StdoutPipe() - if err != nil { - return oapi.ProcessSpawn500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to open stdout"}}, nil - } - stderr, err = cmd.StderrPipe() - if err != nil { - return oapi.ProcessSpawn500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to open stderr"}}, nil - } - stdin, err = cmd.StdinPipe() - if err != nil { - return oapi.ProcessSpawn500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to open stdin"}}, nil - } - if err := cmd.Start(); err != nil { - if isUserCmdError(err) { - return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil - } - log.Error("failed to start process", "err", err) - return oapi.ProcessSpawn500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to start process"}}, nil + } + h, err := s.startProcess(context.WithoutCancel(ctx), cmd, tty, true, body.TimeoutSec) + if err != nil { + if isUserCmdError(err) { + return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil } + logger.FromContext(ctx).Error("failed to start process", "err", err) + return oapi.ProcessSpawn500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to start process"}}, nil } - - // Disable scale-to-zero while the process is running. - // Track success so we only re-enable if disable succeeded. - stzDisabled := false - if err := s.stz.Disable(ctx); err != nil { - log.Error("failed to disable scale-to-zero", "err", err) - } else { - stzDisabled = true - } - - id := openapi_types.UUID(uuid.New()) - h := &processHandle{ - id: id, - pid: cmd.Process.Pid, - cmd: cmd, - started: time.Now(), - stdin: stdin, - stdout: stdout, - stderr: stderr, - ptyFile: ptyFile, - isTTY: isTTY, - outCh: make(chan oapi.ProcessStreamEvent, 256), - doneCh: make(chan struct{}), - } - - // Store handle - s.procMu.Lock() - if s.procs == nil { - s.procs = make(map[string]*processHandle) - } - s.procs[id.String()] = h - s.procMu.Unlock() - - // Reader goroutines - // In PTY mode, do NOT read from the PTY here to avoid competing with the /attach endpoint. - // In non‑PTY mode, stdout and stderr are separate pipes, so we run two readers and tag chunks accordingly. - if !isTTY { - go func() { - reader := bufio.NewReader(stdout) - buf := make([]byte, 4096) - for { - n, err := reader.Read(buf) - if n > 0 { - data := base64.StdEncoding.EncodeToString(buf[:n]) - stream := oapi.ProcessStreamEventStream("stdout") - h.outCh <- oapi.ProcessStreamEvent{Stream: &stream, DataB64: &data} - } - if err != nil { - break - } - } - }() - go func() { - reader := bufio.NewReader(stderr) - buf := make([]byte, 4096) - for { - n, err := reader.Read(buf) - if n > 0 { - data := base64.StdEncoding.EncodeToString(buf[:n]) - stream := oapi.ProcessStreamEventStream("stderr") - h.outCh <- oapi.ProcessStreamEvent{Stream: &stream, DataB64: &data} - } - if err != nil { - break - } - } - }() + if tty && body.Rows != nil && body.Cols != nil { + _ = pty.Setsize(h.ptyFile, &pty.Winsize{Rows: uint16(*body.Rows), Cols: uint16(*body.Cols)}) } - - // Waiter goroutine - use context without cancel since HTTP request may complete - // before the process exits - stzCtx := context.WithoutCancel(ctx) - go func(stzWasDisabled bool) { - err := cmd.Wait() - code := 0 - if err != nil { - if exitErr, ok := err.(*exec.ExitError); ok { - if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { - code = status.ExitStatus() - } - } - } else if cmd.ProcessState != nil { - if status, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok { - code = status.ExitStatus() - } - } - h.setExited(code) - // Ensure all related FDs are closed to avoid leaking descriptors. - // In PTY mode, close the PTY master; in non-PTY mode, close individual pipes. - if h.isTTY { - if h.ptyFile != nil { - _ = h.ptyFile.Close() - } - } else { - if h.stdin != nil { - _ = h.stdin.Close() - } - if h.stdout != nil { - _ = h.stdout.Close() - } - if h.stderr != nil { - _ = h.stderr.Close() - } - } - - // Re-enable scale-to-zero now that the process has exited, - // but only if we successfully disabled it earlier - if stzWasDisabled { - if err := s.stz.Enable(stzCtx); err != nil { - log.Error("failed to enable scale-to-zero", "err", err) - } - } - - // Send exit event - evt := oapi.ProcessStreamEventEvent("exit") - h.outCh <- oapi.ProcessStreamEvent{Event: &evt, ExitCode: &code} - close(h.doneCh) - // Retain the handle for a short period so clients can observe the - // final "exited" status via ProcessStatus before it disappears. - // This avoids races where the process exits immediately after spawn - // and status polling returns 404. - retention := 10 * time.Second - go func(procID string) { - time.Sleep(retention) - s.procMu.Lock() - delete(s.procs, procID) - s.procMu.Unlock() - }(id.String()) - }(stzDisabled) - - startedAt := h.started - pid := h.pid - return oapi.ProcessSpawn200JSONResponse{ - ProcessId: &id, - Pid: &pid, - StartedAt: &startedAt, - }, nil + go s.retainProcess(h) + return oapi.ProcessSpawn200JSONResponse{ProcessId: &h.id, Pid: &h.pid, StartedAt: &h.started}, nil } // Send signal to process @@ -485,10 +284,12 @@ func (s *ApiService) ProcessKill(ctx context.Context, request oapi.ProcessKillRe default: return oapi.ProcessKill400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "invalid signal"}}, nil } - if h.cmd.Process == nil { + h.mu.Lock() + defer h.mu.Unlock() + if h.exitCode != nil { return oapi.ProcessKill404JSONResponse{NotFoundErrorJSONResponse: oapi.NotFoundErrorJSONResponse{Message: "process not running"}}, nil } - if err := h.cmd.Process.Signal(sig); err != nil { + if err := signalChildProcessGroup(h.cmd, sig); err != nil { log.Error("failed to signal process", "err", err) return oapi.ProcessKill500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to signal process"}}, nil } @@ -505,19 +306,20 @@ func (s *ApiService) ProcessStatus(ctx context.Context, request oapi.ProcessStat if !ok { return oapi.ProcessStatus404JSONResponse{NotFoundErrorJSONResponse: oapi.NotFoundErrorJSONResponse{Message: "process not found"}}, nil } - stateStr := h.state() - state := oapi.ProcessStatusState(stateStr) + state := oapi.ProcessStatusState("running") var exitCode *int h.mu.RLock() if h.exitCode != nil { + state = "exited" v := *h.exitCode exitCode = &v } pid := h.pid + reason, truncated := h.reason, h.truncated h.mu.RUnlock() // Best-effort memory stats via /proc var memBytes int - if stateStr == "running" && pid > 0 { + if state == "running" && pid > 0 { if b, err := os.ReadFile("/proc/" + strconv.Itoa(pid) + "/status"); err == nil { // Parse VmRSS: 123 kB for _, line := range strings.Split(string(b), "\n") { @@ -535,7 +337,10 @@ func (s *ApiService) ProcessStatus(ctx context.Context, request oapi.ProcessStat } } cpuPct := float32(0) - resp := oapi.ProcessStatus200JSONResponse{State: &state, ExitCode: exitCode, CpuPct: &cpuPct} + resp := oapi.ProcessStatus200JSONResponse{State: &state, ExitCode: exitCode, CpuPct: &cpuPct, OutputTruncated: &truncated} + if reason != "" { + resp.TerminationReason = ptrOf(oapi.ProcessTerminationReason(reason)) + } if memBytes > 0 { resp.MemBytes = ptrOf(memBytes) } @@ -569,45 +374,121 @@ func (s *ApiService) ProcessStdin(ctx context.Context, request oapi.ProcessStdin // Stream process stdout/stderr (SSE) // (GET /process/{process_id}/stdout/stream) func (s *ApiService) ProcessStdoutStream(ctx context.Context, request oapi.ProcessStdoutStreamRequestObject) (oapi.ProcessStdoutStreamResponseObject, error) { - log := logger.FromContext(ctx) - id := request.ProcessId.String() s.procMu.RLock() - h, ok := s.procs[id] + h, ok := s.procs[request.ProcessId.String()] s.procMu.RUnlock() if !ok { return oapi.ProcessStdoutStream404JSONResponse{NotFoundErrorJSONResponse: oapi.NotFoundErrorJSONResponse{Message: "process not found"}}, nil } - + var offset int64 + var err error + if request.Params.Offset != nil { + offset = *request.Params.Offset + } else if request.Params.LastEventID != nil { + offset, err = strconv.ParseInt(*request.Params.LastEventID, 10, 64) + } + if err != nil || h.output.validateOffset(offset) != nil { + return oapi.ProcessStdoutStream400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "invalid output offset"}}, nil + } + ctx, cancel := context.WithCancel(ctx) pr, pw := io.Pipe() + finished := make(chan struct{}) go func() { + select { + case <-ctx.Done(): + pw.CloseWithError(ctx.Err()) + case <-h.output.closed: + pw.CloseWithError(os.ErrClosed) + case <-finished: + } + }() + go func() { + defer close(finished) + defer cancel() defer pw.Close() - for { - select { - case evt := <-h.outCh: - // Write SSE: data: \n\n - var buf bytes.Buffer - if err := json.NewEncoder(&buf).Encode(evt); err != nil { - log.Error("failed to marshal event", "err", err) - return - } - line := bytes.TrimRight(buf.Bytes(), "\n") - if _, err := pw.Write([]byte("data: ")); err != nil { - return - } - if _, err := pw.Write(line); err != nil { - return + writeEvent := func(event oapi.ProcessStreamEvent) error { + data, err := json.Marshal(event) + if err != nil { + return err + } + if event.Offset != nil { + if _, err := fmt.Fprintf(pw, "id: %d\n", *event.Offset); err != nil { + return err } - if _, err := pw.Write([]byte("\n\n")); err != nil { - return + } + _, err = fmt.Fprintf(pw, "data: %s\n\n", data) + return err + } + for { + stream, data, next, err := h.output.next(ctx, offset) + if errors.Is(err, io.EOF) { + <-h.doneCh + h.mu.RLock() + code, reason, truncated := *h.exitCode, h.reason, h.truncated + h.mu.RUnlock() + event := oapi.ProcessStreamEvent{Event: ptrOf(oapi.Exit), ExitCode: &code, OutputTruncated: &truncated} + if reason != "" { + event.TerminationReason = ptrOf(oapi.ProcessTerminationReason(reason)) } - case <-h.doneCh: + _ = writeEvent(event) + return + } + if err != nil { + pw.CloseWithError(err) + return + } + source := oapi.ProcessStreamEventStream("stdout") + if stream == 1 { + source = "stderr" + } + event := oapi.ProcessStreamEvent{Stream: &source, DataB64: ptrOf(base64.StdEncoding.EncodeToString(data)), Offset: &next} + if writeEvent(event) != nil { return } + offset = next } }() + return processStreamResponse{ + ProcessStdoutStream200TexteventStreamResponse: oapi.ProcessStdoutStream200TexteventStreamResponse{ + Body: &processStreamReader{PipeReader: pr, cancel: cancel}, + Headers: oapi.ProcessStdoutStream200ResponseHeaders{XSSEContentType: "application/json"}, + }, + expired: h.output.closed, + }, nil +} + +type processStreamResponse struct { + oapi.ProcessStdoutStream200TexteventStreamResponse + expired <-chan struct{} +} + +func (r processStreamResponse) VisitProcessStdoutStreamResponse(w http.ResponseWriter) error { + finished, stopped := make(chan struct{}), make(chan struct{}) + controller := http.NewResponseController(w) + go func() { + defer close(stopped) + select { + case <-r.expired: + // Closing the source does not interrupt a network write already in progress. + _ = controller.SetWriteDeadline(time.Now()) + case <-finished: + } + }() + defer func() { + close(finished) + <-stopped + }() + return r.ProcessStdoutStream200TexteventStreamResponse.VisitProcessStdoutStreamResponse(w) +} + +type processStreamReader struct { + *io.PipeReader + cancel context.CancelFunc +} - headers := oapi.ProcessStdoutStream200ResponseHeaders{XSSEContentType: "application/json"} - return oapi.ProcessStdoutStream200TexteventStreamResponse{Body: pr, Headers: headers, ContentLength: 0}, nil +func (r *processStreamReader) Close() error { + r.cancel() + return r.PipeReader.Close() } func ptrOf[T any](v T) *T { return &v } diff --git a/server/cmd/api/api/process_output.go b/server/cmd/api/api/process_output.go new file mode 100644 index 00000000..14e71673 --- /dev/null +++ b/server/cmd/api/api/process_output.go @@ -0,0 +1,201 @@ +package api + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "io" + "os" + "sync" +) + +const ( + processOutputChunkSize = 32 * 1024 + processOutputHeaderSize = 13 +) + +var errProcessOutputLimit = errors.New("process output limit exceeded") +var errProcessOutputOffset = errors.New("invalid process output offset") + +// ProcessOutputConfig bounds stored output, including record headers. Zero limits +// use the defaults; Dir defaults to the operating system's temporary directory. +type ProcessOutputConfig struct { + Dir string + MaxBytes int64 + TotalMaxBytes int64 +} + +type processOutputBudget struct { + mu sync.Mutex + config ProcessOutputConfig + used int64 +} + +func newProcessOutputBudget(config ProcessOutputConfig) (*processOutputBudget, error) { + if config.MaxBytes == 0 { + config.MaxBytes = 64 << 20 + } + if config.TotalMaxBytes == 0 { + config.TotalMaxBytes = 256 << 20 + } + if config.MaxBytes <= processOutputHeaderSize || config.TotalMaxBytes < config.MaxBytes { + return nil, fmt.Errorf("process output limits must exceed %d bytes and total must be at least the per-process limit", processOutputHeaderSize) + } + return &processOutputBudget{config: config}, nil +} + +func (b *processOutputBudget) reserve(n int64) int64 { + b.mu.Lock() + defer b.mu.Unlock() + n = min(n, b.config.TotalMaxBytes-b.used) + b.used += n + return n +} + +func (b *processOutputBudget) release(n int64) { + b.mu.Lock() + b.used -= n + b.mu.Unlock() +} + +type processOutput struct { + mu sync.Mutex + file *os.File + budget *processOutputBudget + size int64 + allocated int64 + complete bool + err error + changed chan struct{} + closed chan struct{} + closeOnce sync.Once +} + +func (b *processOutputBudget) open() (*processOutput, error) { + f, err := os.CreateTemp(b.config.Dir, "kernel-process-output-*") + if err != nil { + return nil, err + } + // Keep only the open descriptor so a server crash cannot orphan output files. + if err := os.Remove(f.Name()); err != nil { + f.Close() + return nil, err + } + return &processOutput{file: f, budget: b, changed: make(chan struct{}), closed: make(chan struct{})}, nil +} + +func (o *processOutput) append(stream byte, data []byte) error { + o.mu.Lock() + defer o.mu.Unlock() + if o.err != nil { + return o.err + } + select { + case <-o.closed: + return os.ErrClosed + default: + } + want := int64(processOutputHeaderSize + len(data)) + available := min(want, o.budget.config.MaxBytes-o.allocated) + reserved := o.budget.reserve(available) + if reserved <= processOutputHeaderSize { + o.budget.release(reserved) + o.err = errProcessOutputLimit + return o.err + } + o.allocated += reserved + n := int(reserved) - processOutputHeaderSize + record := make([]byte, int(reserved)) + binary.BigEndian.PutUint64(record, uint64(o.size)) + binary.BigEndian.PutUint32(record[8:], uint32(n)) + record[12] = stream + copy(record[processOutputHeaderSize:], data[:n]) + if _, err := o.file.WriteAt(record, o.size); err != nil { + o.err = err + return err + } + o.size += reserved + close(o.changed) + o.changed = make(chan struct{}) + if reserved < want { + o.err = errProcessOutputLimit + } + return o.err +} + +func (o *processOutput) finish() { + o.mu.Lock() + o.complete = true + close(o.changed) + o.mu.Unlock() +} + +func (o *processOutput) close() { + o.closeOnce.Do(func() { + o.mu.Lock() + defer o.mu.Unlock() + close(o.closed) + o.file.Close() + o.budget.release(o.allocated) + }) +} + +func (o *processOutput) header(offset int64) (byte, int, error) { + var header [processOutputHeaderSize]byte + if _, err := o.file.ReadAt(header[:], offset); err != nil { + return 0, 0, err + } + n := int(binary.BigEndian.Uint32(header[8:])) + if binary.BigEndian.Uint64(header[:]) != uint64(offset) || n <= 0 || n > processOutputChunkSize || header[12] > 1 { + return 0, 0, errProcessOutputOffset + } + return header[12], n, nil +} + +func (o *processOutput) validateOffset(offset int64) error { + o.mu.Lock() + defer o.mu.Unlock() + if offset < 0 || offset > o.size { + return errProcessOutputOffset + } + if offset == o.size { + return nil + } + _, n, err := o.header(offset) + if err != nil || offset+processOutputHeaderSize+int64(n) > o.size { + return errProcessOutputOffset + } + return nil +} + +func (o *processOutput) next(ctx context.Context, offset int64) (stream byte, data []byte, next int64, err error) { + for { + o.mu.Lock() + size, complete, changed := o.size, o.complete, o.changed + o.mu.Unlock() + if offset < size { + stream, n, err := o.header(offset) + if err != nil { + return 0, nil, offset, err + } + next := offset + processOutputHeaderSize + int64(n) + if next > size { + return 0, nil, offset, errProcessOutputOffset + } + data := make([]byte, n) + _, err = o.file.ReadAt(data, offset+processOutputHeaderSize) + return stream, data, next, err + } + if complete { + return 0, nil, offset, io.EOF + } + select { + case <-ctx.Done(): + return 0, nil, offset, ctx.Err() + case <-o.closed: + return 0, nil, offset, os.ErrClosed + case <-changed: + } + } +} diff --git a/server/cmd/api/api/process_runner.go b/server/cmd/api/api/process_runner.go new file mode 100644 index 00000000..b22f6946 --- /dev/null +++ b/server/cmd/api/api/process_runner.go @@ -0,0 +1,270 @@ +package api + +import ( + "context" + "errors" + "fmt" + "io" + "os" + "os/exec" + "sync" + "syscall" + "time" + + "github.com/creack/pty" + "github.com/google/uuid" + "github.com/kernel/kernel-images/server/lib/logger" +) + +const processOutputDrainTimeout = time.Second +const processRetention = 10 * time.Second + +func (s *ApiService) startProcess(ctx context.Context, cmd *exec.Cmd, tty, stdin bool, timeoutSec *int) (*processHandle, error) { + s.procMu.Lock() + if s.processOutput == nil { + s.processOutput, _ = newProcessOutputBudget(ProcessOutputConfig{}) + } + budget := s.processOutput + s.procMu.Unlock() + output, err := budget.open() + if err != nil { + return nil, fmt.Errorf("create process output: %v", err) + } + h := &processHandle{id: uuid.New(), cmd: cmd, started: time.Now(), isTTY: tty, output: output, doneCh: make(chan struct{})} + if tty { + h.ptyFile, err = pty.Start(cmd) + h.stdin = h.ptyFile + } else { + if cmd.SysProcAttr == nil { + cmd.SysProcAttr = &syscall.SysProcAttr{} + } + cmd.SysProcAttr.Setpgid = true + if stdin { + h.stdin, err = cmd.StdinPipe() + } + if err == nil { + h.stdout, h.stderr, err = startWithOutputPipes(cmd) + } + } + if err != nil { + if h.stdin != nil { + h.stdin.Close() + } + output.close() + return nil, err + } + h.pid = cmd.Process.Pid + s.procMu.Lock() + if s.procs == nil { + s.procs = make(map[string]*processHandle) + } + s.procs[h.id.String()] = h + s.procMu.Unlock() + stzDisabled := false + if s.stz != nil { + if err := s.stz.Disable(ctx); err != nil { + logger.FromContext(ctx).Error("failed to disable scale-to-zero", "err", err) + } else { + stzDisabled = true + } + } + lifecycle := s.lifecycleCtx + if lifecycle == nil { + lifecycle = context.Background() + } + go h.run(ctx, lifecycle, timeoutSec, func() { + if stzDisabled { + releaseCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 5*time.Second) + defer cancel() + if err := s.stz.Enable(releaseCtx); err != nil { + logger.FromContext(ctx).Error("failed to enable scale-to-zero", "err", err) + } + } + }) + return h, nil +} + +func startWithOutputPipes(cmd *exec.Cmd) (io.ReadCloser, io.ReadCloser, error) { + stdoutR, stdoutW, err := os.Pipe() + if err != nil { + return nil, nil, err + } + stderrR, stderrW, err := os.Pipe() + if err != nil { + stdoutR.Close() + stdoutW.Close() + return nil, nil, err + } + cmd.Stdout, cmd.Stderr = stdoutW, stderrW + err = cmd.Start() + stdoutW.Close() + stderrW.Close() + if err != nil { + stdoutR.Close() + stderrR.Close() + return nil, nil, err + } + return stdoutR, stderrR, nil +} + +func (h *processHandle) terminate(reason string, truncated bool) { + h.mu.Lock() + defer h.mu.Unlock() + if h.reason == "" { + h.reason = reason + } + h.truncated = h.truncated || truncated + if h.exitCode == nil { + _ = signalChildProcessGroup(h.cmd, killSignal) + } +} + +func (h *processHandle) outputFailed(err error) { + reason := "output_error" + if errors.Is(err, errProcessOutputLimit) { + reason = "output_limit" + } + h.terminate(reason, true) +} + +func (h *processHandle) run(ctx, lifecycle context.Context, timeoutSec *int, release func()) { + defer release() + failures := make(chan error, 2) + var readers sync.WaitGroup + if !h.isTTY { + for stream, pipe := range []io.ReadCloser{h.stdout, h.stderr} { + readers.Add(1) + go func(stream byte, pipe io.Reader) { + defer readers.Done() + if err := h.captureOutput(stream, pipe); err != nil { + failures <- err + } + }(byte(stream), pipe) + } + } + readersDone := make(chan struct{}) + go func() { readers.Wait(); close(readersDone) }() + waited := make(chan error, 1) + go func() { waited <- waitForProcessExit(h.cmd) }() + var deadline, drain <-chan time.Time + var deadlineAt time.Time + if timeoutSec != nil && *timeoutSec > 0 { + deadlineAt = h.started.Add(time.Duration(*timeoutSec) * time.Second) + timer := time.NewTimer(time.Until(deadlineAt)) + defer timer.Stop() + deadline = timer.C + } + canceled, shutdown := ctx.Done(), lifecycle.Done() + leaderExited, outputComplete := false, false + for !leaderExited || !outputComplete { + select { + case err := <-waited: + if err != nil { + h.terminate("process_canceled", false) + logger.FromContext(ctx).Error("failed to wait for process exit", "err", err) + } + leaderExited = true + waited = nil + timer := time.NewTimer(processOutputDrainTimeout) + defer timer.Stop() + drain = timer.C + case <-readersDone: + outputComplete = true + readersDone = nil + case <-deadline: + h.terminate("process_timeout", false) + deadline = nil + case <-canceled: + h.terminate("process_canceled", false) + canceled = nil + case <-shutdown: + h.terminate("process_canceled", false) + shutdown = nil + case err := <-failures: + h.outputFailed(err) + case <-drain: + if !deadlineAt.IsZero() && !time.Now().Before(deadlineAt) { + h.terminate("process_timeout", false) + } + h.mu.Lock() + h.truncated = true + _ = signalChildProcessGroup(h.cmd, killSignal) + h.mu.Unlock() + h.closeOutputPipes() + drain = nil + } + } + // Reap while holding the same lock used by signal requests, so no signal can + // target a reused PID between Wait and publishing the exit code. + h.mu.Lock() + reapProcess(h.cmd) + code := h.cmd.ProcessState.ExitCode() + h.exitCode = &code + h.mu.Unlock() + h.closeOutputPipes() + if h.stdin != nil { + h.stdin.Close() + } + for { + select { + case err := <-failures: + h.outputFailed(err) + default: + h.mu.Lock() + h.durationMs = int(time.Since(h.started) / time.Millisecond) + h.mu.Unlock() + h.output.finish() + close(h.doneCh) + return + } + } +} + +func (h *processHandle) captureOutput(stream byte, pipe io.Reader) error { + buf := make([]byte, processOutputChunkSize) + for { + n, err := pipe.Read(buf) + if n > 0 { + if writeErr := h.output.append(stream, buf[:n]); writeErr != nil { + return writeErr + } + } + if errors.Is(err, io.EOF) || errors.Is(err, os.ErrClosed) { + return nil + } + if err != nil { + return err + } + } +} + +func (h *processHandle) closeOutputPipes() { + if h.isTTY { + h.ptyFile.Close() + } else { + h.stdout.Close() + h.stderr.Close() + } +} + +func (s *ApiService) releaseProcess(h *processHandle) { + s.procMu.Lock() + delete(s.procs, h.id.String()) + s.procMu.Unlock() + h.output.close() +} + +func (s *ApiService) retainProcess(h *processHandle) { + <-h.doneCh + timer := time.NewTimer(processRetention) + defer timer.Stop() + var shutdown <-chan struct{} + if s.lifecycleCtx != nil { + shutdown = s.lifecycleCtx.Done() + } + select { + case <-timer.C: + case <-shutdown: + } + s.releaseProcess(h) +} diff --git a/server/cmd/api/api/process_wait_linux.go b/server/cmd/api/api/process_wait_linux.go new file mode 100644 index 00000000..6c275e35 --- /dev/null +++ b/server/cmd/api/api/process_wait_linux.go @@ -0,0 +1,23 @@ +//go:build linux + +package api + +import ( + "errors" + "os/exec" + + "golang.org/x/sys/unix" +) + +// Leave the exited leader waitable until capture ends. Its PID cannot be reused +// while we may still need to signal descendants in its process group. +func waitForProcessExit(cmd *exec.Cmd) error { + for { + err := unix.Waitid(unix.P_PID, cmd.Process.Pid, nil, unix.WEXITED|unix.WNOWAIT, nil) + if !errors.Is(err, unix.EINTR) { + return err + } + } +} + +func reapProcess(cmd *exec.Cmd) { _ = cmd.Wait() } diff --git a/server/cmd/api/api/process_wait_other.go b/server/cmd/api/api/process_wait_other.go new file mode 100644 index 00000000..0dc78994 --- /dev/null +++ b/server/cmd/api/api/process_wait_other.go @@ -0,0 +1,12 @@ +//go:build !linux + +package api + +import "os/exec" + +func waitForProcessExit(cmd *exec.Cmd) error { + _ = cmd.Wait() + return nil +} + +func reapProcess(cmd *exec.Cmd) {} diff --git a/server/cmd/api/main.go b/server/cmd/api/main.go index eff99bcb..02be4486 100644 --- a/server/cmd/api/main.go +++ b/server/cmd/api/main.go @@ -207,6 +207,7 @@ func main() { otlpExporter, s2Storage, egressPolicy, + api.ProcessOutputConfig{Dir: config.ProcessOutputDir, MaxBytes: config.ProcessOutputMaxBytes, TotalMaxBytes: config.ProcessOutputTotalMaxBytes}, ) if err != nil { slogger.Error("failed to create api service", "err", err) diff --git a/server/cmd/config/config.go b/server/cmd/config/config.go index 70cce914..4e554107 100644 --- a/server/cmd/config/config.go +++ b/server/cmd/config/config.go @@ -20,6 +20,10 @@ type Config struct { // external API surface. MetricsPort int `envconfig:"METRICS_PORT" default:"10002"` + ProcessOutputDir string `envconfig:"PROCESS_OUTPUT_DIR" default:""` + ProcessOutputMaxBytes int64 `envconfig:"PROCESS_OUTPUT_MAX_BYTES" default:"67108864"` + ProcessOutputTotalMaxBytes int64 `envconfig:"PROCESS_OUTPUT_TOTAL_MAX_BYTES" default:"268435456"` + // Recording configuration FrameRate int `envconfig:"FRAME_RATE" default:"10"` DisplayNum int `envconfig:"DISPLAY_NUM" default:"1"` @@ -90,6 +94,9 @@ func (c *Config) LogValue() slog.Value { return slog.GroupValue( slog.Int("port", c.Port), slog.Int("metrics_port", c.MetricsPort), + slog.String("process_output_dir", c.ProcessOutputDir), + slog.Int64("process_output_max_bytes", c.ProcessOutputMaxBytes), + slog.Int64("process_output_total_max_bytes", c.ProcessOutputTotalMaxBytes), slog.Int("frame_rate", c.FrameRate), slog.Int("display_num", c.DisplayNum), slog.Int("max_size_mb", c.MaxSizeInMB), diff --git a/server/lib/scaletozero/connection.go b/server/lib/scaletozero/connection.go index 2b7dbf4b..9e529be5 100644 --- a/server/lib/scaletozero/connection.go +++ b/server/lib/scaletozero/connection.go @@ -33,6 +33,7 @@ type drainConn struct { closing bool hijackedConn bool writeTimeout time.Duration + writeDeadline time.Time setDeadline func(*net.TCPConn, time.Time) error abortConnection func(*net.TCPConn) error } @@ -77,7 +78,7 @@ func (c *drainConn) Write(p []byte) (int, error) { return total + n, err } if timeout > 0 { - if err := setDeadline(c.TCPConn, time.Now().Add(timeout)); err != nil { + if err := c.refreshWriteDeadline(timeout, setDeadline); err != nil { c.abortNowWithOutcome(abort, responseDrainWriteError, err) return total, err } @@ -113,7 +114,7 @@ func (c *drainConn) ReadFrom(r io.Reader) (int64, error) { return total + n, err } if timeout > 0 { - if err := setDeadline(c.TCPConn, time.Now().Add(timeout)); err != nil { + if err := c.refreshWriteDeadline(timeout, setDeadline); err != nil { c.abortNowWithOutcome(abort, responseDrainWriteError, err) return total, err } @@ -145,6 +146,24 @@ func (c *drainConn) ReadFrom(r io.Reader) (int64, error) { } } +func (c *drainConn) SetWriteDeadline(deadline time.Time) error { + c.mu.Lock() + defer c.mu.Unlock() + c.writeDeadline = deadline + return c.TCPConn.SetWriteDeadline(deadline) +} + +func (c *drainConn) refreshWriteDeadline(timeout time.Duration, setDeadline func(*net.TCPConn, time.Time) error) error { + c.mu.Lock() + defer c.mu.Unlock() + deadline := time.Now().Add(timeout) + // ResponseController deadlines must survive the per-write timeout refresh. + if !c.writeDeadline.IsZero() && c.writeDeadline.Before(deadline) { + deadline = c.writeDeadline + } + return setDeadline(c.TCPConn, deadline) +} + func (c *drainConn) writeConfig() (time.Duration, func(*net.TCPConn, time.Time) error, func(*net.TCPConn) error, bool, error) { c.mu.Lock() defer c.mu.Unlock() From 719c2700b7bb8d2e17c7b9073f9733281559da6a Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Wed, 14 Oct 2026 21:58:52 +0000 Subject: [PATCH 03/10] Test and document process output lifecycles --- server/README.md | 1 + server/cmd/api/api/api_test.go | 2 +- server/cmd/api/api/display_test.go | 2 +- server/cmd/api/api/process_lifecycle_test.go | 401 +++++++++++++++++++ server/cmd/api/api/process_test.go | 2 +- server/cmd/api/api/telemetry_test.go | 2 +- server/cmd/config/config_test.go | 150 +++---- server/docs/processes.md | 35 ++ server/lib/scaletozero/middleware_test.go | 31 ++ 9 files changed, 552 insertions(+), 74 deletions(-) create mode 100644 server/cmd/api/api/process_lifecycle_test.go create mode 100644 server/docs/processes.md diff --git a/server/README.md b/server/README.md index bef0c9e0..79fb8c03 100644 --- a/server/README.md +++ b/server/README.md @@ -72,6 +72,7 @@ export OUTPUT_DIR=/tmp/recordings - **YAML Spec**: `GET /spec.yaml` - **JSON Spec**: `GET /spec.json` +- **Process execution guide**: [`docs/processes.md`](docs/processes.md) - **Browser REPL guide**: [`docs/repl.md`](docs/repl.md) ## 🔧 Development diff --git a/server/cmd/api/api/api_test.go b/server/cmd/api/api/api_test.go index 4300a454..4dbe32f9 100644 --- a/server/cmd/api/api/api_test.go +++ b/server/cmd/api/api/api_test.go @@ -408,7 +408,7 @@ func testEgressPolicy(t *testing.T) *egresspolicy.State { func newSvc(t *testing.T, mgr recorder.RecordManager) (*ApiService, error) { t.Helper() ts, es := newTelemetrySession(t) - return New(mgr, newMockFactory(), newTestUpstreamManager(), scaletozero.NewNoopController(), newMockNekoClient(t), ts, es, 0, nil, nil, testEgressPolicy(t)) + return New(mgr, newMockFactory(), newTestUpstreamManager(), scaletozero.NewNoopController(), newMockNekoClient(t), ts, es, 0, nil, nil, testEgressPolicy(t), ProcessOutputConfig{}) } func TestApiService_PatchChromiumFlags(t *testing.T) { diff --git a/server/cmd/api/api/display_test.go b/server/cmd/api/api/display_test.go index fd283b87..0bbcc387 100644 --- a/server/cmd/api/api/display_test.go +++ b/server/cmd/api/api/display_test.go @@ -36,7 +36,7 @@ func testFFmpegFactory(t *testing.T, tempDir string) recorder.FFmpegRecorderFact func newTestServiceWithFactory(t *testing.T, mgr recorder.RecordManager, factory recorder.FFmpegRecorderFactory) *ApiService { t.Helper() ts, es := newTelemetrySession(t) - svc, err := New(mgr, factory, newTestUpstreamManager(), scaletozero.NewNoopController(), newMockNekoClient(t), ts, es, 0, nil, nil, testEgressPolicy(t)) + svc, err := New(mgr, factory, newTestUpstreamManager(), scaletozero.NewNoopController(), newMockNekoClient(t), ts, es, 0, nil, nil, testEgressPolicy(t), ProcessOutputConfig{}) require.NoError(t, err) return svc } diff --git a/server/cmd/api/api/process_lifecycle_test.go b/server/cmd/api/api/process_lifecycle_test.go new file mode 100644 index 00000000..c546b656 --- /dev/null +++ b/server/cmd/api/api/process_lifecycle_test.go @@ -0,0 +1,401 @@ +package api + +import ( + "bufio" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "strconv" + "strings" + "syscall" + "testing" + "time" + + chiMiddleware "github.com/go-chi/chi/v5/middleware" + oapi "github.com/kernel/kernel-images/server/lib/oapi" + "github.com/stretchr/testify/require" +) + +func newProcessTestService(t *testing.T, config ProcessOutputConfig) *ApiService { + t.Helper() + budget, err := newProcessOutputBudget(config) + require.NoError(t, err) + ctx, cancel := context.WithCancel(context.Background()) + svc := &ApiService{processOutput: budget, lifecycleCtx: ctx, lifecycleCancel: cancel} + t.Cleanup(func() { + cancel() + svc.procMu.RLock() + handles := make([]*processHandle, 0, len(svc.procs)) + for _, h := range svc.procs { + handles = append(handles, h) + } + svc.procMu.RUnlock() + for _, h := range handles { + select { + case <-h.doneCh: + svc.releaseProcess(h) + case <-time.After(5 * time.Second): + t.Error("process did not stop during cleanup") + } + } + }) + return svc +} + +func spawnProcess(t *testing.T, svc *ApiService, command string, args ...string) oapi.ProcessSpawn200JSONResponse { + t.Helper() + resp, err := svc.ProcessSpawn(context.Background(), oapi.ProcessSpawnRequestObject{Body: &oapi.ProcessSpawnRequest{Command: command, Args: &args}}) + require.NoError(t, err) + spawn, ok := resp.(oapi.ProcessSpawn200JSONResponse) + require.True(t, ok, "unexpected spawn response: %T", resp) + + return spawn +} + +func processStream(t *testing.T, svc *ApiService, spawn oapi.ProcessSpawn200JSONResponse) io.ReadCloser { + t.Helper() + resp, err := svc.ProcessStdoutStream(context.Background(), oapi.ProcessStdoutStreamRequestObject{ProcessId: *spawn.ProcessId}) + require.NoError(t, err) + stream, ok := resp.(processStreamResponse) + require.True(t, ok, "unexpected stream response: %T", resp) + body := stream.Body.(io.ReadCloser) + timer := time.AfterFunc(20*time.Second, func() { _ = body.Close() }) + t.Cleanup(func() { timer.Stop(); _ = body.Close() }) + return body +} + +func collectProcessStream(t *testing.T, body io.Reader) (string, []oapi.ProcessStreamEvent) { + t.Helper() + var output strings.Builder + events := make([]oapi.ProcessStreamEvent, 0) + scanner := bufio.NewScanner(body) + for scanner.Scan() { + line := scanner.Text() + if !strings.HasPrefix(line, "data: ") { + continue + } + var event oapi.ProcessStreamEvent + require.NoError(t, json.Unmarshal([]byte(strings.TrimPrefix(line, "data: ")), &event)) + events = append(events, event) + if event.DataB64 != nil { + data, err := base64.StdEncoding.DecodeString(*event.DataB64) + require.NoError(t, err) + output.Write(data) + } + } + require.NoError(t, scanner.Err()) + return output.String(), events +} + +func waitProcessExit(t *testing.T, svc *ApiService, spawn oapi.ProcessSpawn200JSONResponse) { + t.Helper() + require.Eventually(t, func() bool { + resp, err := svc.ProcessStatus(context.Background(), oapi.ProcessStatusRequestObject{ProcessId: *spawn.ProcessId}) + if err != nil { + return false + } + status, ok := resp.(oapi.ProcessStatus200JSONResponse) + return ok && status.State != nil && *status.State == "exited" + }, 5*time.Second, 10*time.Millisecond, "process did not exit without a stream reader") +} + +func requireProcessExitEvent(t *testing.T, events []oapi.ProcessStreamEvent, code int) { + t.Helper() + require.NotEmpty(t, events) + last := events[len(events)-1] + require.NotNil(t, last.Event) + require.Equal(t, "exit", string(*last.Event)) + require.Equal(t, code, *last.ExitCode) + for _, event := range events[:len(events)-1] { + require.Nil(t, event.Event) + } +} + +func TestProcessOutputWithoutReaderAndReplay(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{}) + spawn := spawnProcess(t, svc, "head", "-c", "16777216", "/dev/zero") + waitProcessExit(t, svc, spawn) + for i := 0; i < 2; i++ { + output, events := collectProcessStream(t, processStream(t, svc, spawn)) + require.Equal(t, strings.Repeat("\x00", 16<<20), output) + requireProcessExitEvent(t, events, 0) + } +} + +func TestProcessStreamAfterExit(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{}) + for i := 0; i < 20; i++ { + spawn := spawnProcess(t, svc, "sh", "-c", "printf one; printf two >&2; exit 7") + waitProcessExit(t, svc, spawn) + output, events := collectProcessStream(t, processStream(t, svc, spawn)) + require.Contains(t, output, "one") + require.Contains(t, output, "two") + requireProcessExitEvent(t, events, 7) + } +} + +func TestProcessExecTimeoutIsNotServerError(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{}) + args, timeout := []string{"-c", "printf before; sleep 4; true"}, 1 + started := time.Now() + resp, err := svc.ProcessExec(context.Background(), oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "sh", Args: &args, TimeoutSec: &timeout}}) + require.NoError(t, err) + require.Less(t, time.Since(started), 3*time.Second) + rec := httptest.NewRecorder() + require.NoError(t, resp.VisitProcessExecResponse(rec)) + require.Equal(t, 422, rec.Code, rec.Body.String()) + var result struct { + Code string `json:"code"` + StdoutB64 string `json:"stdout_b64"` + } + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.Equal(t, "process_timeout", result.Code) + require.Equal(t, base64.StdEncoding.EncodeToString([]byte("before")), result.StdoutB64) +} + +func TestProcessSlowReaderAndResume(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{}) + spawn := spawnProcess(t, svc, "head", "-c", "2097152", "/dev/zero") + body := processStream(t, svc, spawn) + scanner := bufio.NewScanner(body) + var first oapi.ProcessStreamEvent + var lastID string + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), "id: ") { + lastID = strings.TrimPrefix(scanner.Text(), "id: ") + } + if strings.HasPrefix(scanner.Text(), "data: ") { + require.NoError(t, json.Unmarshal([]byte(strings.TrimPrefix(scanner.Text(), "data: ")), &first)) + break + } + } + require.NotNil(t, first.Offset) + require.Equal(t, strconv.FormatInt(*first.Offset, 10), lastID) + // Leave the first stream stalled while the producer finishes. + waitProcessExit(t, svc, spawn) + require.NoError(t, body.Close()) + firstData, err := base64.StdEncoding.DecodeString(*first.DataB64) + require.NoError(t, err) + for _, params := range []oapi.ProcessStdoutStreamParams{ + {LastEventID: &lastID}, + {Offset: first.Offset, LastEventID: ptrOf("ignored")}, + } { + resp, err := svc.ProcessStdoutStream(context.Background(), oapi.ProcessStdoutStreamRequestObject{ProcessId: *spawn.ProcessId, Params: params}) + require.NoError(t, err) + stream := resp.(processStreamResponse).Body.(io.ReadCloser) + output, events := collectProcessStream(t, stream) + require.NoError(t, stream.Close()) + require.Equal(t, strings.Repeat("\x00", 2<<20), string(firstData)+output) + requireProcessExitEvent(t, events, 0) + } + for _, offset := range []int64{-1, 1, 1 << 40} { + resp, err := svc.ProcessStdoutStream(context.Background(), oapi.ProcessStdoutStreamRequestObject{ProcessId: *spawn.ProcessId, Params: oapi.ProcessStdoutStreamParams{Offset: &offset}}) + require.NoError(t, err) + require.IsType(t, oapi.ProcessStdoutStream400JSONResponse{}, resp) + } +} + +func TestProcessSpawnTimeoutSurvivesRequestCancellation(t *testing.T) { + for _, tty := range []bool{false, true} { + t.Run(fmt.Sprintf("tty=%v", tty), func(t *testing.T) { + t.Parallel() + svc := newProcessTestService(t, ProcessOutputConfig{}) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + args := []string{"-c", "sleep 30"} + resp, err := svc.ProcessSpawn(ctx, oapi.ProcessSpawnRequestObject{Body: &oapi.ProcessSpawnRequest{Command: "sh", Args: &args, TimeoutSec: ptrOf(1), AllocateTty: &tty}}) + require.NoError(t, err) + spawn := resp.(oapi.ProcessSpawn200JSONResponse) + cancel() + _, events := collectProcessStream(t, processStream(t, svc, spawn)) + requireProcessExitEvent(t, events, -1) + require.Equal(t, oapi.ProcessTimeout, *events[len(events)-1].TerminationReason) + status, err := svc.ProcessStatus(context.Background(), oapi.ProcessStatusRequestObject{ProcessId: *spawn.ProcessId}) + require.NoError(t, err) + require.Equal(t, oapi.ProcessTimeout, *status.(oapi.ProcessStatus200JSONResponse).TerminationReason) + }) + } +} + +func TestProcessTimeoutStopsChildren(t *testing.T) { + t.Parallel() + svc := newProcessTestService(t, ProcessOutputConfig{}) + args := []string{"-c", "sleep 30 & echo $!; wait"} + resp, err := svc.ProcessExec(context.Background(), oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "sh", Args: &args, TimeoutSec: ptrOf(1)}}) + require.NoError(t, err) + failure := resp.(oapi.ProcessExec422JSONResponse) + require.Equal(t, oapi.ProcessTimeout, failure.Code) + data, err := base64.StdEncoding.DecodeString(*failure.StdoutB64) + require.NoError(t, err) + pid, err := strconv.Atoi(strings.TrimSpace(string(data))) + require.NoError(t, err) + require.Eventually(t, func() bool { + stat, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid)) + return os.IsNotExist(err) || strings.Contains(string(stat), ") Z ") + }, time.Second, 10*time.Millisecond, "child %d is still running", pid) +} + +func TestProcessDetachedChildDoesNotHoldExecResponse(t *testing.T) { + t.Parallel() + svc := newProcessTestService(t, ProcessOutputConfig{}) + pidFile := filepath.Join(t.TempDir(), "pid") + args := []string{"-c", `setsid sh -c 'echo $$ > "$1"; exec sleep 30' sh "$1" & wait`, "sh", pidFile} + t.Cleanup(func() { + data, err := os.ReadFile(pidFile) + if err == nil { + pid, err := strconv.Atoi(strings.TrimSpace(string(data))) + if err == nil { + _ = syscall.Kill(pid, syscall.SIGKILL) + } + } + }) + started := time.Now() + resp, err := svc.ProcessExec(context.Background(), oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "sh", Args: &args, TimeoutSec: ptrOf(1)}}) + require.NoError(t, err) + require.Less(t, time.Since(started), 4*time.Second) + failure := resp.(oapi.ProcessExec422JSONResponse) + require.Equal(t, oapi.ProcessTimeout, failure.Code) + require.True(t, *failure.OutputTruncated) +} + +func TestProcessOutputQuota(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{MaxBytes: 4096, TotalMaxBytes: 8192}) + for i := 0; i < 2; i++ { + spawn := spawnProcess(t, svc, "sh", "-c", "head -c 65536 /dev/zero; sleep 30") + output, events := collectProcessStream(t, processStream(t, svc, spawn)) + require.NotEmpty(t, output) + require.Less(t, len(output), 4096) + require.Equal(t, strings.Repeat("\x00", len(output)), output) + requireProcessExitEvent(t, events, -1) + require.Equal(t, oapi.OutputLimit, *events[len(events)-1].TerminationReason) + require.True(t, *events[len(events)-1].OutputTruncated) + } + + // Retained output consumes the shared budget until its retention expires. + args := []string{"-c", "printf more; sleep 30"} + resp, err := svc.ProcessExec(context.Background(), oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "sh", Args: &args}}) + require.NoError(t, err) + failure := resp.(oapi.ProcessExec422JSONResponse) + require.Equal(t, oapi.OutputLimit, failure.Code) + require.Empty(t, *failure.StdoutB64) +} + +func TestProcessRetentionExpiresWithStalledReader(t *testing.T) { + t.Parallel() + svc := newProcessTestService(t, ProcessOutputConfig{MaxBytes: 4096, TotalMaxBytes: 4096}) + spawn := spawnProcess(t, svc, "head", "-c", "65536", "/dev/zero") + body := processStream(t, svc, spawn) + waitProcessExit(t, svc, spawn) + require.Eventually(t, func() bool { + resp, err := svc.ProcessStatus(context.Background(), oapi.ProcessStatusRequestObject{ProcessId: *spawn.ProcessId}) + _, expired := resp.(oapi.ProcessStatus404JSONResponse) + return err == nil && expired + }, 12*time.Second, 20*time.Millisecond) + _, err := io.ReadAll(body) + require.Error(t, err, "stalled stream should close on expiration") + args := []string{"-c", "printf reclaimed"} + resp, err := svc.ProcessExec(context.Background(), oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "sh", Args: &args}}) + require.NoError(t, err) + result := resp.(oapi.ProcessExec200JSONResponse) + require.Equal(t, base64.StdEncoding.EncodeToString([]byte("reclaimed")), *result.StdoutB64) +} + +func TestProcessStorageFailureDoesNotRunCommand(t *testing.T) { + dir := t.TempDir() + svc := newProcessTestService(t, ProcessOutputConfig{Dir: filepath.Join(dir, "missing")}) + marker := filepath.Join(dir, "ran") + resp, err := svc.ProcessExec(context.Background(), oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "touch", Args: &[]string{marker}}}) + require.NoError(t, err) + require.IsType(t, oapi.ProcessExec500JSONResponse{}, resp) + _, err = os.Stat(marker) + require.True(t, os.IsNotExist(err)) +} + +func TestProcessTimeoutHTTPContract(t *testing.T) { + t.Parallel() + svc := newProcessTestService(t, ProcessOutputConfig{}) + server := httptest.NewServer(oapi.Handler(oapi.NewStrictHandler(svc, nil))) + defer server.Close() + client := &http.Client{Timeout: 5 * time.Second} + resp, err := client.Post(server.URL+"/process/exec", "application/json", strings.NewReader(`{"command":"sh","args":["-c","printf partial; sleep 30"],"timeout_sec":1}`)) + require.NoError(t, err) + defer resp.Body.Close() + require.Equal(t, http.StatusUnprocessableEntity, resp.StatusCode) + payload, err := io.ReadAll(resp.Body) + require.NoError(t, err) + var failure oapi.ProcessExecFailure + require.NoError(t, json.Unmarshal(payload, &failure)) + spec, err := oapi.GetSwagger() + require.NoError(t, err) + var document map[string]any + require.NoError(t, json.Unmarshal(payload, &document)) + schema := spec.Paths.Find("/process/exec").Post.Responses.Status(422).Value.Content["application/json"].Schema.Value + require.NoError(t, schema.VisitJSON(document)) + require.Equal(t, oapi.ProcessTimeout, failure.Code) + require.Equal(t, base64.StdEncoding.EncodeToString([]byte("partial")), *failure.StdoutB64) +} + +func TestProcessTimeoutAfterParentExitStopsChild(t *testing.T) { + t.Parallel() + svc := newProcessTestService(t, ProcessOutputConfig{}) + args := []string{"-c", "sleep 30 & echo $!"} + resp, err := svc.ProcessExec(context.Background(), oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "sh", Args: &args, TimeoutSec: ptrOf(1)}}) + require.NoError(t, err) + var output string + switch r := resp.(type) { + case oapi.ProcessExec422JSONResponse: + output = *r.StdoutB64 + case oapi.ProcessExec200JSONResponse: + output = *r.StdoutB64 + } + data, err := base64.StdEncoding.DecodeString(output) + require.NoError(t, err) + pid, err := strconv.Atoi(strings.TrimSpace(string(data))) + require.NoError(t, err) + t.Cleanup(func() { _ = syscall.Kill(pid, syscall.SIGKILL) }) + require.IsType(t, oapi.ProcessExec422JSONResponse{}, resp) + require.Equal(t, oapi.ProcessTimeout, resp.(oapi.ProcessExec422JSONResponse).Code) + require.Eventually(t, func() bool { + stat, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid)) + return os.IsNotExist(err) || strings.Contains(string(stat), ") Z ") + }, time.Second, 10*time.Millisecond, "child %d is still running", pid) +} + +func TestProcessRetentionStopsBlockedHTTPStream(t *testing.T) { + t.Parallel() + svc := newProcessTestService(t, ProcessOutputConfig{}) + spawn := spawnProcess(t, svc, "head", "-c", "16777216", "/dev/zero") + finished := make(chan struct{}) + handler := chiMiddleware.Logger(oapi.Handler(oapi.NewStrictHandler(svc, nil))) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + defer close(finished) + handler.ServeHTTP(w, r) + })) + defer server.Close() + conn, err := net.Dial("tcp", strings.TrimPrefix(server.URL, "http://")) + require.NoError(t, err) + defer conn.Close() + require.NoError(t, conn.(*net.TCPConn).SetReadBuffer(1024)) + require.NoError(t, conn.SetReadDeadline(time.Now().Add(5*time.Second))) + _, err = fmt.Fprintf(conn, "GET /process/%s/stdout/stream HTTP/1.1\r\nHost: localhost\r\n\r\n", spawn.ProcessId.String()) + require.NoError(t, err) + status, err := bufio.NewReader(conn).ReadString('\n') + require.NoError(t, err) + require.Contains(t, status, "200") + waitProcessExit(t, svc, spawn) + select { + case <-finished: + case <-time.After(12 * time.Second): + t.Fatal("HTTP stream stayed blocked after output retention expired") + } + resp, err := svc.ProcessStatus(context.Background(), oapi.ProcessStatusRequestObject{ProcessId: *spawn.ProcessId}) + require.NoError(t, err) + require.IsType(t, oapi.ProcessStatus404JSONResponse{}, resp) +} diff --git a/server/cmd/api/api/process_test.go b/server/cmd/api/api/process_test.go index 741734d7..845c0567 100644 --- a/server/cmd/api/api/process_test.go +++ b/server/cmd/api/api/process_test.go @@ -66,7 +66,7 @@ func TestProcessSpawnStatusAndStream(t *testing.T) { // Start stream reader and collect at least two data events and one exit event streamResp, err := svc.ProcessStdoutStream(ctx, oapi.ProcessStdoutStreamRequestObject{ProcessId: *s200.ProcessId}) require.NoError(t, err, "StdoutStream error") - st200, ok := streamResp.(oapi.ProcessStdoutStream200TexteventStreamResponse) + st200, ok := streamResp.(processStreamResponse) require.True(t, ok, "unexpected stream resp: %T", streamResp) reader := bufio.NewReader(st200.Body) diff --git a/server/cmd/api/api/telemetry_test.go b/server/cmd/api/api/telemetry_test.go index ca71f956..f039b371 100644 --- a/server/cmd/api/api/telemetry_test.go +++ b/server/cmd/api/api/telemetry_test.go @@ -409,7 +409,7 @@ func (m *mockRecordManager) StopAll(_ context.Context) error func newTestService(t *testing.T, mgr recorder.RecordManager) *ApiService { t.Helper() ts, es := newTelemetrySession(t) - svc, err := New(mgr, newMockFactory(), newTestUpstreamManager(), scaletozero.NewNoopController(), newMockNekoClient(t), ts, es, 0, nil, nil, testEgressPolicy(t)) + svc, err := New(mgr, newMockFactory(), newTestUpstreamManager(), scaletozero.NewNoopController(), newMockNekoClient(t), ts, es, 0, nil, nil, testEgressPolicy(t), ProcessOutputConfig{}) require.NoError(t, err) svc.cdpMonitor = &stubCdpMonitor{} return svc diff --git a/server/cmd/config/config_test.go b/server/cmd/config/config_test.go index eda4e366..a1c5598b 100644 --- a/server/cmd/config/config_test.go +++ b/server/cmd/config/config_test.go @@ -18,64 +18,72 @@ func TestLoad(t *testing.T) { name: "defaults (no env set)", env: map[string]string{}, wantCfg: &Config{ - Port: 10001, - MetricsPort: 10002, - FrameRate: 10, - DisplayNum: 1, - MaxSizeInMB: 500, - OutputDir: ".", - AudioSource: "", - PulseServer: "", - PathToFFmpeg: "ffmpeg", - DevToolsProxyPort: 9222, - ScaleToZeroCooldown: time.Second, - ChromeDriverProxyPort: 9224, - ChromeDriverUpstreamAddr: "127.0.0.1:9225", - DevToolsProxyAddr: "127.0.0.1:9222", - OTLPPath: "/v1/logs", - OTLPServiceName: "kernel-browser", - OTLPMaxQueueSize: 2048, - OTLPExportInterval: time.Second, - OTLPExportTimeout: 30 * time.Second, + Port: 10001, + ProcessOutputMaxBytes: 67108864, + ProcessOutputTotalMaxBytes: 268435456, + MetricsPort: 10002, + FrameRate: 10, + DisplayNum: 1, + MaxSizeInMB: 500, + OutputDir: ".", + AudioSource: "", + PulseServer: "", + PathToFFmpeg: "ffmpeg", + DevToolsProxyPort: 9222, + ScaleToZeroCooldown: time.Second, + ChromeDriverProxyPort: 9224, + ChromeDriverUpstreamAddr: "127.0.0.1:9225", + DevToolsProxyAddr: "127.0.0.1:9222", + OTLPPath: "/v1/logs", + OTLPServiceName: "kernel-browser", + OTLPMaxQueueSize: 2048, + OTLPExportInterval: time.Second, + OTLPExportTimeout: 30 * time.Second, }, }, { name: "custom valid env", env: map[string]string{ - "PORT": "12345", - "METRICS_PORT": "12346", - "FRAME_RATE": "20", - "DISPLAY_NUM": "2", - "MAX_SIZE_MB": "250", - "OUTPUT_DIR": "/tmp", - "AUDIO_SOURCE": "CustomOutput.monitor", - "PULSE_SERVER": "unix:/tmp/pulse/native", - "FFMPEG_PATH": "/usr/local/bin/ffmpeg", - "DEVTOOLS_PROXY_PORT": "9876", - "SCALE_TO_ZERO_COOLDOWN": "5s", - "CHROMEDRIVER_PROXY_PORT": "5432", - "CHROMEDRIVER_UPSTREAM_ADDR": "127.0.0.1:9999", + "PORT": "12345", + "PROCESS_OUTPUT_DIR": "/tmp/process-output", + "PROCESS_OUTPUT_MAX_BYTES": "1048576", + "PROCESS_OUTPUT_TOTAL_MAX_BYTES": "4194304", + "METRICS_PORT": "12346", + "FRAME_RATE": "20", + "DISPLAY_NUM": "2", + "MAX_SIZE_MB": "250", + "OUTPUT_DIR": "/tmp", + "AUDIO_SOURCE": "CustomOutput.monitor", + "PULSE_SERVER": "unix:/tmp/pulse/native", + "FFMPEG_PATH": "/usr/local/bin/ffmpeg", + "DEVTOOLS_PROXY_PORT": "9876", + "SCALE_TO_ZERO_COOLDOWN": "5s", + "CHROMEDRIVER_PROXY_PORT": "5432", + "CHROMEDRIVER_UPSTREAM_ADDR": "127.0.0.1:9999", }, wantCfg: &Config{ - Port: 12345, - MetricsPort: 12346, - FrameRate: 20, - DisplayNum: 2, - MaxSizeInMB: 250, - OutputDir: "/tmp", - AudioSource: "CustomOutput.monitor", - PulseServer: "unix:/tmp/pulse/native", - PathToFFmpeg: "/usr/local/bin/ffmpeg", - DevToolsProxyPort: 9876, - ScaleToZeroCooldown: 5 * time.Second, - ChromeDriverProxyPort: 5432, - ChromeDriverUpstreamAddr: "127.0.0.1:9999", - DevToolsProxyAddr: "127.0.0.1:9876", - OTLPPath: "/v1/logs", - OTLPServiceName: "kernel-browser", - OTLPMaxQueueSize: 2048, - OTLPExportInterval: time.Second, - OTLPExportTimeout: 30 * time.Second, + Port: 12345, + ProcessOutputDir: "/tmp/process-output", + ProcessOutputMaxBytes: 1048576, + ProcessOutputTotalMaxBytes: 4194304, + MetricsPort: 12346, + FrameRate: 20, + DisplayNum: 2, + MaxSizeInMB: 250, + OutputDir: "/tmp", + AudioSource: "CustomOutput.monitor", + PulseServer: "unix:/tmp/pulse/native", + PathToFFmpeg: "/usr/local/bin/ffmpeg", + DevToolsProxyPort: 9876, + ScaleToZeroCooldown: 5 * time.Second, + ChromeDriverProxyPort: 5432, + ChromeDriverUpstreamAddr: "127.0.0.1:9999", + DevToolsProxyAddr: "127.0.0.1:9876", + OTLPPath: "/v1/logs", + OTLPServiceName: "kernel-browser", + OTLPMaxQueueSize: 2048, + OTLPExportInterval: time.Second, + OTLPExportTimeout: 30 * time.Second, }, }, { @@ -85,25 +93,27 @@ func TestLoad(t *testing.T) { "DEVTOOLS_PROXY_ADDR": "10.0.0.1:1234", }, wantCfg: &Config{ - Port: 10001, - MetricsPort: 10002, - FrameRate: 10, - DisplayNum: 1, - MaxSizeInMB: 500, - OutputDir: ".", - AudioSource: "", - PulseServer: "", - PathToFFmpeg: "ffmpeg", - DevToolsProxyPort: 7777, - ScaleToZeroCooldown: time.Second, - ChromeDriverProxyPort: 9224, - ChromeDriverUpstreamAddr: "127.0.0.1:9225", - DevToolsProxyAddr: "10.0.0.1:1234", - OTLPPath: "/v1/logs", - OTLPServiceName: "kernel-browser", - OTLPMaxQueueSize: 2048, - OTLPExportInterval: time.Second, - OTLPExportTimeout: 30 * time.Second, + Port: 10001, + ProcessOutputMaxBytes: 67108864, + ProcessOutputTotalMaxBytes: 268435456, + MetricsPort: 10002, + FrameRate: 10, + DisplayNum: 1, + MaxSizeInMB: 500, + OutputDir: ".", + AudioSource: "", + PulseServer: "", + PathToFFmpeg: "ffmpeg", + DevToolsProxyPort: 7777, + ScaleToZeroCooldown: time.Second, + ChromeDriverProxyPort: 9224, + ChromeDriverUpstreamAddr: "127.0.0.1:9225", + DevToolsProxyAddr: "10.0.0.1:1234", + OTLPPath: "/v1/logs", + OTLPServiceName: "kernel-browser", + OTLPMaxQueueSize: 2048, + OTLPExportInterval: time.Second, + OTLPExportTimeout: 30 * time.Second, }, }, { diff --git a/server/docs/processes.md b/server/docs/processes.md new file mode 100644 index 00000000..3e73bdcc --- /dev/null +++ b/server/docs/processes.md @@ -0,0 +1,35 @@ +# Process execution and output + +`POST /process/exec` waits for completion. `POST /process/spawn` returns a process ID immediately. Both accept `timeout_sec`; null or zero disables the deadline. A negative value is rejected. + +Non-TTY commands continuously capture stdout and stderr into temporary files, whether or not a client is streaming. Output capture does not wait for stream readers. TTY output continues to use the WebSocket attach endpoint. + +## Limits and retention + +| Environment variable | Default | Meaning | +| --- | --- | --- | +| `PROCESS_OUTPUT_DIR` | OS temporary directory | Existing writable directory for output files | +| `PROCESS_OUTPUT_MAX_BYTES` | 67108864 (64 MiB) | Maximum stored output per process | +| `PROCESS_OUTPUT_TOTAL_MAX_BYTES` | 268435456 (256 MiB) | Maximum stored output across running and retained processes | + +Limits count stdout, stderr, and record headers. Zero selects the default. The per-process limit must exceed 13 bytes and the aggregate limit must be at least the per-process limit. These limits bound stored file bytes, not filesystem block allocation or the memory needed to serialize an exec response. + +Exceeding either limit stops the producing process group and reports `output_limit` with `output_truncated: true`. Already captured output remains available. A storage failure reports `output_error`. + +Spawned process status and output remain available for 10 seconds after capture completes. Expiration releases the storage budget and closes active streams, even if a reader has stalled. Exec releases its stored output when its result has been assembled. Output is temporary and does not survive a server restart. + +## Streaming and reconnecting + +`GET /process/{process_id}/stdout/stream` replays captured output from the beginning, then follows new output. Each connection reads independently. Data events include an opaque `offset`, also emitted as the SSE `id`. To resume after a data event, send its cursor as `?offset=...` or the `Last-Event-ID` header. The query parameter takes precedence. Invalid cursors return 400; expired processes return 404. + +An `exit` event follows all captured output and includes `exit_code`, `output_truncated`, and, when execution was stopped by the server, `termination_reason`. Clients must check the terminal event to distinguish complete capture from partial output. Reconnection does not extend retention. + +## Timeouts and cancellation + +A timeout or exec request cancellation sends SIGKILL to the command's process group. Ordinary child processes in that group are included. A descendant that deliberately creates its own session or process group can survive. After the direct child exits, capture drains for at most one additional second; pipes still held open at that point are closed, remaining processes in the original group are killed, and the result is marked `output_truncated`. + +An exec timeout returns HTTP 422 with `code: process_timeout`, `message`, `exit_code`, `duration_ms`, and partial `stdout_b64` / `stderr_b64`. Output quota, capture failure, and cancellation also use 422, with `output_limit`, `output_error`, or `process_canceled`. These execution failures must not be retried automatically because the command may already have performed side effects. An ordinary nonzero command exit remains HTTP 200 with its exit code. + +Spawn keeps running after its HTTP request ends, but still honors its execution timeout and server shutdown. Status and the stream's exit event report why it stopped. + +These are the image server's HTTP contracts. Callers that proxy this API must forward `timeout_sec`, preserve 422 responses and their fields, and forward replay cursors to expose the same behavior. diff --git a/server/lib/scaletozero/middleware_test.go b/server/lib/scaletozero/middleware_test.go index a0304cb6..a6ca985c 100644 --- a/server/lib/scaletozero/middleware_test.go +++ b/server/lib/scaletozero/middleware_test.go @@ -686,3 +686,34 @@ func (c *signalController) Enable(context.Context) error { c.once.Do(func() { c.enabled <- time.Now() }) return nil } + +func TestMiddlewarePreservesHandlerWriteDeadline(t *testing.T) { + handlerDone := make(chan error, 1) + handler := middleware(NewNoopController(), testDrainConfig(5*time.Minute, outboundQueue))(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if err := http.NewResponseController(w).SetWriteDeadline(time.Now()); err != nil { + handlerDone <- err + return + } + _, err := io.Copy(w, bytes.NewReader(make([]byte, 32<<20))) + handlerDone <- err + })) + listener, serverDone, server := serveTestHandler(t, handler) + defer func() { + require.NoError(t, server.Close()) + assert.ErrorIs(t, <-serverDone, http.ErrServerClosed) + }() + conn, err := net.Dial("tcp", listener.Addr().String()) + require.NoError(t, err) + defer conn.Close() + require.NoError(t, conn.(*net.TCPConn).SetReadBuffer(1024)) + _, err = fmt.Fprint(conn, "GET /stream HTTP/1.1\r\nHost: test\r\n\r\n") + require.NoError(t, err) + select { + case err := <-handlerDone: + var timeout net.Error + require.ErrorAs(t, err, &timeout) + require.True(t, timeout.Timeout()) + case <-time.After(time.Second): + t.Fatal("connection overwrote the handler's expired write deadline") + } +} From e19584623253d74bf917141c872efe0aa0049400 Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Thu, 15 Oct 2026 00:01:53 +0000 Subject: [PATCH 04/10] Preserve cursorless streams and finalize process status --- server/cmd/api/api/process.go | 161 +++++++++++------------ server/cmd/api/api/process_output.go | 54 ++++++-- server/cmd/api/api/process_runner.go | 40 +++--- server/cmd/api/api/process_wait_linux.go | 3 +- server/docs/processes.md | 6 +- server/openapi.yaml | 12 +- 6 files changed, 155 insertions(+), 121 deletions(-) diff --git a/server/cmd/api/api/process.go b/server/cmd/api/api/process.go index 2db90150..b8b910b7 100644 --- a/server/cmd/api/api/process.go +++ b/server/cmd/api/api/process.go @@ -227,8 +227,11 @@ func (s *ApiService) ProcessSpawn(ctx context.Context, request oapi.ProcessSpawn } tty := body.AllocateTty != nil && *body.AllocateTty if tty { - if (body.Rows != nil && (*body.Rows < 1 || *body.Rows > 65535)) || (body.Cols != nil && (*body.Cols < 1 || *body.Cols > 65535)) { - return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "rows and cols must be between 1 and 65535"}}, nil + if body.Rows != nil && *body.Rows > 65535 { + return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "rows must be <= 65535"}}, nil + } + if body.Cols != nil && *body.Cols > 65535 { + return oapi.ProcessSpawn400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "cols must be <= 65535"}}, nil } hasTerm := false for _, env := range cmd.Env { @@ -249,7 +252,7 @@ func (s *ApiService) ProcessSpawn(ctx context.Context, request oapi.ProcessSpawn logger.FromContext(ctx).Error("failed to start process", "err", err) return oapi.ProcessSpawn500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to start process"}}, nil } - if tty && body.Rows != nil && body.Cols != nil { + if tty && body.Rows != nil && *body.Rows > 0 && body.Cols != nil && *body.Cols > 0 { _ = pty.Setsize(h.ptyFile, &pty.Winsize{Rows: uint16(*body.Rows), Cols: uint16(*body.Cols)}) } go s.retainProcess(h) @@ -289,7 +292,7 @@ func (s *ApiService) ProcessKill(ctx context.Context, request oapi.ProcessKillRe if h.exitCode != nil { return oapi.ProcessKill404JSONResponse{NotFoundErrorJSONResponse: oapi.NotFoundErrorJSONResponse{Message: "process not running"}}, nil } - if err := signalChildProcessGroup(h.cmd, sig); err != nil { + if err := h.cmd.Process.Signal(sig); err != nil { log.Error("failed to signal process", "err", err) return oapi.ProcessKill500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to signal process"}}, nil } @@ -390,76 +393,17 @@ func (s *ApiService) ProcessStdoutStream(ctx context.Context, request oapi.Proce if err != nil || h.output.validateOffset(offset) != nil { return oapi.ProcessStdoutStream400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "invalid output offset"}}, nil } - ctx, cancel := context.WithCancel(ctx) - pr, pw := io.Pipe() - finished := make(chan struct{}) - go func() { - select { - case <-ctx.Done(): - pw.CloseWithError(ctx.Err()) - case <-h.output.closed: - pw.CloseWithError(os.ErrClosed) - case <-finished: - } - }() - go func() { - defer close(finished) - defer cancel() - defer pw.Close() - writeEvent := func(event oapi.ProcessStreamEvent) error { - data, err := json.Marshal(event) - if err != nil { - return err - } - if event.Offset != nil { - if _, err := fmt.Fprintf(pw, "id: %d\n", *event.Offset); err != nil { - return err - } - } - _, err = fmt.Fprintf(pw, "data: %s\n\n", data) - return err - } - for { - stream, data, next, err := h.output.next(ctx, offset) - if errors.Is(err, io.EOF) { - <-h.doneCh - h.mu.RLock() - code, reason, truncated := *h.exitCode, h.reason, h.truncated - h.mu.RUnlock() - event := oapi.ProcessStreamEvent{Event: ptrOf(oapi.Exit), ExitCode: &code, OutputTruncated: &truncated} - if reason != "" { - event.TerminationReason = ptrOf(oapi.ProcessTerminationReason(reason)) - } - _ = writeEvent(event) - return - } - if err != nil { - pw.CloseWithError(err) - return - } - source := oapi.ProcessStreamEventStream("stdout") - if stream == 1 { - source = "stderr" - } - event := oapi.ProcessStreamEvent{Stream: &source, DataB64: ptrOf(base64.StdEncoding.EncodeToString(data)), Offset: &next} - if writeEvent(event) != nil { - return - } - offset = next - } - }() return processStreamResponse{ - ProcessStdoutStream200TexteventStreamResponse: oapi.ProcessStdoutStream200TexteventStreamResponse{ - Body: &processStreamReader{PipeReader: pr, cancel: cancel}, - Headers: oapi.ProcessStdoutStream200ResponseHeaders{XSSEContentType: "application/json"}, - }, - expired: h.output.closed, + ctx: ctx, process: h, offset: offset, + replay: request.Params.Offset != nil || request.Params.LastEventID != nil, }, nil } type processStreamResponse struct { - oapi.ProcessStdoutStream200TexteventStreamResponse - expired <-chan struct{} + ctx context.Context + process *processHandle + offset int64 + replay bool } func (r processStreamResponse) VisitProcessStdoutStreamResponse(w http.ResponseWriter) error { @@ -468,27 +412,82 @@ func (r processStreamResponse) VisitProcessStdoutStreamResponse(w http.ResponseW go func() { defer close(stopped) select { - case <-r.expired: - // Closing the source does not interrupt a network write already in progress. - _ = controller.SetWriteDeadline(time.Now()) + case <-r.process.output.closed: + case <-r.ctx.Done(): case <-finished: + return } + // Interrupt a network write already in progress on expiry or disconnect. + _ = controller.SetWriteDeadline(time.Now()) }() defer func() { close(finished) <-stopped }() - return r.ProcessStdoutStream200TexteventStreamResponse.VisitProcessStdoutStreamResponse(w) -} - -type processStreamReader struct { - *io.PipeReader - cancel context.CancelFunc + w.Header().Set("Content-Type", "text/event-stream") + w.Header().Set("X-SSE-Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + if err := controller.Flush(); err != nil { + return err + } + for { + var stream byte + var data []byte + var next int64 + var err error + if r.replay { + stream, data, next, err = r.process.output.next(r.ctx, r.offset) + } else { + stream, data, next, err = r.process.output.nextUnread(r.ctx) + } + if errors.Is(err, errProcessOutputConsumed) { + return nil + } + var event oapi.ProcessStreamEvent + if errors.Is(err, io.EOF) { + h := r.process + <-h.doneCh + h.mu.RLock() + code, reason, truncated := *h.exitCode, h.reason, h.truncated + h.mu.RUnlock() + event = oapi.ProcessStreamEvent{Event: ptrOf(oapi.Exit), ExitCode: &code, OutputTruncated: &truncated} + if reason != "" { + event.TerminationReason = ptrOf(oapi.ProcessTerminationReason(reason)) + } + } else if err != nil { + return err + } else { + source := oapi.ProcessStreamEventStream("stdout") + if stream == 1 { + source = "stderr" + } + event = oapi.ProcessStreamEvent{Stream: &source, DataB64: ptrOf(base64.StdEncoding.EncodeToString(data)), Offset: &next} + } + if err := writeProcessEvent(w, event); err != nil { + return err + } + if err := controller.Flush(); err != nil { + return err + } + if event.Event != nil { + return nil + } + r.offset = next + } } -func (r *processStreamReader) Close() error { - r.cancel() - return r.PipeReader.Close() +func writeProcessEvent(w io.Writer, event oapi.ProcessStreamEvent) error { + data, err := json.Marshal(event) + if err != nil { + return err + } + if event.Offset != nil { + if _, err := fmt.Fprintf(w, "id: %d\n", *event.Offset); err != nil { + return err + } + } + _, err = fmt.Fprintf(w, "data: %s\n\n", data) + return err } func ptrOf[T any](v T) *T { return &v } diff --git a/server/cmd/api/api/process_output.go b/server/cmd/api/api/process_output.go index 14e71673..605f0f2e 100644 --- a/server/cmd/api/api/process_output.go +++ b/server/cmd/api/api/process_output.go @@ -16,6 +16,7 @@ const ( ) var errProcessOutputLimit = errors.New("process output limit exceeded") +var errProcessOutputConsumed = errors.New("process output already consumed") var errProcessOutputOffset = errors.New("invalid process output offset") // ProcessOutputConfig bounds stored output, including record headers. Zero limits @@ -60,16 +61,18 @@ func (b *processOutputBudget) release(n int64) { } type processOutput struct { - mu sync.Mutex - file *os.File - budget *processOutputBudget - size int64 - allocated int64 - complete bool - err error - changed chan struct{} - closed chan struct{} - closeOnce sync.Once + mu sync.Mutex + file *os.File + budget *processOutputBudget + size int64 + allocated int64 + complete bool + err error + changed chan struct{} + closed chan struct{} + closeOnce sync.Once + consumedOffset int64 + exitConsumed bool } func (b *processOutputBudget) open() (*processOutput, error) { @@ -136,8 +139,10 @@ func (o *processOutput) close() { o.mu.Lock() defer o.mu.Unlock() close(o.closed) - o.file.Close() - o.budget.release(o.allocated) + if o.file != nil { + o.file.Close() + o.budget.release(o.allocated) + } }) } @@ -199,3 +204,28 @@ func (o *processOutput) next(ctx context.Context, offset int64) (stream byte, da } } } + +// Cursorless streams share consumption, as with the original output queue. +func (o *processOutput) nextUnread(ctx context.Context) (byte, []byte, int64, error) { + for { + o.mu.Lock() + offset, consumed := o.consumedOffset, o.exitConsumed + o.mu.Unlock() + if consumed { + return 0, nil, offset, errProcessOutputConsumed + } + stream, data, next, err := o.next(ctx, offset) + if err != nil && !errors.Is(err, io.EOF) { + return 0, nil, offset, err + } + o.mu.Lock() + if o.consumedOffset != offset || o.exitConsumed { + o.mu.Unlock() + continue + } + o.consumedOffset = next + o.exitConsumed = errors.Is(err, io.EOF) + o.mu.Unlock() + return stream, data, next, err + } +} diff --git a/server/cmd/api/api/process_runner.go b/server/cmd/api/api/process_runner.go index b22f6946..7fcb08a7 100644 --- a/server/cmd/api/api/process_runner.go +++ b/server/cmd/api/api/process_runner.go @@ -26,9 +26,13 @@ func (s *ApiService) startProcess(ctx context.Context, cmd *exec.Cmd, tty, stdin } budget := s.processOutput s.procMu.Unlock() - output, err := budget.open() - if err != nil { - return nil, fmt.Errorf("create process output: %v", err) + output := &processOutput{changed: make(chan struct{}), closed: make(chan struct{})} + var err error + if !tty { + output, err = budget.open() + if err != nil { + return nil, fmt.Errorf("create process output: %v", err) + } } h := &processHandle{id: uuid.New(), cmd: cmd, started: time.Now(), isTTY: tty, output: output, doneCh: make(chan struct{})} if tty { @@ -194,30 +198,24 @@ func (h *processHandle) run(ctx, lifecycle context.Context, timeoutSec *int, rel drain = nil } } + close(failures) + for err := range failures { + h.outputFailed(err) + } + h.closeOutputPipes() + if h.stdin != nil { + h.stdin.Close() + } // Reap while holding the same lock used by signal requests, so no signal can - // target a reused PID between Wait and publishing the exit code. + // target a reused PID between Wait and publishing the final status. h.mu.Lock() reapProcess(h.cmd) code := h.cmd.ProcessState.ExitCode() + h.durationMs = int(time.Since(h.started) / time.Millisecond) h.exitCode = &code h.mu.Unlock() - h.closeOutputPipes() - if h.stdin != nil { - h.stdin.Close() - } - for { - select { - case err := <-failures: - h.outputFailed(err) - default: - h.mu.Lock() - h.durationMs = int(time.Since(h.started) / time.Millisecond) - h.mu.Unlock() - h.output.finish() - close(h.doneCh) - return - } - } + h.output.finish() + close(h.doneCh) } func (h *processHandle) captureOutput(stream byte, pipe io.Reader) error { diff --git a/server/cmd/api/api/process_wait_linux.go b/server/cmd/api/api/process_wait_linux.go index 6c275e35..da9b0f1f 100644 --- a/server/cmd/api/api/process_wait_linux.go +++ b/server/cmd/api/api/process_wait_linux.go @@ -12,8 +12,9 @@ import ( // Leave the exited leader waitable until capture ends. Its PID cannot be reused // while we may still need to signal descendants in its process group. func waitForProcessExit(cmd *exec.Cmd) error { + var info unix.Siginfo for { - err := unix.Waitid(unix.P_PID, cmd.Process.Pid, nil, unix.WEXITED|unix.WNOWAIT, nil) + err := unix.Waitid(unix.P_PID, cmd.Process.Pid, &info, unix.WEXITED|unix.WNOWAIT, nil) if !errors.Is(err, unix.EINTR) { return err } diff --git a/server/docs/processes.md b/server/docs/processes.md index 3e73bdcc..fcd979fb 100644 --- a/server/docs/processes.md +++ b/server/docs/processes.md @@ -20,7 +20,9 @@ Spawned process status and output remain available for 10 seconds after capture ## Streaming and reconnecting -`GET /process/{process_id}/stdout/stream` replays captured output from the beginning, then follows new output. Each connection reads independently. Data events include an opaque `offset`, also emitted as the SSE `id`. To resume after a data event, send its cursor as `?offset=...` or the `Last-Event-ID` header. The query parameter takes precedence. Invalid cursors return 400; expired processes return 404. +`GET /process/{process_id}/stdout/stream` without a cursor consumes the process's unread output, including output captured before the first connection. Reconnects continue at the shared consumed position and do not repeat a consumed exit event. Concurrent cursorless connections divide the output, as with the original queue. Consumption happens when a record is read for delivery; a disconnect can lose an in-flight record, so use explicit cursors when delivery must be resumable. + +Supplying `?offset=0` replays all retained output, then follows new output. Data events include an opaque `offset`, also emitted as the SSE `id`. To resume after a data event, send its cursor as `?offset=...` or the `Last-Event-ID` header. These explicit cursors read independently and do not advance cursorless consumption. The query parameter takes precedence. Invalid cursors return 400; expired processes return 404. An `exit` event follows all captured output and includes `exit_code`, `output_truncated`, and, when execution was stopped by the server, `termination_reason`. Clients must check the terminal event to distinguish complete capture from partial output. Reconnection does not extend retention. @@ -30,6 +32,8 @@ A timeout or exec request cancellation sends SIGKILL to the command's process gr An exec timeout returns HTTP 422 with `code: process_timeout`, `message`, `exit_code`, `duration_ms`, and partial `stdout_b64` / `stderr_b64`. Output quota, capture failure, and cancellation also use 422, with `output_limit`, `output_error`, or `process_canceled`. These execution failures must not be retried automatically because the command may already have performed side effects. An ordinary nonzero command exit remains HTTP 200 with its exit code. +Manual `/kill` requests continue to signal only the requested process, using the specified signal. + Spawn keeps running after its HTTP request ends, but still honors its execution timeout and server shutdown. Status and the stream's exit event report why it stopped. These are the image server's HTTP contracts. Callers that proxy this API must forward `timeout_sec`, preserve 422 responses and their fields, and forward replay cursors to expose the same behavior. diff --git a/server/openapi.yaml b/server/openapi.yaml index 46b63c75..aff12dbc 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -103,10 +103,12 @@ paths: get: summary: Stream retained process stdout and stderr over SSE description: | - Output is retained until 10 seconds after completion. Each connection replays - from the beginning unless an offset or Last-Event-ID from a previous data - event is supplied. Exit is sent after all retained output. Active streams - also end when retention expires. PTY output is available through attach. + Output is retained until 10 seconds after completion. Without a cursor, + connections share consumption: reconnects continue unread output and do not + repeat a consumed exit event. Supply offset=0 to replay from the beginning, + or an offset or Last-Event-ID from a previous data event to resume independently. + Exit follows the retained output. Active streams also end when retention + expires. PTY output is available through attach. operationId: processStdoutStream x-telemetry-category: platform parameters: @@ -118,7 +120,7 @@ paths: format: uuid - name: offset in: query - description: Resume cursor from a prior output event. Overrides Last-Event-ID. + description: Resume cursor from a prior output event, or 0 to replay all retained output. Overrides Last-Event-ID. schema: type: integer format: int64 From 45748d4bc6064d965d9cb8f22a270cfd303fbe3d Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Thu, 15 Oct 2026 00:01:53 +0000 Subject: [PATCH 05/10] Regenerate process stream API documentation --- server/lib/oapi/oapi.go | 1429 ++++++++++++++++++++------------------- 1 file changed, 715 insertions(+), 714 deletions(-) diff --git a/server/lib/oapi/oapi.go b/server/lib/oapi/oapi.go index 55e423cc..162ec914 100644 --- a/server/lib/oapi/oapi.go +++ b/server/lib/oapi/oapi.go @@ -7318,7 +7318,7 @@ type DeletePlaywrightExecutorParams struct { // ProcessStdoutStreamParams defines parameters for ProcessStdoutStream. type ProcessStdoutStreamParams struct { - // Offset Resume cursor from a prior output event. Overrides Last-Event-ID. + // Offset Resume cursor from a prior output event, or 0 to replay all retained output. Overrides Last-Event-ID. Offset *int64 `form:"offset,omitempty" json:"offset,omitempty"` // LastEventID Resume cursor from a prior SSE data event. @@ -26798,719 +26798,720 @@ func (sh *strictHandler) GetWebMCPTools(w http.ResponseWriter, r *http.Request, // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file From fe917f74e9527205d9961016fec7665e730c0a48 Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Thu, 15 Oct 2026 00:01:53 +0000 Subject: [PATCH 06/10] Test process lifecycle regressions in browser images --- server/cmd/api/api/process_lifecycle_test.go | 151 ++++++++++-- server/cmd/api/api/process_test.go | 7 +- server/cmd/api/api/process_wait_linux_test.go | 29 +++ server/e2e/e2e_process_test.go | 222 ++++++++++++++++++ 4 files changed, 387 insertions(+), 22 deletions(-) create mode 100644 server/cmd/api/api/process_wait_linux_test.go create mode 100644 server/e2e/e2e_process_test.go diff --git a/server/cmd/api/api/process_lifecycle_test.go b/server/cmd/api/api/process_lifecycle_test.go index c546b656..25a4c530 100644 --- a/server/cmd/api/api/process_lifecycle_test.go +++ b/server/cmd/api/api/process_lifecycle_test.go @@ -59,16 +59,21 @@ func spawnProcess(t *testing.T, svc *ApiService, command string, args ...string) return spawn } -func processStream(t *testing.T, svc *ApiService, spawn oapi.ProcessSpawn200JSONResponse) io.ReadCloser { +func processStream(t *testing.T, svc *ApiService, spawn oapi.ProcessSpawn200JSONResponse, params ...oapi.ProcessStdoutStreamParams) io.ReadCloser { t.Helper() - resp, err := svc.ProcessStdoutStream(context.Background(), oapi.ProcessStdoutStreamRequestObject{ProcessId: *spawn.ProcessId}) + server := httptest.NewServer(oapi.Handler(oapi.NewStrictHandler(svc, nil))) + t.Cleanup(server.Close) + client, err := oapi.NewClient(server.URL, oapi.WithHTTPClient(&http.Client{Timeout: 20 * time.Second})) + require.NoError(t, err) + var p oapi.ProcessStdoutStreamParams + if len(params) > 0 { + p = params[0] + } + resp, err := client.ProcessStdoutStream(context.Background(), *spawn.ProcessId, &p) require.NoError(t, err) - stream, ok := resp.(processStreamResponse) - require.True(t, ok, "unexpected stream response: %T", resp) - body := stream.Body.(io.ReadCloser) - timer := time.AfterFunc(20*time.Second, func() { _ = body.Close() }) - t.Cleanup(func() { timer.Stop(); _ = body.Close() }) - return body + require.Equal(t, http.StatusOK, resp.StatusCode) + t.Cleanup(func() { _ = resp.Body.Close() }) + return resp.Body } func collectProcessStream(t *testing.T, body io.Reader) (string, []oapi.ProcessStreamEvent) { @@ -123,7 +128,7 @@ func TestProcessOutputWithoutReaderAndReplay(t *testing.T) { spawn := spawnProcess(t, svc, "head", "-c", "16777216", "/dev/zero") waitProcessExit(t, svc, spawn) for i := 0; i < 2; i++ { - output, events := collectProcessStream(t, processStream(t, svc, spawn)) + output, events := collectProcessStream(t, processStream(t, svc, spawn, oapi.ProcessStdoutStreamParams{Offset: ptrOf(int64(0))})) require.Equal(t, strings.Repeat("\x00", 16<<20), output) requireProcessExitEvent(t, events, 0) } @@ -187,9 +192,7 @@ func TestProcessSlowReaderAndResume(t *testing.T) { {LastEventID: &lastID}, {Offset: first.Offset, LastEventID: ptrOf("ignored")}, } { - resp, err := svc.ProcessStdoutStream(context.Background(), oapi.ProcessStdoutStreamRequestObject{ProcessId: *spawn.ProcessId, Params: params}) - require.NoError(t, err) - stream := resp.(processStreamResponse).Body.(io.ReadCloser) + stream := processStream(t, svc, spawn, params) output, events := collectProcessStream(t, stream) require.NoError(t, stream.Close()) require.Equal(t, strings.Repeat("\x00", 2<<20), string(firstData)+output) @@ -287,19 +290,16 @@ func TestProcessOutputQuota(t *testing.T) { require.Empty(t, *failure.StdoutB64) } -func TestProcessRetentionExpiresWithStalledReader(t *testing.T) { +func TestProcessRetentionReclaimsOutputQuota(t *testing.T) { t.Parallel() svc := newProcessTestService(t, ProcessOutputConfig{MaxBytes: 4096, TotalMaxBytes: 4096}) spawn := spawnProcess(t, svc, "head", "-c", "65536", "/dev/zero") - body := processStream(t, svc, spawn) waitProcessExit(t, svc, spawn) require.Eventually(t, func() bool { resp, err := svc.ProcessStatus(context.Background(), oapi.ProcessStatusRequestObject{ProcessId: *spawn.ProcessId}) _, expired := resp.(oapi.ProcessStatus404JSONResponse) return err == nil && expired }, 12*time.Second, 20*time.Millisecond) - _, err := io.ReadAll(body) - require.Error(t, err, "stalled stream should close on expiration") args := []string{"-c", "printf reclaimed"} resp, err := svc.ProcessExec(context.Background(), oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "sh", Args: &args}}) require.NoError(t, err) @@ -399,3 +399,122 @@ func TestProcessRetentionStopsBlockedHTTPStream(t *testing.T) { require.NoError(t, err) require.IsType(t, oapi.ProcessStatus404JSONResponse{}, resp) } + +func TestProcessCursorlessReconnectDoesNotReplay(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{}) + spawn := spawnProcess(t, svc, "printf", "once") + output, events := collectProcessStream(t, processStream(t, svc, spawn)) + require.Equal(t, "once", output) + requireProcessExitEvent(t, events, 0) + output, events = collectProcessStream(t, processStream(t, svc, spawn)) + require.Empty(t, output) + require.Empty(t, events) +} + +func TestProcessTTYDoesNotRequireOutputStorage(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{Dir: filepath.Join(t.TempDir(), "missing")}) + resp, err := svc.ProcessSpawn(context.Background(), oapi.ProcessSpawnRequestObject{Body: &oapi.ProcessSpawnRequest{Command: "true", AllocateTty: ptrOf(true)}}) + require.NoError(t, err) + require.IsType(t, oapi.ProcessSpawn200JSONResponse{}, resp) + spawn := resp.(oapi.ProcessSpawn200JSONResponse) + waitProcessExit(t, svc, spawn) + _, events := collectProcessStream(t, processStream(t, svc, spawn)) + requireProcessExitEvent(t, events, 0) +} + +func TestProcessExitedStatusIncludesCaptureFailure(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{MaxBytes: 1024, TotalMaxBytes: 1024 * 100}) + for i := 0; i < 50; i++ { + spawn := spawnProcess(t, svc, "head", "-c", "8192", "/dev/zero") + require.Eventually(t, func() bool { + resp, err := svc.ProcessStatus(context.Background(), oapi.ProcessStatusRequestObject{ProcessId: *spawn.ProcessId}) + require.NoError(t, err) + status := resp.(oapi.ProcessStatus200JSONResponse) + if *status.State != "exited" { + return false + } + require.NotNil(t, status.TerminationReason) + require.Equal(t, oapi.OutputLimit, *status.TerminationReason) + require.True(t, *status.OutputTruncated) + return true + }, time.Second, time.Millisecond) + } +} + +func TestProcessCursorlessReconnectContinuesUnreadOutput(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{}) + spawn := spawnProcess(t, svc, "sh", "-c", "printf first; read line; printf second") + finished := make(chan struct{}) + handler := oapi.Handler(oapi.NewStrictHandler(svc, nil)) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + defer close(finished) + handler.ServeHTTP(w, r) + })) + defer server.Close() + client := &http.Client{Timeout: 5 * time.Second} + resp, err := client.Get(server.URL + "/process/" + spawn.ProcessId.String() + "/stdout/stream") + require.NoError(t, err) + body := resp.Body + defer body.Close() + scanner := bufio.NewScanner(body) + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), "data: ") { + var event oapi.ProcessStreamEvent + require.NoError(t, json.Unmarshal([]byte(strings.TrimPrefix(scanner.Text(), "data: ")), &event)) + require.Equal(t, base64.StdEncoding.EncodeToString([]byte("first")), *event.DataB64) + break + } + } + require.NoError(t, scanner.Err()) + require.NoError(t, body.Close()) + select { + case <-finished: + case <-time.After(time.Second): + t.Fatal("disconnected stream did not stop") + } + _, err = svc.ProcessStdin(context.Background(), oapi.ProcessStdinRequestObject{ProcessId: *spawn.ProcessId, Body: &oapi.ProcessStdinRequest{DataB64: base64.StdEncoding.EncodeToString([]byte("go\n"))}}) + require.NoError(t, err) + output, events := collectProcessStream(t, processStream(t, svc, spawn)) + require.Equal(t, "second", output) + requireProcessExitEvent(t, events, 0) + replay, replayEvents := collectProcessStream(t, processStream(t, svc, spawn, oapi.ProcessStdoutStreamParams{Offset: ptrOf(int64(0))})) + require.Equal(t, "firstsecond", replay) + requireProcessExitEvent(t, replayEvents, 0) +} + +func TestProcessManualSignalTargetsLeader(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{}) + spawn := spawnProcess(t, svc, "sh", "-c", `trap 'printf parent-signal; exit 17' HUP +sh -c 'trap "printf child-signal" HUP; printf ready; while :; do sleep 1; done' & +wait`) + body := processStream(t, svc, spawn) + scanner := bufio.NewScanner(body) + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), "data: ") { + var event oapi.ProcessStreamEvent + require.NoError(t, json.Unmarshal([]byte(strings.TrimPrefix(scanner.Text(), "data: ")), &event)) + require.Equal(t, base64.StdEncoding.EncodeToString([]byte("ready")), *event.DataB64) + break + } + } + require.NoError(t, scanner.Err()) + response, err := svc.ProcessKill(context.Background(), oapi.ProcessKillRequestObject{ProcessId: *spawn.ProcessId, Body: &oapi.ProcessKillRequest{Signal: "HUP"}}) + require.NoError(t, err) + require.IsType(t, oapi.ProcessKill200JSONResponse{}, response) + var output strings.Builder + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), "data: ") { + var event oapi.ProcessStreamEvent + require.NoError(t, json.Unmarshal([]byte(strings.TrimPrefix(scanner.Text(), "data: ")), &event)) + if event.DataB64 != nil { + data, err := base64.StdEncoding.DecodeString(*event.DataB64) + require.NoError(t, err) + output.Write(data) + } else { + require.Equal(t, 17, *event.ExitCode) + } + } + } + require.NoError(t, scanner.Err()) + require.Equal(t, "parent-signal", output.String()) +} diff --git a/server/cmd/api/api/process_test.go b/server/cmd/api/api/process_test.go index 845c0567..ed90a48a 100644 --- a/server/cmd/api/api/process_test.go +++ b/server/cmd/api/api/process_test.go @@ -64,12 +64,7 @@ func TestProcessSpawnStatusAndStream(t *testing.T) { require.True(t, ok, "unexpected status resp: %T", statusResp) // Start stream reader and collect at least two data events and one exit event - streamResp, err := svc.ProcessStdoutStream(ctx, oapi.ProcessStdoutStreamRequestObject{ProcessId: *s200.ProcessId}) - require.NoError(t, err, "StdoutStream error") - st200, ok := streamResp.(processStreamResponse) - require.True(t, ok, "unexpected stream resp: %T", streamResp) - - reader := bufio.NewReader(st200.Body) + reader := bufio.NewReader(processStream(t, svc, s200)) var gotStdout, gotStderr, gotExit bool deadline := time.Now().Add(2 * time.Second) for time.Now().Before(deadline) && !(gotStdout && gotStderr && gotExit) { diff --git a/server/cmd/api/api/process_wait_linux_test.go b/server/cmd/api/api/process_wait_linux_test.go new file mode 100644 index 00000000..46912612 --- /dev/null +++ b/server/cmd/api/api/process_wait_linux_test.go @@ -0,0 +1,29 @@ +//go:build linux + +package api + +import ( + "fmt" + "os" + "os/exec" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestProcessWaitPreservesExitedLeader(t *testing.T) { + cmd := exec.Command("sh", "-c", "exit 37") + require.NoError(t, cmd.Start()) + defer cmd.Wait() + require.Eventually(t, func() bool { + stat, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", cmd.Process.Pid)) + return err == nil && strings.Contains(string(stat), ") Z ") + }, time.Second, time.Millisecond) + require.NoError(t, waitForProcessExit(cmd)) + require.NoError(t, waitForProcessExit(cmd), "observing exit must not reap the leader") + reapProcess(cmd) + require.NotNil(t, cmd.ProcessState) + require.Equal(t, 37, cmd.ProcessState.ExitCode()) +} diff --git a/server/e2e/e2e_process_test.go b/server/e2e/e2e_process_test.go new file mode 100644 index 00000000..9def1637 --- /dev/null +++ b/server/e2e/e2e_process_test.go @@ -0,0 +1,222 @@ +package e2e + +import ( + "bufio" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "net/http" + "strconv" + "strings" + "testing" + "time" + + "github.com/coder/websocket" + oapi "github.com/kernel/kernel-images/server/lib/oapi" + "github.com/samber/lo" + "github.com/stretchr/testify/require" +) + +func TestProcessLifecycle(t *testing.T) { + for _, image := range []string{headlessImage, headfulImage} { + t.Run(image, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) + defer cancel() + c := NewTestContainer(t, image) + require.NoError(t, c.Start(ctx, ContainerConfig{Env: map[string]string{ + "PROCESS_OUTPUT_MAX_BYTES": "8388608", "PROCESS_OUTPUT_TOTAL_MAX_BYTES": "16777216", + }})) + defer c.Stop(context.Background()) + require.NoError(t, c.WaitReady(ctx)) + client, err := c.APIClient() + require.NoError(t, err) + + t.Run("fast exits preserve status", func(t *testing.T) { + for i := 0; i < 20; i++ { + result, err := client.ProcessExecWithResponse(ctx, oapi.ProcessExecRequest{Command: "sh", Args: lo.ToPtr([]string{"-c", fmt.Sprintf("printf out; printf err >&2; exit %d", i)})}) + require.NoError(t, err) + require.Equal(t, http.StatusOK, result.StatusCode(), "%s", result.Body) + require.Equal(t, i, *result.JSON200.ExitCode) + require.Equal(t, "b3V0", *result.JSON200.StdoutB64) + require.Equal(t, "ZXJy", *result.JSON200.StderrB64) + } + }) + + t.Run("unread output and explicit replay", func(t *testing.T) { + spawn, err := client.ProcessSpawnWithResponse(ctx, oapi.ProcessSpawnRequest{Command: "sh", Args: lo.ToPtr([]string{"-c", "head -c 4194304 /dev/zero; printf tail; printf stderr >&2"})}) + require.NoError(t, err) + require.NotNil(t, spawn.JSON200, "%s", spawn.Body) + id := spawn.JSON200.ProcessId + status := waitImageProcessExit(t, ctx, client, *spawn.JSON200) + require.Equal(t, 0, *status.ExitCode) + require.False(t, *status.OutputTruncated) + response, err := client.ProcessStdoutStream(ctx, *id, &oapi.ProcessStdoutStreamParams{}) + require.NoError(t, err) + out, errOut, events := readImageProcessStream(t, response) + require.Equal(t, strings.Repeat("\x00", 4<<20)+"tail", out) + require.Equal(t, "stderr", errOut) + requireImageExitEvent(t, events, 0) + + response, err = client.ProcessStdoutStream(ctx, *id, &oapi.ProcessStdoutStreamParams{}) + require.NoError(t, err) + out, errOut, events = readImageProcessStream(t, response) + require.Empty(t, out) + require.Empty(t, errOut) + require.Empty(t, events) + + response, err = client.ProcessStdoutStream(ctx, *id, &oapi.ProcessStdoutStreamParams{Offset: lo.ToPtr(int64(0))}) + require.NoError(t, err) + out, errOut, events = readImageProcessStream(t, response) + require.Equal(t, strings.Repeat("\x00", 4<<20)+"tail", out) + require.Equal(t, "stderr", errOut) + requireImageExitEvent(t, events, 0) + // Resume just after the first event and compare the remaining records. + response, err = client.ProcessStdoutStream(ctx, *id, &oapi.ProcessStdoutStreamParams{LastEventID: lo.ToPtr(strconv.FormatInt(*events[0].Offset, 10))}) + require.NoError(t, err) + _, _, resumed := readImageProcessStream(t, response) + require.Equal(t, events[1:], resumed) + }) + + t.Run("exec deadlines stop children", func(t *testing.T) { + for _, script := range []string{"sleep 30 & echo $!; wait", "sleep 30 & echo $!"} { + result, err := client.ProcessExecWithResponse(ctx, oapi.ProcessExecRequest{Command: "sh", Args: lo.ToPtr([]string{"-c", script}), TimeoutSec: lo.ToPtr(1)}) + require.NoError(t, err) + require.Equal(t, http.StatusUnprocessableEntity, result.StatusCode(), "%s", result.Body) + require.Equal(t, oapi.ProcessTimeout, result.JSON422.Code) + data, err := base64.StdEncoding.DecodeString(*result.JSON422.StdoutB64) + require.NoError(t, err) + pid, err := strconv.Atoi(strings.TrimSpace(string(data))) + require.NoError(t, err) + require.Eventually(t, func() bool { + code, _, err := c.Exec(ctx, []string{"sh", "-c", fmt.Sprintf("test ! -e /proc/%d/stat || grep -q ') Z ' /proc/%d/stat", pid, pid)}) + return err == nil && code == 0 + }, 2*time.Second, 20*time.Millisecond, "child %d remains alive", pid) + } + }) + + t.Run("spawn deadlines include tty", func(t *testing.T) { + for _, tty := range []bool{false, true} { + spawn, err := client.ProcessSpawnWithResponse(ctx, oapi.ProcessSpawnRequest{Command: "sleep", Args: lo.ToPtr([]string{"30"}), TimeoutSec: lo.ToPtr(1), AllocateTty: &tty}) + require.NoError(t, err) + require.NotNil(t, spawn.JSON200, "%s", spawn.Body) + status := waitImageProcessExit(t, ctx, client, *spawn.JSON200) + require.Equal(t, oapi.ProcessTimeout, *status.TerminationReason) + response, err := client.ProcessStdoutStream(ctx, *spawn.JSON200.ProcessId, &oapi.ProcessStdoutStreamParams{}) + require.NoError(t, err) + _, _, events := readImageProcessStream(t, response) + requireImageExitEvent(t, events, -1) + require.Equal(t, oapi.ProcessTimeout, *events[len(events)-1].TerminationReason) + } + }) + + t.Run("quota failure is present at first exited status", func(t *testing.T) { + spawn, err := client.ProcessSpawnWithResponse(ctx, oapi.ProcessSpawnRequest{Command: "head", Args: lo.ToPtr([]string{"-c", "12582912", "/dev/zero"})}) + require.NoError(t, err) + require.NotNil(t, spawn.JSON200, "%s", spawn.Body) + status := waitImageProcessExit(t, ctx, client, *spawn.JSON200) + require.NotNil(t, status.TerminationReason) + require.Equal(t, oapi.OutputLimit, *status.TerminationReason) + require.True(t, *status.OutputTruncated) + response, err := client.ProcessStdoutStream(ctx, *spawn.JSON200.ProcessId, &oapi.ProcessStdoutStreamParams{}) + require.NoError(t, err) + out, _, events := readImageProcessStream(t, response) + require.NotEmpty(t, out) + require.Less(t, len(out), 8<<20) + require.Equal(t, oapi.OutputLimit, *events[len(events)-1].TerminationReason) + require.True(t, *events[len(events)-1].OutputTruncated) + }) + }) + } +} + +func TestProcessTTYWithoutOutputStorage(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + c := NewTestContainer(t, headlessImage) + require.NoError(t, c.Start(ctx, ContainerConfig{Env: map[string]string{"PROCESS_OUTPUT_DIR": "/proc/unavailable"}})) + defer c.Stop(context.Background()) + require.NoError(t, c.WaitReady(ctx)) + client, err := c.APIClient() + require.NoError(t, err) + spawn, err := client.ProcessSpawnWithResponse(ctx, oapi.ProcessSpawnRequest{ + Command: "sh", Args: lo.ToPtr([]string{"-c", "read line; printf 'reply:%s\\n' \"$line\"; read line"}), + AllocateTty: lo.ToPtr(true), Rows: lo.ToPtr(24), Cols: lo.ToPtr(80), + }) + require.NoError(t, err) + require.NotNil(t, spawn.JSON200, "%s", spawn.Body) + defer client.ProcessKillWithResponse(context.Background(), *spawn.JSON200.ProcessId, oapi.ProcessKillRequest{Signal: "KILL"}) + url := strings.Replace(c.APIBaseURL(), "http", "ws", 1) + "/process/" + spawn.JSON200.ProcessId.String() + "/attach" + conn, _, err := websocket.Dial(ctx, url, nil) + require.NoError(t, err) + defer conn.CloseNow() + resized, err := client.ProcessResizeWithResponse(ctx, *spawn.JSON200.ProcessId, oapi.ProcessResizeRequest{Rows: 30, Cols: 100}) + require.NoError(t, err) + require.Equal(t, http.StatusOK, resized.StatusCode()) + require.NoError(t, conn.Write(ctx, websocket.MessageBinary, []byte("hello\n"))) + var output strings.Builder + for !strings.Contains(output.String(), "reply:hello") { + kind, data, err := conn.Read(ctx) + require.NoError(t, err) + if kind == websocket.MessageBinary { + output.Write(data) + } + } + // Non-TTY capture still fails before running commands when storage is unavailable. + result, err := client.ProcessExecWithResponse(ctx, oapi.ProcessExecRequest{Command: "true"}) + require.NoError(t, err) + require.Equal(t, http.StatusInternalServerError, result.StatusCode()) +} + +func waitImageProcessExit(t *testing.T, ctx context.Context, client *oapi.ClientWithResponses, spawn oapi.ProcessSpawnResult) *oapi.ProcessStatus { + t.Helper() + var status *oapi.ProcessStatus + require.Eventually(t, func() bool { + response, err := client.ProcessStatusWithResponse(ctx, *spawn.ProcessId) + require.NoError(t, err) + require.NotNil(t, response.JSON200, "%s", response.Body) + status = response.JSON200 + return *status.State == "exited" + }, 5*time.Second, 10*time.Millisecond) + return status +} + +func readImageProcessStream(t *testing.T, response *http.Response) (string, string, []oapi.ProcessStreamEvent) { + t.Helper() + defer response.Body.Close() + require.Equal(t, http.StatusOK, response.StatusCode) + var out, errOut strings.Builder + events := make([]oapi.ProcessStreamEvent, 0) + scanner := bufio.NewScanner(response.Body) + for scanner.Scan() { + if !strings.HasPrefix(scanner.Text(), "data: ") { + continue + } + var event oapi.ProcessStreamEvent + require.NoError(t, json.Unmarshal([]byte(strings.TrimPrefix(scanner.Text(), "data: ")), &event)) + events = append(events, event) + if event.DataB64 != nil { + data, err := base64.StdEncoding.DecodeString(*event.DataB64) + require.NoError(t, err) + if *event.Stream == "stdout" { + out.Write(data) + } else { + errOut.Write(data) + } + } + } + require.NoError(t, scanner.Err()) + return out.String(), errOut.String(), events +} + +func requireImageExitEvent(t *testing.T, events []oapi.ProcessStreamEvent, code int) { + t.Helper() + require.NotEmpty(t, events) + last := events[len(events)-1] + require.NotNil(t, last.Event) + require.Equal(t, oapi.Exit, *last.Event) + require.Equal(t, code, *last.ExitCode) + for _, event := range events[:len(events)-1] { + require.Nil(t, event.Event) + } +} From e608025c71f068734ea80fbbfc2e8d1c0afdc0b0 Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Thu, 15 Oct 2026 22:29:54 +0000 Subject: [PATCH 07/10] Prefer the SSE resume header on reconnect --- server/cmd/api/api/process.go | 6 +++--- server/docs/processes.md | 2 +- server/openapi.yaml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server/cmd/api/api/process.go b/server/cmd/api/api/process.go index b8b910b7..45065e6e 100644 --- a/server/cmd/api/api/process.go +++ b/server/cmd/api/api/process.go @@ -385,10 +385,10 @@ func (s *ApiService) ProcessStdoutStream(ctx context.Context, request oapi.Proce } var offset int64 var err error - if request.Params.Offset != nil { - offset = *request.Params.Offset - } else if request.Params.LastEventID != nil { + if request.Params.LastEventID != nil { offset, err = strconv.ParseInt(*request.Params.LastEventID, 10, 64) + } else if request.Params.Offset != nil { + offset = *request.Params.Offset } if err != nil || h.output.validateOffset(offset) != nil { return oapi.ProcessStdoutStream400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "invalid output offset"}}, nil diff --git a/server/docs/processes.md b/server/docs/processes.md index fcd979fb..823b60cb 100644 --- a/server/docs/processes.md +++ b/server/docs/processes.md @@ -22,7 +22,7 @@ Spawned process status and output remain available for 10 seconds after capture `GET /process/{process_id}/stdout/stream` without a cursor consumes the process's unread output, including output captured before the first connection. Reconnects continue at the shared consumed position and do not repeat a consumed exit event. Concurrent cursorless connections divide the output, as with the original queue. Consumption happens when a record is read for delivery; a disconnect can lose an in-flight record, so use explicit cursors when delivery must be resumable. -Supplying `?offset=0` replays all retained output, then follows new output. Data events include an opaque `offset`, also emitted as the SSE `id`. To resume after a data event, send its cursor as `?offset=...` or the `Last-Event-ID` header. These explicit cursors read independently and do not advance cursorless consumption. The query parameter takes precedence. Invalid cursors return 400; expired processes return 404. +Supplying `?offset=0` replays all retained output, then follows new output. Data events include an opaque `offset`, also emitted as the SSE `id`. To resume after a data event, send its cursor as `?offset=...` or the `Last-Event-ID` header. These explicit cursors read independently and do not advance cursorless consumption. When both are supplied, `Last-Event-ID` takes precedence so an `EventSource` opened with `?offset=0` resumes on automatic reconnect. To replay from the beginning again, open a new connection with `?offset=0` and no `Last-Event-ID`. Invalid cursors return 400; expired processes return 404. An `exit` event follows all captured output and includes `exit_code`, `output_truncated`, and, when execution was stopped by the server, `termination_reason`. Clients must check the terminal event to distinguish complete capture from partial output. Reconnection does not extend retention. diff --git a/server/openapi.yaml b/server/openapi.yaml index 5511a37c..ac45a2b7 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -120,14 +120,14 @@ paths: format: uuid - name: offset in: query - description: Resume cursor from a prior output event, or 0 to replay all retained output. Overrides Last-Event-ID. + description: Resume cursor from a prior output event, or 0 to replay all retained output. Used when Last-Event-ID is absent. schema: type: integer format: int64 minimum: 0 - name: Last-Event-ID in: header - description: Resume cursor from a prior SSE data event. + description: Resume cursor from a prior SSE data event. Takes precedence over offset so automatic reconnects resume after the last received event. schema: type: string responses: From 18fc9214da4e919b461604db8de5820d6a90a6bb Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Thu, 15 Oct 2026 22:29:55 +0000 Subject: [PATCH 08/10] Regenerate process cursor documentation --- server/lib/oapi/oapi.go | 179 ++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 89 deletions(-) diff --git a/server/lib/oapi/oapi.go b/server/lib/oapi/oapi.go index 85285060..df3f3e1d 100644 --- a/server/lib/oapi/oapi.go +++ b/server/lib/oapi/oapi.go @@ -7335,10 +7335,10 @@ type DeletePlaywrightExecutorParams struct { // ProcessStdoutStreamParams defines parameters for ProcessStdoutStream. type ProcessStdoutStreamParams struct { - // Offset Resume cursor from a prior output event, or 0 to replay all retained output. Overrides Last-Event-ID. + // Offset Resume cursor from a prior output event, or 0 to replay all retained output. Used when Last-Event-ID is absent. Offset *int64 `form:"offset,omitempty" json:"offset,omitempty"` - // LastEventID Resume cursor from a prior SSE data event. + // LastEventID Resume cursor from a prior SSE data event. Takes precedence over offset so automatic reconnects resume after the last received event. LastEventID *string `json:"Last-Event-ID,omitempty"` } @@ -27706,93 +27706,94 @@ var swaggerSpec = []string{ "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", + "Dy8n7VjE7uPH//8AesMYOITpAwA=", } // GetSwagger returns the content of the embedded swagger specification file From fcb2ed6601ef58597058b0093170b1635603913c Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Thu, 15 Oct 2026 22:29:55 +0000 Subject: [PATCH 09/10] Cover process reconnect and cancellation behavior --- server/cmd/api/api/process_lifecycle_test.go | 97 +++++++++++++++++++- server/e2e/e2e_process_test.go | 4 +- 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/server/cmd/api/api/process_lifecycle_test.go b/server/cmd/api/api/process_lifecycle_test.go index 25a4c530..53a1140c 100644 --- a/server/cmd/api/api/process_lifecycle_test.go +++ b/server/cmd/api/api/process_lifecycle_test.go @@ -20,6 +20,7 @@ import ( chiMiddleware "github.com/go-chi/chi/v5/middleware" oapi "github.com/kernel/kernel-images/server/lib/oapi" + "github.com/kernel/kernel-images/server/lib/recorder" "github.com/stretchr/testify/require" ) @@ -190,11 +191,13 @@ func TestProcessSlowReaderAndResume(t *testing.T) { require.NoError(t, err) for _, params := range []oapi.ProcessStdoutStreamParams{ {LastEventID: &lastID}, - {Offset: first.Offset, LastEventID: ptrOf("ignored")}, + {Offset: first.Offset}, + {Offset: ptrOf(int64(0)), LastEventID: &lastID}, } { stream := processStream(t, svc, spawn, params) output, events := collectProcessStream(t, stream) require.NoError(t, stream.Close()) + require.Equal(t, 2<<20, len(firstData)+len(output), "resumed stream duplicated or lost output") require.Equal(t, strings.Repeat("\x00", 2<<20), string(firstData)+output) requireProcessExitEvent(t, events, 0) } @@ -203,6 +206,98 @@ func TestProcessSlowReaderAndResume(t *testing.T) { require.NoError(t, err) require.IsType(t, oapi.ProcessStdoutStream400JSONResponse{}, resp) } + resp, err := svc.ProcessStdoutStream(context.Background(), oapi.ProcessStdoutStreamRequestObject{ + ProcessId: *spawn.ProcessId, Params: oapi.ProcessStdoutStreamParams{Offset: ptrOf(int64(0)), LastEventID: ptrOf("invalid")}, + }) + require.NoError(t, err) + require.IsType(t, oapi.ProcessStdoutStream400JSONResponse{}, resp) +} + +func TestProcessExecCancellationStopsChildren(t *testing.T) { + svc := newProcessTestService(t, ProcessOutputConfig{}) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + pidFile := filepath.Join(t.TempDir(), "child-pid") + args := []string{"-c", `sleep 30 & child=$!; printf before; printf '%s' "$child" > "$1"; wait`, "sh", pidFile} + type result struct { + response oapi.ProcessExecResponseObject + err error + } + completed := make(chan result, 1) + go func() { + response, err := svc.ProcessExec(ctx, oapi.ProcessExecRequestObject{Body: &oapi.ProcessExecRequest{Command: "sh", Args: &args}}) + completed <- result{response: response, err: err} + }() + childPID := waitProcessPIDFile(t, pidFile) + cancel() + select { + case result := <-completed: + require.NoError(t, result.err) + require.IsType(t, oapi.ProcessExec422JSONResponse{}, result.response) + failure := result.response.(oapi.ProcessExec422JSONResponse) + require.Equal(t, oapi.ProcessCanceled, failure.Code) + require.Equal(t, base64.StdEncoding.EncodeToString([]byte("before")), *failure.StdoutB64) + case <-time.After(5 * time.Second): + t.Fatal("exec did not finish after request cancellation") + } + requireProcessStopped(t, childPID) +} + +func TestProcessSpawnShutdownStopsChildren(t *testing.T) { + for _, tty := range []bool{false, true} { + t.Run(fmt.Sprintf("tty=%v", tty), func(t *testing.T) { + svc, err := newSvc(t, recorder.NewFFmpegManager()) + require.NoError(t, err) + t.Cleanup(func() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + require.NoError(t, svc.Shutdown(ctx)) + }) + pidFile := filepath.Join(t.TempDir(), "child-pid") + args := []string{"-c", `sleep 30 & printf '%s' "$!" > "$1"; wait`, "sh", pidFile} + response, err := svc.ProcessSpawn(context.Background(), oapi.ProcessSpawnRequestObject{Body: &oapi.ProcessSpawnRequest{ + Command: "sh", Args: &args, AllocateTty: &tty, + }}) + require.NoError(t, err) + require.IsType(t, oapi.ProcessSpawn200JSONResponse{}, response) + spawn := response.(oapi.ProcessSpawn200JSONResponse) + childPID := waitProcessPIDFile(t, pidFile) + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + require.NoError(t, svc.Shutdown(ctx)) + requireProcessStopped(t, *spawn.Pid) + requireProcessStopped(t, childPID) + require.Eventually(t, func() bool { + status, err := svc.ProcessStatus(context.Background(), oapi.ProcessStatusRequestObject{ProcessId: *spawn.ProcessId}) + require.NoError(t, err) + _, released := status.(oapi.ProcessStatus404JSONResponse) + return released + }, time.Second, 10*time.Millisecond, "shutdown did not release the process") + }) + } +} + +func waitProcessPIDFile(t *testing.T, path string) int { + t.Helper() + var pid int + require.Eventually(t, func() bool { + data, err := os.ReadFile(path) + if err != nil { + return false + } + pid, err = strconv.Atoi(string(data)) + return err == nil && pid > 0 + }, 5*time.Second, 10*time.Millisecond, "command did not start its child") + return pid +} + +func requireProcessStopped(t *testing.T, pid int) { + t.Helper() + require.Eventually(t, func() bool { + stat, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid)) + return os.IsNotExist(err) || strings.Contains(string(stat), ") Z ") + }, time.Second, 10*time.Millisecond, "process %d is still running", pid) } func TestProcessSpawnTimeoutSurvivesRequestCancellation(t *testing.T) { diff --git a/server/e2e/e2e_process_test.go b/server/e2e/e2e_process_test.go index 9def1637..75c1ff1e 100644 --- a/server/e2e/e2e_process_test.go +++ b/server/e2e/e2e_process_test.go @@ -72,7 +72,9 @@ func TestProcessLifecycle(t *testing.T) { require.Equal(t, "stderr", errOut) requireImageExitEvent(t, events, 0) // Resume just after the first event and compare the remaining records. - response, err = client.ProcessStdoutStream(ctx, *id, &oapi.ProcessStdoutStreamParams{LastEventID: lo.ToPtr(strconv.FormatInt(*events[0].Offset, 10))}) + response, err = client.ProcessStdoutStream(ctx, *id, &oapi.ProcessStdoutStreamParams{ + Offset: lo.ToPtr(int64(0)), LastEventID: lo.ToPtr(strconv.FormatInt(*events[0].Offset, 10)), + }) require.NoError(t, err) _, _, resumed := readImageProcessStream(t, response) require.Equal(t, events[1:], resumed) From fc08a38084a3327f495347d7dd37e9481e3ac732 Mon Sep 17 00:00:00 2001 From: Sayan- <1415138+Sayan-@users.noreply.github.com> Date: Thu, 22 Oct 2026 23:12:57 +0000 Subject: [PATCH 10/10] Simplify process capture completion coordination --- server/cmd/api/api/process_runner.go | 32 +++++++++------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/server/cmd/api/api/process_runner.go b/server/cmd/api/api/process_runner.go index 7fcb08a7..db818537 100644 --- a/server/cmd/api/api/process_runner.go +++ b/server/cmd/api/api/process_runner.go @@ -7,7 +7,6 @@ import ( "io" "os" "os/exec" - "sync" "syscall" "time" @@ -133,21 +132,16 @@ func (h *processHandle) outputFailed(err error) { func (h *processHandle) run(ctx, lifecycle context.Context, timeoutSec *int, release func()) { defer release() - failures := make(chan error, 2) - var readers sync.WaitGroup + captureResults := make(chan error, 2) + pendingCaptures := 0 if !h.isTTY { for stream, pipe := range []io.ReadCloser{h.stdout, h.stderr} { - readers.Add(1) + pendingCaptures++ go func(stream byte, pipe io.Reader) { - defer readers.Done() - if err := h.captureOutput(stream, pipe); err != nil { - failures <- err - } + captureResults <- h.captureOutput(stream, pipe) }(byte(stream), pipe) } } - readersDone := make(chan struct{}) - go func() { readers.Wait(); close(readersDone) }() waited := make(chan error, 1) go func() { waited <- waitForProcessExit(h.cmd) }() var deadline, drain <-chan time.Time @@ -159,22 +153,22 @@ func (h *processHandle) run(ctx, lifecycle context.Context, timeoutSec *int, rel deadline = timer.C } canceled, shutdown := ctx.Done(), lifecycle.Done() - leaderExited, outputComplete := false, false - for !leaderExited || !outputComplete { + for waited != nil || pendingCaptures > 0 { select { case err := <-waited: if err != nil { h.terminate("process_canceled", false) logger.FromContext(ctx).Error("failed to wait for process exit", "err", err) } - leaderExited = true waited = nil timer := time.NewTimer(processOutputDrainTimeout) defer timer.Stop() drain = timer.C - case <-readersDone: - outputComplete = true - readersDone = nil + case err := <-captureResults: + pendingCaptures-- + if err != nil { + h.outputFailed(err) + } case <-deadline: h.terminate("process_timeout", false) deadline = nil @@ -184,8 +178,6 @@ func (h *processHandle) run(ctx, lifecycle context.Context, timeoutSec *int, rel case <-shutdown: h.terminate("process_canceled", false) shutdown = nil - case err := <-failures: - h.outputFailed(err) case <-drain: if !deadlineAt.IsZero() && !time.Now().Before(deadlineAt) { h.terminate("process_timeout", false) @@ -198,10 +190,6 @@ func (h *processHandle) run(ctx, lifecycle context.Context, timeoutSec *int, rel drain = nil } } - close(failures) - for err := range failures { - h.outputFailed(err) - } h.closeOutputPipes() if h.stdin != nil { h.stdin.Close()