From 0ff13be803da1bc613801561fbb375919687f05f Mon Sep 17 00:00:00 2001 From: Preetam Dwivedi Date: Mon, 28 Sep 2026 09:55:09 -0700 Subject: [PATCH 1/8] docs(web): design gateway-backed web library ## Summary ### Why? SubmitQueue has gateway APIs and a terminal client but no reusable browser UX. Shipping one fixed Next application would couple the UI to a deployment's authentication, telemetry, routing, and process policy, forcing other deployers to fork it. ### What? Define a gateway-backed web package analogous to `submitqueue/client`: generated Connect clients, server-only gateway helpers, presentation models, components, and link helpers live in a pnpm workspace under `web/`, while host-owned Next applications provide routes, authorization, telemetry, configuration, transport, and deployment. The RFC specifies the Node/server boundary, Next 16 packaging and security constraints, TypeScript proto generation, additive gateway prerequisites, status and error compatibility, telemetry ownership, testing, CI isolation from Go/Bazel, a read-only first phase, and the promotion path for additional domain UX packages. Co-authored-by: Cursor # Conflicts: # doc/rfc/index.md # Please enter the commit message for your changes. Lines starting # with '#' will be kept; you may remove them yourself if you want to. # An empty message aborts the commit. # # interactive rebase in progress; onto 69165965 # Last command done (1 command done): # pick ff32728c # docs(web): design gateway-backed web library # Next commands to do (4 remaining commands): # pick a1afdc2c # docs(web): refocus web library RFC on design boundaries # pick d05545e2 # docs(web): tighten web library transport and link contracts # You are currently rebasing branch 'preetam/web-rfc' on '69165965'. # # Changes to be committed: # modified: doc/rfc/index.md # new file: doc/rfc/web-library.md # # Untracked files: # web/ # --- doc/rfc/index.md | 1 + doc/rfc/web-library.md | 397 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 398 insertions(+) create mode 100644 doc/rfc/web-library.md diff --git a/doc/rfc/index.md b/doc/rfc/index.md index f27eaaf0c..46fe51a44 100644 --- a/doc/rfc/index.md +++ b/doc/rfc/index.md @@ -13,6 +13,7 @@ Design documents and technical proposals, grouped by scope. Shared/cross-cutting - [Scoped Sequential Resource IDs](scoped-resource-ids.md) - Queue-scoped positive numeric IDs allocated by durable per-domain, per-kind counters, stored without queue/kind prefixes, and rendered directly in resource URL segments - [Hooks Framework](hook-framework.md) - Implemented fire-and-forget side effects: one shared `HookEvent` contract (`api/base/hook/`) on a durable per-domain hook topic, dispatched by `platform/hook` to `platform/extension/hook`. Stovepipe `process` and `record` publish repository events; the SubmitQueue orchestrator registers the stage and does not publish events yet - [Service-Scoped Extensions](service-scoped-extensions.md) - Implemented for SubmitQueue storage: gateway and orchestrator aggregates, schemas, and the core packages that serve one service have moved, while store contracts stay at `submitqueue/extension/storage`. Domain-level `buildrunner`, `conflict`, and `speculation` have not moved, and `changeset` still declares its own store slice +- [Web as a Library](web-library.md) - Publishing gateway-backed components, presentation models, and server helpers as a reusable package while host-owned Next apps provide routes, authentication, telemetry, configuration, and gateway transport ## SubmitQueue diff --git a/doc/rfc/web-library.md b/doc/rfc/web-library.md new file mode 100644 index 000000000..5d8e5a01c --- /dev/null +++ b/doc/rfc/web-library.md @@ -0,0 +1,397 @@ +# Web as a Library + +SubmitQueue should publish its web UX as a library of components, gateway helpers, and presentation models. A deployer-owned Next application supplies authentication, telemetry, configuration, routes, and gateway connectivity. + +## Problem + +There is no browser UX today. The gateway already exposes the required read APIs: `GetRequestSummaryByID`, `GetRequestSummaryByChangeURI`, `List`, `GetRequestHistoryByID`, and `GetRequestHistoryByChangeURI` ([status/list](submitqueue/status-list-api.md), [history](submitqueue/history-api.md)). It also exposes `Cancel`, which needs an actor/audit contract before the web host uses it. `submitqueue/client/` already renders the read data in a terminal. + +A repository-owned Next application would couple the reusable UX to one deployment's environment variables, authentication, telemetry, and gateway routing. Unlike a Go deployer, who can import the library and replace `service/.../main.go`, a Next deployer would have to fork the application root (`app/`, `proxy.ts`, and `next.config.ts`). + +Hosts supply these deployment-specific inputs: + +| Concern | The host supplies | Wired with | +|---|---|---| +| Authentication and authorization | the caller session and allowed actions | host routes, server actions, and an optional optimistic `proxy.ts` redirect | +| Logging | a `pino.Logger`, or any structurally compatible object | `pino` plus `pino-pretty`, `pino-opentelemetry-transport`, or another host-selected transport | +| Metrics | a registered global OpenTelemetry `MeterProvider`, or none | `@opentelemetry/sdk-metrics` plus a Prometheus or OTLP exporter | +| Gateway transport | a generated gateway client for each queue | Connect transport configured for the host's gateway address, credentials, and edge | +| Configuration | branding, external-host mappings, and internal path templates | a serializable `WebConfig` populated by the host | + +Keeping these inputs outside the library allows the same UX to run in multiple hosts. This also matches the gateway's existing security boundary: `submitqueue/client/conn.go` can send a bearer token, but this repository does not validate it. Authentication belongs to the proxy, sidecar, ingress, or host in front of the gateway. + +Change and build links are concrete helpers over gateway data. Change URIs use `scheme://{host[:port]}/{path}` with a mandatory host and must be interpretable without deployment wiring ([change URIs](change-uri.md)). Build runners already write the provider's web URL into request metadata. Every rendered external link is validated against an HTTP/HTTPS allowlist; `git://` and deployments with different browser hosts use explicit `WebConfig` mappings. + +## Runtime boundary + +Unlike a Go service, a Next application runs in three environments: + +``` +build route discovery, bundling, and static generation; no host process +server Node server components, route handlers, server actions, and proxy +browser client components on another machine; serializable data and opaque + server-action references only +``` + +Next owns the request loop and bundler, so the library cannot own "no server" in the literal Go sense. Instead, it owns no process and no application root. The host owns the Next app root and resolves server dependencies once per process. Only serializable data, capabilities, and opaque server-action references cross into client components. + +## Design principles + +- **Use the gateway as the domain boundary.** Web code reads and mutates SubmitQueue only through the published gateway API. Missing domain data should extend that API. +- **Keep deployment policy in the host.** The library does not read environment variables, open listeners, import auth SDKs, choose telemetry exporters, hardcode external URLs, or exit the process. +- **Keep server dependencies on the server.** Host objects are never serialized into client components. +- **Compose with data and callbacks.** Host routes pass serializable data, capabilities, and authorized server actions to library components. +- **Keep routing private to the host.** Per-queue gateway selection is a plain host function, not a library interface. +- **Let the host choose framework versions.** `react`, `react-dom`, and `next` are peer dependencies. + +``` +┌───────────────────────────── HOST ──────────────────────────────┐ +│ app routes · proxy · auth · telemetry · config · transport │ +└──────────────────────────────┬──────────────────────────────────┘ + │ generated client, data, actions + ▼ +┌──────────────────────────── LIBRARY ────────────────────────────┐ +│ gateway helpers · param parsers · components · models · hrefs │ +│ NO env reads · NO listener · NO auth SDK · NO backend choices │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## Go analogy and its limits + +The reusable web package most closely matches `submitqueue/client/`, not `pipeline.Construct`: + +| Web | Go analogue | +|---|---| +| Gateway query helpers, paging, presentation models | `submitqueue/client/query.go`, `view.go`, and `watch.go` | +| Host route, auth checks, transport, and telemetry wiring | `service/.../main.go` | +| `(queue) => generated client` | host-private `Factory.For(Config{QueueName})` routing | + +The analogy stops at the wire boundary. Go controllers take domain entities and keep protobuf mapping in the host. The web library intentionally consumes the published gateway contract, so gateway-to-presentation mapping and gRPC-status-to-display-error mapping belong in the library. All deeper domain extensions remain behind the gateway. + +## Proposal + +### Step 1 · Package layout + +Start with one domain package and promote shared code only after another domain needs it: + +``` +web/ # pnpm workspace root +├── go.mod # exclude Node dependencies from root Go ./... +├── .nvmrc +├── package.json +├── pnpm-lock.yaml +├── pnpm-workspace.yaml +├── api/ # committed protobuf-es/Connect output +│ ├── base/change/ +│ ├── base/mergestrategy/ +│ └── submitqueue/gateway/ # @submitqueue/api-submitqueue-gateway +├── submitqueue/ # @submitqueue/web-submitqueue +│ └── src/ +│ ├── gateway/ # ./server: server-only RPC helpers +│ ├── component/ # server and client UI components +│ ├── model/ # presentation models and capabilities +│ ├── params.ts # route/search parameter parsing +│ ├── href.ts # external and internal link helpers +│ └── testing/ # ./testing: fixtures and fake generated clients +├── service/ +│ └── submitqueue/ # reference host and Next application root + +api/ # existing proto source + committed Go output +``` + +`web/` is a root-level artifact tree, like `api/`, `service/`, and `test/`. It contains the complete Node workspace, including the reference host, so dependency installation has one workspace boundary. pnpm may create package-local links, but all stay below `web/`. The Go domain and service trees remain Go-only. + +TypeScript stubs are generated into the pnpm workspace so their runtime dependencies resolve there. Protobuf-ES and Connect-ES v2 use pinned `@bufbuild/buf` and `@bufbuild/protoc-gen-es` development dependencies; no separate Connect generator is needed. After the existing Bazel Go generation, `make proto` runs `pnpm --dir web exec buf generate` for TypeScript. A new `check-proto` target regenerates both Go and TypeScript output and fails on a dirty tree. The API package, `@bufbuild/protobuf`, and `@connectrpc/connect` use one compatible v2 line across the workspace. + +The web library depends on `web/api/submitqueue/gateway`, not the Go code under `submitqueue/`. The cost is that one domain spans `submitqueue/`, `api/submitqueue/`, and `web/submitqueue/`; ownership and the Go/web hierarchies must remain aligned by convention. + +`web/service/submitqueue/` is the reference composition root used by Docker Compose. Deployers reuse the package and maintain their own host. + +### Step 2 · Gateway client and presentation helpers + +The generated gateway client is the web library's only domain dependency. The library adds concrete helpers for presentation mapping, error classification, and telemetry; it does not redefine the gateway as an interface. + +```ts +// web/submitqueue/src/gateway/request.ts +import type { Client } from '@connectrpc/connect' +import type { SubmitQueueGateway } from '@submitqueue/api-submitqueue-gateway' + +export async function loadRequest( + gateway: Client, + query: ByID, + logger?: Logger, +): Promise + +export async function cancelRequest( + gateway: Client, + command: CancelCommand, + logger?: Logger, +): Promise +``` + +The library obtains its meter through `metrics.getMeter("@submitqueue/web-submitqueue", version)` and never accepts an SDK or exporter. A logger is optional and typed as `pino.Logger`; `pino` is an optional peer because the emitted declarations reference its type. + +The host constructs Node clients with `@connectrpc/connect-node` `createGrpcTransport`, which speaks gRPC over HTTP/2 to the existing grpc-go server. The transport is cached on `globalThis` so route and instrumentation bundles plus development hot reload share one instance. It is configured with TLS and bearer/deadline interceptors. The library exports an API-only Connect tracing interceptor so gateway calls nest under the active Next span. Host startup validates every configured gateway. Per-queue routing is a plain function: + +```ts +type GatewayForQueue = (queue: string) => Client +``` + +Cross-queue helpers take this function. Library tests use a fake generated client. + +If a view needs domain data that the gateway does not expose, the gateway contract should grow. Phase one adds `ListQueues`, backed by the gateway's existing `queueconfig.Store.List`. A host spanning several gateways fans out over its configured gateway endpoints and associates each returned queue with that client. + +Links are also concrete helpers: + +```ts +export function changeHref(uri: string, config: WebConfig): Href | null +export function buildHref(buildURL: string): Href | null +export function requestHref(id: ByID, paths: WebPaths): Href | null +``` + +`WebPaths` contains serializable templates such as `/q/{queue}/r/{sqid}`. A missing template means the host did not expose that route, so the component renders no link. The gateway contract adds `build_url` to `HistoryEvent`, where each build occurrence belongs, and may mirror the current build URL on `RequestSummary`. + +#### Telemetry + +`@opentelemetry/api` is stable, works in Node and browsers, and is a no-op until the host registers a provider. Library packages depend only on that API. SDKs, exporters, registries, transports, and collector addresses remain host dependencies. Connect interceptors create client spans so gateway calls nest under Next request traces. + +An incompatible OpenTelemetry API major silently becomes a no-op, so host startup asserts compatibility. Ephemeral/serverless hosts may flush through `after(...)`; the recommended long-running Node host does not flush per request. + +### Step 3 · Host route composition + +Next's filesystem is the route topology, so the library does not add a runtime engine or view registry. Each host route performs the composition work that Go service mains perform: + +1. Resolve and authorize the host session. +2. Select and call the generated gateway client through library helpers. +3. Derive serializable capabilities and data. +4. Render a library component. +5. Provide host-owned server actions for enabled mutations. + +```tsx +// web/service/submitqueue/app/request/[queue]/[sqid]/page.tsx +export default async function RequestRoute({ params }: RouteProps) { + const parsed = parseRequestParams(await params) // params is a Promise in Next 16 + if (!parsed.ok) { + return + } + const route = parsed.value + const session = await requireSession() + await requireAllowed(session, Action.ViewRequest, route) + + const result = await loadRequest(gatewayForQueue(route.queue), route, logger) + if (!result.ok) { + return + } + + return ( + + ) +} +``` + +Phase one is read-only. Cancel is enabled only after `CancelRequest` carries an additive actor field and the gateway records it in request history. A later host-owned action re-authenticates, authorizes the same queue/request resource, constructs identity fields from the trusted session rather than browser input, and returns a result union instead of throwing an expected error. Land remains out of scope until change-level authorization is defined. + +Hiding a button is not authorization. The library receives resource-bound capabilities for presentation and callbacks for actions, not sessions or an authorization interface. List rows carry their own queue/request capabilities. + +Routes remain hand-written host composition roots. A host may expose only a subset; missing `WebPaths` templates suppress links to unmounted routes. Separate route files preserve per-segment layouts, metadata, streaming, Suspense boundaries, and caching. + +The library ships built ESM that preserves `"use client"` directives, with package exports for the default component surface, `./server`, and `./testing`. The reference host targets `next >=16.3 <17`—above the Server Actions CSRF security floor—and compatible React 19 releases. Gateway loaders are `server-only`, never cached, and convert proto messages before data reaches client components. + +`proxy.ts` may perform an optimistic anonymous-user redirect, but every server component, route handler, and server action performs the real authorization check. Multi-instance hosts configure a shared `NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` and `experimental.serverActions.allowedOrigins` when a proxy rewrites `Host`. + +### Step 4 · Browser boundary + +The host passes only serializable configuration, page data, and capabilities to client components. Sessions remain in the host: + +```tsx +// web/service/submitqueue/app/layout.tsx (host-owned) +export default async function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + + {children} + + + + ) +} +``` + +Phase one uses client `error.tsx` boundaries that show `error.digest`, plus `onRequestError`, which logs that digest with the active trace ID. Browser telemetry (`useReportWebVitals` or a dedicated endpoint) is added only when a concrete metric requires it; the library does not prescribe a second collector or browser credential path. + +### Step 5 · Data and wire contracts + +Gateway calls run only in server components, route handlers, or server actions. The browser holds a session cookie, never gateway credentials. The gateway is a private dependency reachable only by trusted hosts; otherwise host authorization can be bypassed. + +`make proto` generates and commits TypeScript stubs under `web/api/`, mirroring `protopb/`. Protobuf-ES maps `int64` timestamps to `bigint`; gateway helpers validate safe range and convert them to `number` milliseconds in presentation models. Proto messages never cross into client components. + +Gateway statuses are strings today, not an enum. The library owns a display table for color, ordering, and terminal state plus an explicit unknown-status fallback. A committed fixture under `api/submitqueue/gateway/testdata/` is checked by both Go and TypeScript tests so new `entity.RequestStatus*` values cannot silently miss web presentation; keeping it outside `web/` lets hermetic Go tests read it. + +Before implementation, additive gateway changes provide: + +- `ListQueues` +- typed gRPC status details for known errors +- typed `build_url` fields instead of an implicit metadata key +- an actor field for audited mutations before web Cancel is enabled + +### Step 6 · Errors + +Gateway helpers classify from gRPC codes and typed details, never from server messages: + +| Codes | Display classification | +|---|---| +| `InvalidArgument`, `NotFound`, `ResourceExhausted` | actionable user error | +| `Unavailable`, `DeadlineExceeded` | transient infrastructure error | +| `Internal`, `Unknown`, unmapped | infrastructure error | + +Unknown errors default to infrastructure errors, and raw gateway messages are never rendered. Gateway follow-up work attaches typed details; the current server only sends `err.Error()` and passes some unclassified errors through. + +Helpers and server actions return result unions for expected outcomes rather than throwing them. Unexpected infrastructure failures reach a client `error.tsx` boundary, which shows only Next's `error.digest`. On the server, `onRequestError` logs the same digest with the active trace ID, route, and request context. Stack traces and reporting destinations remain hidden and host-owned. + +### Step 7 · Host surface + +| File | Content | +|---|---| +| `instrumentation.ts` | Node-guarded OpenTelemetry registration and `onRequestError` | +| `app/layout.tsx` | `` + branding | +| `app/**/page.tsx` | authenticate, load through gateway helpers, and render library components | +| `app/**/action.ts` | authorize mutations and call gateway helpers | +| `proxy.ts` | optimistic anonymous-user redirect only | +| `server/gateway.ts` | `globalThis`-cached transports, clients, and `(queue) => client` routing | +| `server/auth.ts` | authoritative session and resource checks | +| `server/telemetry.ts` | `globalThis`-cached logger plus OpenTelemetry SDK registration | +| `server/config.ts` | validated host config and serializable display config | +| `next.config.ts` | standalone output, tracing root, and Server Action origins | +| `Dockerfile` | the host's image | + +These files contain no presentation logic, gateway request mapping, or status definitions. Those remain in the library. + +## What the library enforces + +| Concern | Enforced by | +|---|---| +| No environment reads in the library | Lint rule banning `process.env` under `web/submitqueue`; CI gate | +| No gateway client in browser bundles | `import 'server-only'` in the `./server` export | +| No unsafe external URLs | Every rendered external href passes an HTTP/HTTPS scheme allowlist | +| Status vocabulary drift | Shared fixture tests the string display table in Go and TypeScript | +| Host controls framework versions | `react` / `next` are `peerDependencies`, never dependencies | +| One protobuf runtime | API package, Connect, and Protobuf-ES versions are aligned in the workspace | +| No telemetry backend in the library | `pino` is an optional type peer and `@opentelemetry/api` is a no-op peer; SDKs and exporters are forbidden in library packages | + +Authorization is host-owned and therefore not enforceable by the library. Host route tests must verify that reads and mutations reject unauthorized sessions; hiding a component based on capabilities is never treated as enforcement. + +## Host telemetry + +`instrumentation.ts` is a separate bundle entry, so shared process objects are cached on `globalThis` rather than relying on module-instance singletons: + +```ts +export async function register() { + if (process.env.NEXT_RUNTIME !== 'nodejs') return + const { registerTelemetry } = await import('./server/telemetry') + await registerTelemetry() +} + +export const onRequestError: Instrumentation.onRequestError = async ( + error, + request, + context, +) => { + if (process.env.NEXT_RUNTIME !== 'nodejs') return + const { reportRequestError } = await import('./server/telemetry') + const digest = + typeof error === 'object' && error !== null && 'digest' in error + ? String(error.digest) + : undefined + reportRequestError({ + error, + digest, + route: context.routePath, + request, + }) +} +``` + +`server/telemetry.ts` owns pino and SDK construction through `globalThis` caches. The OpenTelemetry provider survives through the API global, and the library obtains its meter from that API. `reportRequestError` logs the supplied digest with the active trace ID. + +## Testing + +```ts +import pino from 'pino' + +const data = await loadRequest( + fakeGateway({ 'demo/1': summary({ status: 'landing' }) }), + { queue: 'demo', sqid: 'demo/1' }, + pino({ level: 'silent' }), +) + +if (!data.ok) throw new Error('test fixture must load') +render() +``` + +The fake implements the generated client shape. Proto fixtures include `bigint` timestamps, but presentation fixtures contain only serializable values. Playwright end-to-end tests use the domain-qualified compose context `e2e-submitqueue-web` ([testing guide](../howto/TESTING.md#container-naming)). + +## Deployment model + +The supported deployment is a long-running Node host with server-side gateway access. `next.config.ts` uses `output: "standalone"` and `outputFileTracingRoot` points at `web/`; the Docker build context is `web/`. Hosts behind a rewriting proxy set `experimental.serverActions.allowedOrigins`. + +## Build and CI + +The `web/` pnpm workspace adds these Makefile targets to the existing CI gates: + +```makefile +check-proto: ## Check committed Go and TypeScript protobuf files +web-build: ## Build all web packages +web-e2e-test: ## Run Playwright web end-to-end tests +web-lint: ## Lint and typecheck web packages +web-test: ## Run web unit tests +``` + +Targets remain alphabetically sorted with `## Description`; `make lint` and `make test` include their web equivalents. + +Phase one does not use Bazel for TypeScript or Playwright. Bazel 8's root `REPO.bazel` and the root Gazelle directive exclude all of `web/`; web tests run through Make/pnpm and feed the same required-checks gate. `web/go.mod` keeps the root Go module from traversing Node dependencies. This choice can be revisited if hermetic Bazel web tests become necessary. + +`web/package.json` pins pnpm through `packageManager`, and `.nvmrc` pins Node. The library publishes built ESM and declares `next >=16.3 <17`, compatible React 19, the generated API package, Connect v2, Protobuf-ES v2, and optional pino types as peers. + +## Rejected + +- **Container image instead of a library.** Hosts could not replace authentication, telemetry, or transport without a permanent source fork. +- **One catch-all route.** `app/[[...slug]]/page.tsx` would replace Next routing and lose per-segment layouts, metadata, streaming, Suspense boundaries, and caching. +- **Static export or embedding in a Go binary.** Dynamic request routes cannot be enumerated, server actions and authoritative route checks disappear, and the grpc-go gateway needs a browser-reachable proxy with its own resource authorization. Revisit only with a separate design. +- **Web extension interfaces.** The gateway is already the domain contract. Extra `Gateway`, `GatewayFactory`, `Authorizer`, and generic `Deps` interfaces duplicate that contract or turn host authentication into library policy. +- **A generic `web/platform` engine.** Next's filesystem already defines route topology, and only one web domain exists. Add shared platform code only after a second domain demonstrates the common behavior. +- **Library-owned auth, logger, or metrics backends.** Token sources, clients, timeouts, transports, and registries are process infrastructure. Shipping them also adds unused dependencies to every host. +- **Bespoke telemetry interfaces.** OpenTelemetry already provides a stable, no-op metrics API. A type-only `pino.Logger` is structurally compatible with other loggers without an adapter or runtime dependency. +- **Environment-based library defaults.** `NEXT_PUBLIC_GATEWAY_ADDR` or similar defaults create a hidden configuration surface. +- **GraphQL or REST BFF.** Server components already provide the BFF and the generated gateway client is the domain boundary; another wire contract adds no capability. +- **DI framework.** Host route modules are explicit composition roots and do not need a runtime graph. +- **Shared Go/TypeScript view model through WASM or code generation.** A cross-language status fixture catches drift; the remaining presentation code is cheaper than a cross-language runtime. +- **Non-Next SPA.** Server components keep gateway access and authorization on the server; an SPA moves both into the browser. + +## Migration path + +The first phase makes additive gateway changes without changing existing behavior: + +1. Add gateway contracts required by the UI (`ListQueues`, attached typed error details, typed `build_url`) and generate committed TypeScript packages under `web/api/`; add Go/TypeScript round-trip and status-fixture checks. +2. Add the read-only `web/submitqueue` package with gateway helpers, models, components, parameter parsers, href helpers, and fakes; add unit and screenshot tests. +3. Add the read-only `web/service/submitqueue` reference host and a `web-ui` service to `service/submitqueue/docker-compose.yml`, depending on `gateway-service`; add `e2e-submitqueue-web`. +4. Add an actor to `CancelRequest`, persist it in request history, and then add the host-authorized Cancel action. Land remains deferred until change-level authorization is designed. +5. Build another host from the published package. Promote shared code only when that host or another domain demonstrates a reusable need. + +## Open questions + +- **Live updates.** Phase one uses polling with server revalidation, matching `client/watch.go`. Server-sent events could follow; a gateway `Watch` RPC needs a separate RFC. +- **`List` filtering.** The [status/list RFC](submitqueue/status-list-api.md) deferred status filters. The first queue view must either filter a receipt-time window or extend the gateway. +- **Authorization capabilities.** Finalize resource-bound capability types for queue pages and request rows. Phase one exposes read capabilities; Cancel follows its actor contract, and Land follows change-level authorization. +- **Initial scope.** Decide whether the first app contains only SubmitQueue or also Stovepipe history. Each domain uses its published RPC contract; Runway currently exposes only `Ping`, so a Runway view requires a new API. A second domain may justify shared UI helpers. +- **OTLP compatibility.** Determine whether intended host metrics backends accept OTLP. Otherwise those hosts must provide a `MetricReader`, making their wiring less similar to the reference host. +- **npm publishing.** The proposed `@submitqueue/*` packages require an npm organization and release cadence. From 80729280b2e28128d9cabedbaa505f792d7a04b1 Mon Sep 17 00:00:00 2001 From: Preetam Dwivedi Date: Mon, 28 Sep 2026 10:11:47 -0700 Subject: [PATCH 2/8] docs(web): refocus web library RFC on design boundaries ## Summary ### Why? The RFC had grown into an implementation guide, with migration steps, build targets, file-by-file host instructions, and code samples, which buried the design decisions reviewers need to evaluate. ### What? Recast the RFC around package, gateway, host-composition, wire, and error boundaries plus ownership invariants. Library components are synchronous and props-only, polling uses `router.refresh()`, multi-gateway queue collisions fail at startup, and server actions are covered by an authorization lint. Adds a layered UX testing strategy covering contracts, components, browser UX and accessibility, host authorization, and end-to-end flows. Co-authored-by: Cursor --- doc/rfc/web-library.md | 304 +++++++---------------------------------- 1 file changed, 49 insertions(+), 255 deletions(-) diff --git a/doc/rfc/web-library.md b/doc/rfc/web-library.md index 5d8e5a01c..5f51ad0ad 100644 --- a/doc/rfc/web-library.md +++ b/doc/rfc/web-library.md @@ -41,21 +41,9 @@ Next owns the request loop and bundler, so the library cannot own "no server" in - **Keep deployment policy in the host.** The library does not read environment variables, open listeners, import auth SDKs, choose telemetry exporters, hardcode external URLs, or exit the process. - **Keep server dependencies on the server.** Host objects are never serialized into client components. - **Compose with data and callbacks.** Host routes pass serializable data, capabilities, and authorized server actions to library components. -- **Keep routing private to the host.** Per-queue gateway selection is a plain host function, not a library interface. +- **Keep gateway routing private to the host.** Per-queue gateway selection is a plain host function, not a library interface. - **Let the host choose framework versions.** `react`, `react-dom`, and `next` are peer dependencies. -``` -┌───────────────────────────── HOST ──────────────────────────────┐ -│ app routes · proxy · auth · telemetry · config · transport │ -└──────────────────────────────┬──────────────────────────────────┘ - │ generated client, data, actions - ▼ -┌──────────────────────────── LIBRARY ────────────────────────────┐ -│ gateway helpers · param parsers · components · models · hrefs │ -│ NO env reads · NO listener · NO auth SDK · NO backend choices │ -└─────────────────────────────────────────────────────────────────┘ -``` - ## Go analogy and its limits The reusable web package most closely matches `submitqueue/client/`, not `pipeline.Construct`: @@ -68,11 +56,11 @@ The reusable web package most closely matches `submitqueue/client/`, not `pipeli The analogy stops at the wire boundary. Go controllers take domain entities and keep protobuf mapping in the host. The web library intentionally consumes the published gateway contract, so gateway-to-presentation mapping and gRPC-status-to-display-error mapping belong in the library. All deeper domain extensions remain behind the gateway. -## Proposal +## Design -### Step 1 · Package layout +### Package boundary -Start with one domain package and promote shared code only after another domain needs it: +Start with one domain package. Promote shared code only after another domain needs it: ``` web/ # pnpm workspace root @@ -87,79 +75,41 @@ web/ # pnpm workspace root │ └── submitqueue/gateway/ # @submitqueue/api-submitqueue-gateway ├── submitqueue/ # @submitqueue/web-submitqueue │ └── src/ -│ ├── gateway/ # ./server: server-only RPC helpers +│ ├── gateway/ # server-only RPC helpers │ ├── component/ # server and client UI components │ ├── model/ # presentation models and capabilities │ ├── params.ts # route/search parameter parsing │ ├── href.ts # external and internal link helpers -│ └── testing/ # ./testing: fixtures and fake generated clients -├── service/ -│ └── submitqueue/ # reference host and Next application root - -api/ # existing proto source + committed Go output -``` - -`web/` is a root-level artifact tree, like `api/`, `service/`, and `test/`. It contains the complete Node workspace, including the reference host, so dependency installation has one workspace boundary. pnpm may create package-local links, but all stay below `web/`. The Go domain and service trees remain Go-only. - -TypeScript stubs are generated into the pnpm workspace so their runtime dependencies resolve there. Protobuf-ES and Connect-ES v2 use pinned `@bufbuild/buf` and `@bufbuild/protoc-gen-es` development dependencies; no separate Connect generator is needed. After the existing Bazel Go generation, `make proto` runs `pnpm --dir web exec buf generate` for TypeScript. A new `check-proto` target regenerates both Go and TypeScript output and fails on a dirty tree. The API package, `@bufbuild/protobuf`, and `@connectrpc/connect` use one compatible v2 line across the workspace. - -The web library depends on `web/api/submitqueue/gateway`, not the Go code under `submitqueue/`. The cost is that one domain spans `submitqueue/`, `api/submitqueue/`, and `web/submitqueue/`; ownership and the Go/web hierarchies must remain aligned by convention. - -`web/service/submitqueue/` is the reference composition root used by Docker Compose. Deployers reuse the package and maintain their own host. - -### Step 2 · Gateway client and presentation helpers - -The generated gateway client is the web library's only domain dependency. The library adds concrete helpers for presentation mapping, error classification, and telemetry; it does not redefine the gateway as an interface. - -```ts -// web/submitqueue/src/gateway/request.ts -import type { Client } from '@connectrpc/connect' -import type { SubmitQueueGateway } from '@submitqueue/api-submitqueue-gateway' - -export async function loadRequest( - gateway: Client, - query: ByID, - logger?: Logger, -): Promise - -export async function cancelRequest( - gateway: Client, - command: CancelCommand, - logger?: Logger, -): Promise +│ └── testing/ # fixtures and fake generated clients +└── service/ + └── submitqueue/ # reference host and Next application root ``` -The library obtains its meter through `metrics.getMeter("@submitqueue/web-submitqueue", version)` and never accepts an SDK or exporter. A logger is optional and typed as `pino.Logger`; `pino` is an optional peer because the emitted declarations reference its type. +`web/` contains the complete Node workspace, including committed Protobuf-ES/Connect output and the reference host; proto sources and Go output stay in the root `api/` tree. `web/go.mod` and repository exclusions keep Node dependencies outside Go and Gazelle traversal. The web library depends on the generated API package, not Go domain code. -The host constructs Node clients with `@connectrpc/connect-node` `createGrpcTransport`, which speaks gRPC over HTTP/2 to the existing grpc-go server. The transport is cached on `globalThis` so route and instrumentation bundles plus development hot reload share one instance. It is configured with TLS and bearer/deadline interceptors. The library exports an API-only Connect tracing interceptor so gateway calls nest under the active Next span. Host startup validates every configured gateway. Per-queue routing is a plain function: +The package ships built ESM with default component exports plus `./server` and `./testing`. React, Next, Connect, Protobuf-ES, and optional pino types are peers so host and library share one runtime. `web/service/submitqueue/` demonstrates composition; deployers own their hosts. -```ts -type GatewayForQueue = (queue: string) => Client -``` +Phase one contains SubmitQueue only. Stovepipe can later add `web/stovepipe/` against its published RPCs; Runway needs a read API beyond `Ping` before it can expose UX. Shared UI is promoted only after that second domain exists. -Cross-queue helpers take this function. Library tests use a fake generated client. +### Gateway boundary -If a view needs domain data that the gateway does not expose, the gateway contract should grow. Phase one adds `ListQueues`, backed by the gateway's existing `queueconfig.Store.List`. A host spanning several gateways fans out over its configured gateway endpoints and associates each returned queue with that client. +The generated gateway client is the library's only domain dependency. Concrete helpers map gateway responses into presentation models; there is no web-specific gateway interface. -Links are also concrete helpers: +Gateway helpers take `Client`, typed queries, and an optional `pino.Logger`; expected outcomes use result unions. The library obtains its meter through `metrics.getMeter("@submitqueue/web-submitqueue", version)` and never accepts an SDK or exporter. -```ts -export function changeHref(uri: string, config: WebConfig): Href | null -export function buildHref(buildURL: string): Href | null -export function requestHref(id: ByID, paths: WebPaths): Href | null -``` +The host constructs Node gRPC clients, supplies credentials and deadlines, and routes queues with a plain `(queue) => generated client` function. Cross-queue helpers take that function. The library supplies presentation/error mapping, tracing instrumentation, and a fake generated client for tests. -`WebPaths` contains serializable templates such as `/q/{queue}/r/{sqid}`. A missing template means the host did not expose that route, so the component renders no link. The gateway contract adds `build_url` to `HistoryEvent`, where each build occurrence belongs, and may mirror the current build URL on `RequestSummary`. +If a view needs missing domain data, the gateway contract grows instead of adding a web-only backend. Phase one adds `ListQueues`, backed by `queueconfig.Store.List`; a multi-gateway host fans it out across configured endpoints and rejects its configuration at startup if two gateways report the same queue name. -#### Telemetry +Phase one refreshes views with a small client component that calls `router.refresh()` on an interval, re-running the server loaders, matching `submitqueue/client/watch.go`. It presents the bounded receipt-history `List` without status filtering. Streaming or filtered gateway APIs require separate contract changes. -`@opentelemetry/api` is stable, works in Node and browsers, and is a no-op until the host registers a provider. Library packages depend only on that API. SDKs, exporters, registries, transports, and collector addresses remain host dependencies. Connect interceptors create client spans so gateway calls nest under Next request traces. +Link helpers derive change and build URLs from gateway data and internal links from serializable `WebPaths` templates such as `/q/{queue}/r/{sqid}`. A missing template suppresses the link. `build_url` is added to `HistoryEvent`, where each build occurrence belongs, and may be mirrored on `RequestSummary` for the current build. -An incompatible OpenTelemetry API major silently becomes a no-op, so host startup asserts compatibility. Ephemeral/serverless hosts may flush through `after(...)`; the recommended long-running Node host does not flush per request. +The library depends only on `@opentelemetry/api` and obtains its own meter. SDKs, exporters, collector addresses, and logger construction remain host concerns. A Connect interceptor nests gateway spans under the active Next request trace. -### Step 3 · Host route composition +### Host composition -Next's filesystem is the route topology, so the library does not add a runtime engine or view registry. Each host route performs the composition work that Go service mains perform: +Next's filesystem is the route topology; there is no runtime engine or view registry. Each host route: 1. Resolve and authorize the host session. 2. Select and call the generated gateway client through library helpers. @@ -167,71 +117,19 @@ Next's filesystem is the route topology, so the library does not add a runtime e 4. Render a library component. 5. Provide host-owned server actions for enabled mutations. -```tsx -// web/service/submitqueue/app/request/[queue]/[sqid]/page.tsx -export default async function RequestRoute({ params }: RouteProps) { - const parsed = parseRequestParams(await params) // params is a Promise in Next 16 - if (!parsed.ok) { - return - } - const route = parsed.value - const session = await requireSession() - await requireAllowed(session, Action.ViewRequest, route) - - const result = await loadRequest(gatewayForQueue(route.queue), route, logger) - if (!result.ok) { - return - } - - return ( - - ) -} -``` - -Phase one is read-only. Cancel is enabled only after `CancelRequest` carries an additive actor field and the gateway records it in request history. A later host-owned action re-authenticates, authorizes the same queue/request resource, constructs identity fields from the trusted session rather than browser input, and returns a result union instead of throwing an expected error. Land remains out of scope until change-level authorization is defined. +Route params are untrusted and parsed before lookup. Phase one is read-only. Cancel follows only after `CancelRequest` records an actor; its action re-authenticates, authorizes the same queue/request, and derives identity from the trusted session rather than browser input. Land remains out of scope until change-level authorization is defined. Hiding a button is not authorization. The library receives resource-bound capabilities for presentation and callbacks for actions, not sessions or an authorization interface. List rows carry their own queue/request capabilities. -Routes remain hand-written host composition roots. A host may expose only a subset; missing `WebPaths` templates suppress links to unmounted routes. Separate route files preserve per-segment layouts, metadata, streaming, Suspense boundaries, and caching. - -The library ships built ESM that preserves `"use client"` directives, with package exports for the default component surface, `./server`, and `./testing`. The reference host targets `next >=16.3 <17`—above the Server Actions CSRF security floor—and compatible React 19 releases. Gateway loaders are `server-only`, never cached, and convert proto messages before data reaches client components. - -`proxy.ts` may perform an optimistic anonymous-user redirect, but every server component, route handler, and server action performs the real authorization check. Multi-instance hosts configure a shared `NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` and `experimental.serverActions.allowedOrigins` when a proxy rewrites `Host`. - -### Step 4 · Browser boundary - -The host passes only serializable configuration, page data, and capabilities to client components. Sessions remain in the host: +Library components are synchronous and render only their props; they never fetch. Data loading lives in gateway helpers called by host routes, which keeps the boundary explicit and lets components be tested without a server. -```tsx -// web/service/submitqueue/app/layout.tsx (host-owned) -export default async function RootLayout({ children }: { children: React.ReactNode }) { - return ( - - - - {children} - - - - ) -} -``` +Routes remain hand-written composition roots, and hosts may expose subsets. `WebPaths` controls internal links so unmounted routes are not advertised. Gateway loaders are `server-only` and uncached. Only serializable models, resource-bound capabilities, and opaque server-action references cross to client components; sessions, proto messages, and gateway clients do not. -Phase one uses client `error.tsx` boundaries that show `error.digest`, plus `onRequestError`, which logs that digest with the active trace ID. Browser telemetry (`useReportWebVitals` or a dedicated endpoint) is added only when a concrete metric requires it; the library does not prescribe a second collector or browser credential path. +The reference host targets `next >=16.3 <17` and compatible React 19 releases. `proxy.ts` may optimize anonymous redirects, but routes and actions perform authoritative checks. -### Step 5 · Data and wire contracts +### Wire compatibility -Gateway calls run only in server components, route handlers, or server actions. The browser holds a session cookie, never gateway credentials. The gateway is a private dependency reachable only by trusted hosts; otherwise host authorization can be bypassed. +Gateway calls stay on the server, and the gateway remains reachable only by trusted hosts; otherwise host authorization can be bypassed. `make proto` generates and commits TypeScript stubs under `web/api/`, mirroring `protopb/`. Protobuf-ES maps `int64` timestamps to `bigint`; gateway helpers validate safe range and convert them to `number` milliseconds in presentation models. Proto messages never cross into client components. @@ -244,7 +142,7 @@ Before implementation, additive gateway changes provide: - typed `build_url` fields instead of an implicit metadata key - an actor field for audited mutations before web Cancel is enabled -### Step 6 · Errors +### Error boundary Gateway helpers classify from gRPC codes and typed details, never from server messages: @@ -254,144 +152,40 @@ Gateway helpers classify from gRPC codes and typed details, never from server me | `Unavailable`, `DeadlineExceeded` | transient infrastructure error | | `Internal`, `Unknown`, unmapped | infrastructure error | -Unknown errors default to infrastructure errors, and raw gateway messages are never rendered. Gateway follow-up work attaches typed details; the current server only sends `err.Error()` and passes some unclassified errors through. - -Helpers and server actions return result unions for expected outcomes rather than throwing them. Unexpected infrastructure failures reach a client `error.tsx` boundary, which shows only Next's `error.digest`. On the server, `onRequestError` logs the same digest with the active trace ID, route, and request context. Stack traces and reporting destinations remain hidden and host-owned. - -### Step 7 · Host surface - -| File | Content | -|---|---| -| `instrumentation.ts` | Node-guarded OpenTelemetry registration and `onRequestError` | -| `app/layout.tsx` | `` + branding | -| `app/**/page.tsx` | authenticate, load through gateway helpers, and render library components | -| `app/**/action.ts` | authorize mutations and call gateway helpers | -| `proxy.ts` | optimistic anonymous-user redirect only | -| `server/gateway.ts` | `globalThis`-cached transports, clients, and `(queue) => client` routing | -| `server/auth.ts` | authoritative session and resource checks | -| `server/telemetry.ts` | `globalThis`-cached logger plus OpenTelemetry SDK registration | -| `server/config.ts` | validated host config and serializable display config | -| `next.config.ts` | standalone output, tracing root, and Server Action origins | -| `Dockerfile` | the host's image | - -These files contain no presentation logic, gateway request mapping, or status definitions. Those remain in the library. - -## What the library enforces - -| Concern | Enforced by | -|---|---| -| No environment reads in the library | Lint rule banning `process.env` under `web/submitqueue`; CI gate | -| No gateway client in browser bundles | `import 'server-only'` in the `./server` export | -| No unsafe external URLs | Every rendered external href passes an HTTP/HTTPS scheme allowlist | -| Status vocabulary drift | Shared fixture tests the string display table in Go and TypeScript | -| Host controls framework versions | `react` / `next` are `peerDependencies`, never dependencies | -| One protobuf runtime | API package, Connect, and Protobuf-ES versions are aligned in the workspace | -| No telemetry backend in the library | `pino` is an optional type peer and `@opentelemetry/api` is a no-op peer; SDKs and exporters are forbidden in library packages | - -Authorization is host-owned and therefore not enforceable by the library. Host route tests must verify that reads and mutations reject unauthorized sessions; hiding a component based on capabilities is never treated as enforcement. - -## Host telemetry - -`instrumentation.ts` is a separate bundle entry, so shared process objects are cached on `globalThis` rather than relying on module-instance singletons: - -```ts -export async function register() { - if (process.env.NEXT_RUNTIME !== 'nodejs') return - const { registerTelemetry } = await import('./server/telemetry') - await registerTelemetry() -} - -export const onRequestError: Instrumentation.onRequestError = async ( - error, - request, - context, -) => { - if (process.env.NEXT_RUNTIME !== 'nodejs') return - const { reportRequestError } = await import('./server/telemetry') - const digest = - typeof error === 'object' && error !== null && 'digest' in error - ? String(error.digest) - : undefined - reportRequestError({ - error, - digest, - route: context.routePath, - request, - }) -} -``` - -`server/telemetry.ts` owns pino and SDK construction through `globalThis` caches. The OpenTelemetry provider survives through the API global, and the library obtains its meter from that API. `reportRequestError` logs the supplied digest with the active trace ID. - -## Testing - -```ts -import pino from 'pino' - -const data = await loadRequest( - fakeGateway({ 'demo/1': summary({ status: 'landing' }) }), - { queue: 'demo', sqid: 'demo/1' }, - pino({ level: 'silent' }), -) +Unknown errors default to infrastructure errors, and raw gateway messages are never rendered. Expected outcomes use result unions. Unexpected failures reach `error.tsx`, which shows only Next's digest; `onRequestError` logs that digest with trace and request context. -if (!data.ok) throw new Error('test fixture must load') -render() -``` - -The fake implements the generated client shape. Proto fixtures include `bigint` timestamps, but presentation fixtures contain only serializable values. Playwright end-to-end tests use the domain-qualified compose context `e2e-submitqueue-web` ([testing guide](../howto/TESTING.md#container-naming)). - -## Deployment model +### Ownership invariants -The supported deployment is a long-running Node host with server-side gateway access. `next.config.ts` uses `output: "standalone"` and `outputFileTracingRoot` points at `web/`; the Docker build context is `web/`. Hosts behind a rewriting proxy set `experimental.serverActions.allowedOrigins`. +- Host: routes, authorization, gateway construction/routing, telemetry SDKs, configuration, branding, process lifecycle, and deployment. +- Library: gateway mapping, presentation models, components, capabilities, status display, safe links, and display errors. +- `./server` imports `server-only`; library code never reads environment variables or chooses backends. +- External links pass an HTTP/HTTPS allowlist; status fixtures prevent Go/TypeScript drift. +- Committed Go and TypeScript proto outputs are regenerated in a clean-tree drift check. +- Authorization is enforced and tested in host routes/actions. Capabilities only control presentation. -## Build and CI +The supported deployment is a long-running Node host with private gateway access. `web/` stays outside Bazel/Gazelle while remaining inside required checks. -The `web/` pnpm workspace adds these Makefile targets to the existing CI gates: +## UX testing strategy -```makefile -check-proto: ## Check committed Go and TypeScript protobuf files -web-build: ## Build all web packages -web-e2e-test: ## Run Playwright web end-to-end tests -web-lint: ## Lint and typecheck web packages -web-test: ## Run web unit tests -``` - -Targets remain alphabetically sorted with `## Description`; `make lint` and `make test` include their web equivalents. +| Layer | Tool | What it verifies | +|---|---|---| +| Contract/model | Go tests + Vitest | Proto round trips and drift, status compatibility, `bigint` conversion, paging, href safety, error mapping, and client props containing no proto markers or `bigint` | +| Component behavior | Vitest + React Testing Library | Rendering states, interactions, resource capabilities, and keyboard/focus behavior | +| Browser UX | Playwright + axe-core | Responsive and visual regression, real-browser accessibility/contrast, non-color-only statuses, navigation, loading/empty/error states, and stable focus/scroll during polling | +| Host security | Route matrix generated from `app/` + action lint | Every discovered route has an authorization case and rejects missing/denied sessions without `proxy.ts`; a lint rule requires every `'use server'` export to call the authorization helper, and actions reject cross-resource arguments when called directly | +| Host integration | Playwright + Docker Compose | Real gateway list/history flows, polling, transport failures, and later mutation authorization | -Phase one does not use Bazel for TypeScript or Playwright. Bazel 8's root `REPO.bazel` and the root Gazelle directive exclude all of `web/`; web tests run through Make/pnpm and feed the same required-checks gate. `web/go.mod` keeps the root Go module from traversing Node dependencies. This choice can be revisited if hermetic Bazel web tests become necessary. +Browser UX tests use a separate build-time entry point that aliases the reference host's gateway and session providers to fakes; production builds contain neither fake, and a build check verifies the production artifact. Fixtures cover scripted status changes, unknown statuses, long and numerous URIs, long errors, full pages, omitted path templates, and per-row capabilities. Screenshots are deterministic, and the lowest and latest supported Next/React versions run the component and browser suites. -`web/package.json` pins pnpm through `packageManager`, and `.nvmrc` pins Node. The library publishes built ESM and declares `next >=16.3 <17`, compatible React 19, the generated API package, Connect v2, Protobuf-ES v2, and optional pino types as peers. +End-to-end tests use the real gateway in the domain-qualified `e2e-submitqueue-web` context ([testing guide](../howto/TESTING.md#container-naming)). Storybook is not required initially because the fixture mode already renders deterministic browser states. ## Rejected - **Container image instead of a library.** Hosts could not replace authentication, telemetry, or transport without a permanent source fork. - **One catch-all route.** `app/[[...slug]]/page.tsx` would replace Next routing and lose per-segment layouts, metadata, streaming, Suspense boundaries, and caching. - **Static export or embedding in a Go binary.** Dynamic request routes cannot be enumerated, server actions and authoritative route checks disappear, and the grpc-go gateway needs a browser-reachable proxy with its own resource authorization. Revisit only with a separate design. -- **Web extension interfaces.** The gateway is already the domain contract. Extra `Gateway`, `GatewayFactory`, `Authorizer`, and generic `Deps` interfaces duplicate that contract or turn host authentication into library policy. -- **A generic `web/platform` engine.** Next's filesystem already defines route topology, and only one web domain exists. Add shared platform code only after a second domain demonstrates the common behavior. -- **Library-owned auth, logger, or metrics backends.** Token sources, clients, timeouts, transports, and registries are process infrastructure. Shipping them also adds unused dependencies to every host. -- **Bespoke telemetry interfaces.** OpenTelemetry already provides a stable, no-op metrics API. A type-only `pino.Logger` is structurally compatible with other loggers without an adapter or runtime dependency. -- **Environment-based library defaults.** `NEXT_PUBLIC_GATEWAY_ADDR` or similar defaults create a hidden configuration surface. +- **Web extensions, DI, or a generic platform engine.** The gateway and Next filesystem already provide domain and route boundaries. Extra interfaces or runtime assembly duplicate them; shared code is promoted only after another domain demonstrates reuse. +- **Library-owned process infrastructure.** Auth SDKs, logger/metrics backends, environment defaults, token sources, clients, and registries belong to the host. OpenTelemetry and optional pino types already provide the needed contracts. - **GraphQL or REST BFF.** Server components already provide the BFF and the generated gateway client is the domain boundary; another wire contract adds no capability. -- **DI framework.** Host route modules are explicit composition roots and do not need a runtime graph. - **Shared Go/TypeScript view model through WASM or code generation.** A cross-language status fixture catches drift; the remaining presentation code is cheaper than a cross-language runtime. - **Non-Next SPA.** Server components keep gateway access and authorization on the server; an SPA moves both into the browser. - -## Migration path - -The first phase makes additive gateway changes without changing existing behavior: - -1. Add gateway contracts required by the UI (`ListQueues`, attached typed error details, typed `build_url`) and generate committed TypeScript packages under `web/api/`; add Go/TypeScript round-trip and status-fixture checks. -2. Add the read-only `web/submitqueue` package with gateway helpers, models, components, parameter parsers, href helpers, and fakes; add unit and screenshot tests. -3. Add the read-only `web/service/submitqueue` reference host and a `web-ui` service to `service/submitqueue/docker-compose.yml`, depending on `gateway-service`; add `e2e-submitqueue-web`. -4. Add an actor to `CancelRequest`, persist it in request history, and then add the host-authorized Cancel action. Land remains deferred until change-level authorization is designed. -5. Build another host from the published package. Promote shared code only when that host or another domain demonstrates a reusable need. - -## Open questions - -- **Live updates.** Phase one uses polling with server revalidation, matching `client/watch.go`. Server-sent events could follow; a gateway `Watch` RPC needs a separate RFC. -- **`List` filtering.** The [status/list RFC](submitqueue/status-list-api.md) deferred status filters. The first queue view must either filter a receipt-time window or extend the gateway. -- **Authorization capabilities.** Finalize resource-bound capability types for queue pages and request rows. Phase one exposes read capabilities; Cancel follows its actor contract, and Land follows change-level authorization. -- **Initial scope.** Decide whether the first app contains only SubmitQueue or also Stovepipe history. Each domain uses its published RPC contract; Runway currently exposes only `Ping`, so a Runway view requires a new API. A second domain may justify shared UI helpers. -- **OTLP compatibility.** Determine whether intended host metrics backends accept OTLP. Otherwise those hosts must provide a `MetricReader`, making their wiring less similar to the reference host. -- **npm publishing.** The proposed `@submitqueue/*` packages require an npm organization and release cadence. From 2e47042f4cc198a59748eb7d55c47d86f5d35e65 Mon Sep 17 00:00:00 2001 From: Preetam Dwivedi Date: Mon, 28 Sep 2026 10:30:10 -0700 Subject: [PATCH 3/8] docs(web): tighten web library transport and link contracts ## Summary ### Why? Review found contracts that would mis-route requests, emit phishing links, or fail to build as published packages: sqids contain a slash, the gateway speaks native gRPC, speculation runs sibling builds, and helpers cannot install interceptors on an already-created client. ### What? Require percent-encoding of path segments, a scheme-and-authority allowlist, history-only build URLs, `createGrpcTransport` with TLS by default, an exported tracing interceptor, one `@submitqueue/api` package, RSC export invariants, a structural `Logger`, a Node-owned Compose end-to-end check, and a `pnpm pack` test against an external Next app. Co-authored-by: Cursor --- doc/rfc/web-library.md | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/doc/rfc/web-library.md b/doc/rfc/web-library.md index 5f51ad0ad..368b05819 100644 --- a/doc/rfc/web-library.md +++ b/doc/rfc/web-library.md @@ -13,14 +13,14 @@ Hosts supply these deployment-specific inputs: | Concern | The host supplies | Wired with | |---|---|---| | Authentication and authorization | the caller session and allowed actions | host routes, server actions, and an optional optimistic `proxy.ts` redirect | -| Logging | a `pino.Logger`, or any structurally compatible object | `pino` plus `pino-pretty`, `pino-opentelemetry-transport`, or another host-selected transport | +| Logging | a logger matching the library's structural `Logger` type | `pino` plus `pino-pretty`, `pino-opentelemetry-transport`, or another host-selected transport | | Metrics | a registered global OpenTelemetry `MeterProvider`, or none | `@opentelemetry/sdk-metrics` plus a Prometheus or OTLP exporter | -| Gateway transport | a generated gateway client for each queue | Connect transport configured for the host's gateway address, credentials, and edge | +| Gateway transport | a generated gateway client for each queue | `@connectrpc/connect-node` `createGrpcTransport` against the grpc-go gateway | | Configuration | branding, external-host mappings, and internal path templates | a serializable `WebConfig` populated by the host | Keeping these inputs outside the library allows the same UX to run in multiple hosts. This also matches the gateway's existing security boundary: `submitqueue/client/conn.go` can send a bearer token, but this repository does not validate it. Authentication belongs to the proxy, sidecar, ingress, or host in front of the gateway. -Change and build links are concrete helpers over gateway data. Change URIs use `scheme://{host[:port]}/{path}` with a mandatory host and must be interpretable without deployment wiring ([change URIs](change-uri.md)). Build runners already write the provider's web URL into request metadata. Every rendered external link is validated against an HTTP/HTTPS allowlist; `git://` and deployments with different browser hosts use explicit `WebConfig` mappings. +Change and build links are concrete helpers over gateway data. Change URIs use `scheme://{host[:port]}/{path}` with a mandatory host and must be interpretable without deployment wiring ([change URIs](change-uri.md)). A rendered external link must match an explicit host mapping keyed by provider scheme and authority; an HTTP or HTTPS scheme alone is not enough, and an unmapped authority renders as text. Build URLs come from history occurrences, not from a single field on the request summary, because speculation can run several sibling builds for one request. ## Runtime boundary @@ -69,10 +69,10 @@ web/ # pnpm workspace root ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml -├── api/ # committed protobuf-es/Connect output -│ ├── base/change/ -│ ├── base/mergestrategy/ -│ └── submitqueue/gateway/ # @submitqueue/api-submitqueue-gateway +├── api/ # one package, @submitqueue/api +│ ├── base/change/ # generated with the gateway stubs +│ ├── base/mergestrategy/ # so cross-file imports stay intra-package +│ └── submitqueue/gateway/ ├── submitqueue/ # @submitqueue/web-submitqueue │ └── src/ │ ├── gateway/ # server-only RPC helpers @@ -87,7 +87,7 @@ web/ # pnpm workspace root `web/` contains the complete Node workspace, including committed Protobuf-ES/Connect output and the reference host; proto sources and Go output stay in the root `api/` tree. `web/go.mod` and repository exclusions keep Node dependencies outside Go and Gazelle traversal. The web library depends on the generated API package, not Go domain code. -The package ships built ESM with default component exports plus `./server` and `./testing`. React, Next, Connect, Protobuf-ES, and optional pino types are peers so host and library share one runtime. `web/service/submitqueue/` demonstrates composition; deployers own their hosts. +The package ships built ESM with an export map of the root, `./server`, and `./testing`. The root export is components and presentation types only: the build preserves `'use client'`, and nothing reachable from that export imports `server-only` or Node built-ins. `./server` is the only server entry, and `./testing` is test-only. React, Next, Connect, and Protobuf-ES are peers so host and library share one runtime. The logger parameter is a small structural type owned by the library, so pino is not a dependency or a peer. `web/service/submitqueue/` demonstrates composition; deployers own their hosts. Phase one contains SubmitQueue only. Stovepipe can later add `web/stovepipe/` against its published RPCs; Runway needs a read API beyond `Ping` before it can expose UX. Shared UI is promoted only after that second domain exists. @@ -95,17 +95,17 @@ Phase one contains SubmitQueue only. Stovepipe can later add `web/stovepipe/` ag The generated gateway client is the library's only domain dependency. Concrete helpers map gateway responses into presentation models; there is no web-specific gateway interface. -Gateway helpers take `Client`, typed queries, and an optional `pino.Logger`; expected outcomes use result unions. The library obtains its meter through `metrics.getMeter("@submitqueue/web-submitqueue", version)` and never accepts an SDK or exporter. +Gateway helpers take `Client`, typed queries, and an optional structural `Logger`; expected outcomes use result unions. The library obtains its meter through `metrics.getMeter("@submitqueue/web-submitqueue", version)` and never accepts an SDK or exporter. -The host constructs Node gRPC clients, supplies credentials and deadlines, and routes queues with a plain `(queue) => generated client` function. Cross-queue helpers take that function. The library supplies presentation/error mapping, tracing instrumentation, and a fake generated client for tests. +The gateway serves native gRPC, so the host builds clients with `@connectrpc/connect-node` `createGrpcTransport` over HTTP/2. TLS is the default; plaintext h2c is an explicit host opt-in for a local stack, and an integration test dials the real gateway. The host supplies credentials and deadlines, caches transports, and routes queues with a plain `(queue) => generated client` function. Cross-queue helpers take that function. Helpers cannot attach interceptors to a client they receive already built, so the library exports a tracing interceptor for the host to install while constructing the transport. Tests use a fake generated client. If a view needs missing domain data, the gateway contract grows instead of adding a web-only backend. Phase one adds `ListQueues`, backed by `queueconfig.Store.List`; a multi-gateway host fans it out across configured endpoints and rejects its configuration at startup if two gateways report the same queue name. Phase one refreshes views with a small client component that calls `router.refresh()` on an interval, re-running the server loaders, matching `submitqueue/client/watch.go`. It presents the bounded receipt-history `List` without status filtering. Streaming or filtered gateway APIs require separate contract changes. -Link helpers derive change and build URLs from gateway data and internal links from serializable `WebPaths` templates such as `/q/{queue}/r/{sqid}`. A missing template suppresses the link. `build_url` is added to `HistoryEvent`, where each build occurrence belongs, and may be mirrored on `RequestSummary` for the current build. +Link helpers derive change URLs from gateway data through the trusted scheme-and-authority mapping, and internal links from serializable `WebPaths` templates such as `/q/{queue}/r/{sqid}`. Each substituted value is percent-encoded as one path segment: an sqid is `/`, so raw substitution would split the route, and queue names may contain `/`, `%`, `?`, `#`, `.`, or `..`. A missing template suppresses the link. Build URLs stay on history occurrences; `RequestSummary` does not carry one, because several sibling builds can be in flight for the same request. -The library depends only on `@opentelemetry/api` and obtains its own meter. SDKs, exporters, collector addresses, and logger construction remain host concerns. A Connect interceptor nests gateway spans under the active Next request trace. +The library depends only on `@opentelemetry/api` and obtains its own meter. SDKs, exporters, collector addresses, and logger construction remain host concerns. The exported tracing interceptor nests gateway spans under the active Next request trace. ### Host composition @@ -139,7 +139,7 @@ Before implementation, additive gateway changes provide: - `ListQueues` - typed gRPC status details for known errors -- typed `build_url` fields instead of an implicit metadata key +- a typed build URL on history occurrences, not on `RequestSummary` - an actor field for audited mutations before web Cancel is enabled ### Error boundary @@ -159,25 +159,27 @@ Unknown errors default to infrastructure errors, and raw gateway messages are ne - Host: routes, authorization, gateway construction/routing, telemetry SDKs, configuration, branding, process lifecycle, and deployment. - Library: gateway mapping, presentation models, components, capabilities, status display, safe links, and display errors. - `./server` imports `server-only`; library code never reads environment variables or chooses backends. -- External links pass an HTTP/HTTPS allowlist; status fixtures prevent Go/TypeScript drift. +- External links require a trusted scheme-and-authority mapping; status fixtures prevent Go/TypeScript drift. +- Internal path substitutions encode each value as one segment, covering `/`, `%`, `?`, `#`, `.`, and `..`. - Committed Go and TypeScript proto outputs are regenerated in a clean-tree drift check. - Authorization is enforced and tested in host routes/actions. Capabilities only control presentation. -The supported deployment is a long-running Node host with private gateway access. `web/` stays outside Bazel/Gazelle while remaining inside required checks. +The supported deployment is a long-running Node host with private gateway access. `web/` stays outside Gazelle so the Go build graph does not index it. End-to-end coverage is a separate required check, not a Bazel test: a Node-owned job, pinned to the workspace Node version and lockfile, builds the host and runs Playwright against Compose using the domain-qualified `e2e-submitqueue-web` context ([testing guide](../howto/TESTING.md#container-naming)). ## UX testing strategy | Layer | Tool | What it verifies | |---|---|---| -| Contract/model | Go tests + Vitest | Proto round trips and drift, status compatibility, `bigint` conversion, paging, href safety, error mapping, and client props containing no proto markers or `bigint` | +| Contract/model | Go tests + Vitest | Proto round trips and drift, status compatibility, `bigint` conversion, paging, segment encoding, trusted-authority links, error mapping, and client props containing no proto markers or `bigint` | | Component behavior | Vitest + React Testing Library | Rendering states, interactions, resource capabilities, and keyboard/focus behavior | | Browser UX | Playwright + axe-core | Responsive and visual regression, real-browser accessibility/contrast, non-color-only statuses, navigation, loading/empty/error states, and stable focus/scroll during polling | | Host security | Route matrix generated from `app/` + action lint | Every discovered route has an authorization case and rejects missing/denied sessions without `proxy.ts`; a lint rule requires every `'use server'` export to call the authorization helper, and actions reject cross-resource arguments when called directly | -| Host integration | Playwright + Docker Compose | Real gateway list/history flows, polling, transport failures, and later mutation authorization | +| Host integration | Node-owned Playwright + Compose | Real grpc-go gateway list/history flows, TLS and explicit h2c, polling, transport failures, and later mutation authorization | +| Published package | `pnpm pack` into an external Next app | The packed library and API tarballs install outside the workspace, their export maps match the root, `./server`, and `./testing`, the root stays free of `server-only`, and both supported Next/React bounds build | Browser UX tests use a separate build-time entry point that aliases the reference host's gateway and session providers to fakes; production builds contain neither fake, and a build check verifies the production artifact. Fixtures cover scripted status changes, unknown statuses, long and numerous URIs, long errors, full pages, omitted path templates, and per-row capabilities. Screenshots are deterministic, and the lowest and latest supported Next/React versions run the component and browser suites. -End-to-end tests use the real gateway in the domain-qualified `e2e-submitqueue-web` context ([testing guide](../howto/TESTING.md#container-naming)). Storybook is not required initially because the fixture mode already renders deterministic browser states. +Storybook is not required initially because the fixture build already renders deterministic browser states. ## Rejected @@ -185,7 +187,7 @@ End-to-end tests use the real gateway in the domain-qualified `e2e-submitqueue-w - **One catch-all route.** `app/[[...slug]]/page.tsx` would replace Next routing and lose per-segment layouts, metadata, streaming, Suspense boundaries, and caching. - **Static export or embedding in a Go binary.** Dynamic request routes cannot be enumerated, server actions and authoritative route checks disappear, and the grpc-go gateway needs a browser-reachable proxy with its own resource authorization. Revisit only with a separate design. - **Web extensions, DI, or a generic platform engine.** The gateway and Next filesystem already provide domain and route boundaries. Extra interfaces or runtime assembly duplicate them; shared code is promoted only after another domain demonstrates reuse. -- **Library-owned process infrastructure.** Auth SDKs, logger/metrics backends, environment defaults, token sources, clients, and registries belong to the host. OpenTelemetry and optional pino types already provide the needed contracts. +- **Library-owned process infrastructure.** Auth SDKs, logger/metrics backends, environment defaults, token sources, clients, and registries belong to the host. OpenTelemetry supplies the metrics contract; logging uses a structural type the host's logger satisfies. - **GraphQL or REST BFF.** Server components already provide the BFF and the generated gateway client is the domain boundary; another wire contract adds no capability. - **Shared Go/TypeScript view model through WASM or code generation.** A cross-language status fixture catches drift; the remaining presentation code is cheaper than a cross-language runtime. - **Non-Next SPA.** Server components keep gateway access and authorization on the server; an SPA moves both into the browser. From c2bd35f29f56201509e983957c5cdd9e3b0af46a Mon Sep 17 00:00:00 2001 From: Preetam Dwivedi Date: Mon, 28 Sep 2026 10:39:19 -0700 Subject: [PATCH 4/8] docs(web): condense the web library RFC ## Summary ### Why? The RFC restated the same host and library boundaries and specified phase-one machinery the host already owns or that a read-only release does not need. ### What? State each boundary once. Keep phase one read-only, with queue names configured by the host. Record proxy-safe base64url paths, request-time rendering, stable list windows, and polling limits, and move build and test detail into acceptance criteria. Co-authored-by: Cursor --- doc/rfc/web-library.md | 206 ++++++++--------------------------------- 1 file changed, 38 insertions(+), 168 deletions(-) diff --git a/doc/rfc/web-library.md b/doc/rfc/web-library.md index 368b05819..23d1b7222 100644 --- a/doc/rfc/web-library.md +++ b/doc/rfc/web-library.md @@ -1,193 +1,63 @@ # Web as a Library -SubmitQueue should publish its web UX as a library of components, gateway helpers, and presentation models. A deployer-owned Next application supplies authentication, telemetry, configuration, routes, and gateway connectivity. +## Decision -## Problem +SubmitQueue publishes its browser UX as a library of components, gateway helpers, and presentation models. A deployer-owned Next application supplies routes, authentication, telemetry, configuration, and gateway connectivity. -There is no browser UX today. The gateway already exposes the required read APIs: `GetRequestSummaryByID`, `GetRequestSummaryByChangeURI`, `List`, `GetRequestHistoryByID`, and `GetRequestHistoryByChangeURI` ([status/list](submitqueue/status-list-api.md), [history](submitqueue/history-api.md)). It also exposes `Cancel`, which needs an actor/audit contract before the web host uses it. `submitqueue/client/` already renders the read data in a terminal. +The package resembles `submitqueue/client/`, while the host resembles service wiring. The library consumes the published gateway contract and maps it to presentation. Domain extensions stay behind the gateway. -A repository-owned Next application would couple the reusable UX to one deployment's environment variables, authentication, telemetry, and gateway routing. Unlike a Go deployer, who can import the library and replace `service/.../main.go`, a Next deployer would have to fork the application root (`app/`, `proxy.ts`, and `next.config.ts`). +Phase one is read-only: request summary, history, and queue receipt list ([status/list](submitqueue/status-list-api.md), [history](submitqueue/history-api.md)). Mutations require a separate authorization and audit design. -Hosts supply these deployment-specific inputs: +## Host/library boundary -| Concern | The host supplies | Wired with | -|---|---|---| -| Authentication and authorization | the caller session and allowed actions | host routes, server actions, and an optional optimistic `proxy.ts` redirect | -| Logging | a logger matching the library's structural `Logger` type | `pino` plus `pino-pretty`, `pino-opentelemetry-transport`, or another host-selected transport | -| Metrics | a registered global OpenTelemetry `MeterProvider`, or none | `@opentelemetry/sdk-metrics` plus a Prometheus or OTLP exporter | -| Gateway transport | a generated gateway client for each queue | `@connectrpc/connect-node` `createGrpcTransport` against the grpc-go gateway | -| Configuration | branding, external-host mappings, and internal path templates | a serializable `WebConfig` populated by the host | - -Keeping these inputs outside the library allows the same UX to run in multiple hosts. This also matches the gateway's existing security boundary: `submitqueue/client/conn.go` can send a bearer token, but this repository does not validate it. Authentication belongs to the proxy, sidecar, ingress, or host in front of the gateway. - -Change and build links are concrete helpers over gateway data. Change URIs use `scheme://{host[:port]}/{path}` with a mandatory host and must be interpretable without deployment wiring ([change URIs](change-uri.md)). A rendered external link must match an explicit host mapping keyed by provider scheme and authority; an HTTP or HTTPS scheme alone is not enough, and an unmapped authority renders as text. Build URLs come from history occurrences, not from a single field on the request summary, because speculation can run several sibling builds for one request. - -## Runtime boundary - -Unlike a Go service, a Next application runs in three environments: - -``` -build route discovery, bundling, and static generation; no host process -server Node server components, route handlers, server actions, and proxy -browser client components on another machine; serializable data and opaque - server-action references only -``` - -Next owns the request loop and bundler, so the library cannot own "no server" in the literal Go sense. Instead, it owns no process and no application root. The host owns the Next app root and resolves server dependencies once per process. Only serializable data, capabilities, and opaque server-action references cross into client components. - -## Design principles - -- **Use the gateway as the domain boundary.** Web code reads and mutates SubmitQueue only through the published gateway API. Missing domain data should extend that API. -- **Keep deployment policy in the host.** The library does not read environment variables, open listeners, import auth SDKs, choose telemetry exporters, hardcode external URLs, or exit the process. -- **Keep server dependencies on the server.** Host objects are never serialized into client components. -- **Compose with data and callbacks.** Host routes pass serializable data, capabilities, and authorized server actions to library components. -- **Keep gateway routing private to the host.** Per-queue gateway selection is a plain host function, not a library interface. -- **Let the host choose framework versions.** `react`, `react-dom`, and `next` are peer dependencies. +| Library | Host | +|---|---| +| Gateway-to-presentation mapping, components, status and error display | Next application root, routes, and which subset to expose | +| Internal and external link helpers | Queue names, per-queue gateway routing, credentials, and deadlines | +| OpenTelemetry API instrumentation and a structural `Logger` | Session authorization, telemetry backends, configuration, and process lifecycle | -## Go analogy and its limits +The host configures the queues it serves and selects each generated client with `(queue) => client`. It builds those clients with `@connectrpc/connect-node` `createGrpcTransport` over HTTP/2: TLS by default, plaintext h2c only as an explicit local option. It installs the library's tracing interceptor while constructing the transport. The gateway stays reachable only by trusted hosts. -The reusable web package most closely matches `submitqueue/client/`, not `pipeline.Construct`: +Components render serializable props and do not fetch. Sessions, gateway clients, and protobuf messages stay on the server. Server helpers call `connection()` before gateway I/O, host routes that call them are dynamically rendered, and neither side caches gateway results. -| Web | Go analogue | -|---|---| -| Gateway query helpers, paging, presentation models | `submitqueue/client/query.go`, `view.go`, and `watch.go` | -| Host route, auth checks, transport, and telemetry wiring | `service/.../main.go` | -| `(queue) => generated client` | host-private `Factory.For(Config{QueueName})` routing | +`WebPaths` selects internal links. Each substituted value is unpadded base64url, so a slash inside an sqid (`/`) remains one path segment after a proxy decodes `%2F`. External links require a host mapping keyed by change-URI scheme and authority; other values render as text. Build URLs stay on history occurrences, because one request can have concurrent sibling builds. -The analogy stops at the wire boundary. Go controllers take domain entities and keep protobuf mapping in the host. The web library intentionally consumes the published gateway contract, so gateway-to-presentation mapping and gRPC-status-to-display-error mapping belong in the library. All deeper domain extensions remain behind the gateway. +`List` requires a queue and a half-open receipt window. A first visit uses a trailing 24-hour window, which the host may override. Both bounds live in the route's search parameters and stay fixed across refresh and paging, because the page token is valid only for that queue and those bounds. Changing the window drops the token. -## Design +A client component calls `router.refresh()` to rerun the server loaders. One refresh runs at a time. The wait is the terminal client's poll interval plus jitter, grows after a transport failure, and pauses while the document is hidden or the browser is offline. A request view stops on `landed`, `error`, or `cancelled`. A queue list keeps polling for the life of its fixed window. -### Package boundary +## Package shape -Start with one domain package. Promote shared code only after another domain needs it: +The pnpm workspace lives under `web/`, with a nested `web/go.mod` so the Go build graph does not index it: ``` -web/ # pnpm workspace root -├── go.mod # exclude Node dependencies from root Go ./... -├── .nvmrc -├── package.json -├── pnpm-lock.yaml -├── pnpm-workspace.yaml -├── api/ # one package, @submitqueue/api -│ ├── base/change/ # generated with the gateway stubs -│ ├── base/mergestrategy/ # so cross-file imports stay intra-package -│ └── submitqueue/gateway/ -├── submitqueue/ # @submitqueue/web-submitqueue -│ └── src/ -│ ├── gateway/ # server-only RPC helpers -│ ├── component/ # server and client UI components -│ ├── model/ # presentation models and capabilities -│ ├── params.ts # route/search parameter parsing -│ ├── href.ts # external and internal link helpers -│ └── testing/ # fixtures and fake generated clients -└── service/ - └── submitqueue/ # reference host and Next application root +web/ +├── api/ # @submitqueue/api, one package for base and gateway stubs +├── submitqueue/ # @submitqueue/web-submitqueue +└── service/submitqueue/ # reference host ``` -`web/` contains the complete Node workspace, including committed Protobuf-ES/Connect output and the reference host; proto sources and Go output stay in the root `api/` tree. `web/go.mod` and repository exclusions keep Node dependencies outside Go and Gazelle traversal. The web library depends on the generated API package, not Go domain code. - -The package ships built ESM with an export map of the root, `./server`, and `./testing`. The root export is components and presentation types only: the build preserves `'use client'`, and nothing reachable from that export imports `server-only` or Node built-ins. `./server` is the only server entry, and `./testing` is test-only. React, Next, Connect, and Protobuf-ES are peers so host and library share one runtime. The logger parameter is a small structural type owned by the library, so pino is not a dependency or a peer. `web/service/submitqueue/` demonstrates composition; deployers own their hosts. - -Phase one contains SubmitQueue only. Stovepipe can later add `web/stovepipe/` against its published RPCs; Runway needs a read API beyond `Ping` before it can expose UX. Shared UI is promoted only after that second domain exists. - -### Gateway boundary - -The generated gateway client is the library's only domain dependency. Concrete helpers map gateway responses into presentation models; there is no web-specific gateway interface. - -Gateway helpers take `Client`, typed queries, and an optional structural `Logger`; expected outcomes use result unions. The library obtains its meter through `metrics.getMeter("@submitqueue/web-submitqueue", version)` and never accepts an SDK or exporter. - -The gateway serves native gRPC, so the host builds clients with `@connectrpc/connect-node` `createGrpcTransport` over HTTP/2. TLS is the default; plaintext h2c is an explicit host opt-in for a local stack, and an integration test dials the real gateway. The host supplies credentials and deadlines, caches transports, and routes queues with a plain `(queue) => generated client` function. Cross-queue helpers take that function. Helpers cannot attach interceptors to a client they receive already built, so the library exports a tracing interceptor for the host to install while constructing the transport. Tests use a fake generated client. - -If a view needs missing domain data, the gateway contract grows instead of adding a web-only backend. Phase one adds `ListQueues`, backed by `queueconfig.Store.List`; a multi-gateway host fans it out across configured endpoints and rejects its configuration at startup if two gateways report the same queue name. - -Phase one refreshes views with a small client component that calls `router.refresh()` on an interval, re-running the server loaders, matching `submitqueue/client/watch.go`. It presents the bounded receipt-history `List` without status filtering. Streaming or filtered gateway APIs require separate contract changes. - -Link helpers derive change URLs from gateway data through the trusted scheme-and-authority mapping, and internal links from serializable `WebPaths` templates such as `/q/{queue}/r/{sqid}`. Each substituted value is percent-encoded as one path segment: an sqid is `/`, so raw substitution would split the route, and queue names may contain `/`, `%`, `?`, `#`, `.`, or `..`. A missing template suppresses the link. Build URLs stay on history occurrences; `RequestSummary` does not carry one, because several sibling builds can be in flight for the same request. - -The library depends only on `@opentelemetry/api` and obtains its own meter. SDKs, exporters, collector addresses, and logger construction remain host concerns. The exported tracing interceptor nests gateway spans under the active Next request trace. - -### Host composition - -Next's filesystem is the route topology; there is no runtime engine or view registry. Each host route: - -1. Resolve and authorize the host session. -2. Select and call the generated gateway client through library helpers. -3. Derive serializable capabilities and data. -4. Render a library component. -5. Provide host-owned server actions for enabled mutations. - -Route params are untrusted and parsed before lookup. Phase one is read-only. Cancel follows only after `CancelRequest` records an actor; its action re-authenticates, authorizes the same queue/request, and derives identity from the trusted session rather than browser input. Land remains out of scope until change-level authorization is defined. - -Hiding a button is not authorization. The library receives resource-bound capabilities for presentation and callbacks for actions, not sessions or an authorization interface. List rows carry their own queue/request capabilities. - -Library components are synchronous and render only their props; they never fetch. Data loading lives in gateway helpers called by host routes, which keeps the boundary explicit and lets components be tested without a server. - -Routes remain hand-written composition roots, and hosts may expose subsets. `WebPaths` controls internal links so unmounted routes are not advertised. Gateway loaders are `server-only` and uncached. Only serializable models, resource-bound capabilities, and opaque server-action references cross to client components; sessions, proto messages, and gateway clients do not. - -The reference host targets `next >=16.3 <17` and compatible React 19 releases. `proxy.ts` may optimize anonymous redirects, but routes and actions perform authoritative checks. - -### Wire compatibility - -Gateway calls stay on the server, and the gateway remains reachable only by trusted hosts; otherwise host authorization can be bypassed. - -`make proto` generates and commits TypeScript stubs under `web/api/`, mirroring `protopb/`. Protobuf-ES maps `int64` timestamps to `bigint`; gateway helpers validate safe range and convert them to `number` milliseconds in presentation models. Proto messages never cross into client components. - -Gateway statuses are strings today, not an enum. The library owns a display table for color, ordering, and terminal state plus an explicit unknown-status fallback. A committed fixture under `api/submitqueue/gateway/testdata/` is checked by both Go and TypeScript tests so new `entity.RequestStatus*` values cannot silently miss web presentation; keeping it outside `web/` lets hermetic Go tests read it. - -Before implementation, additive gateway changes provide: - -- `ListQueues` -- typed gRPC status details for known errors -- a typed build URL on history occurrences, not on `RequestSummary` -- an actor field for audited mutations before web Cancel is enabled - -### Error boundary - -Gateway helpers classify from gRPC codes and typed details, never from server messages: - -| Codes | Display classification | -|---|---| -| `InvalidArgument`, `NotFound`, `ResourceExhausted` | actionable user error | -| `Unavailable`, `DeadlineExceeded` | transient infrastructure error | -| `Internal`, `Unknown`, unmapped | infrastructure error | - -Unknown errors default to infrastructure errors, and raw gateway messages are never rendered. Expected outcomes use result unions. Unexpected failures reach `error.tsx`, which shows only Next's digest; `onRequestError` logs that digest with trace and request context. - -### Ownership invariants - -- Host: routes, authorization, gateway construction/routing, telemetry SDKs, configuration, branding, process lifecycle, and deployment. -- Library: gateway mapping, presentation models, components, capabilities, status display, safe links, and display errors. -- `./server` imports `server-only`; library code never reads environment variables or chooses backends. -- External links require a trusted scheme-and-authority mapping; status fixtures prevent Go/TypeScript drift. -- Internal path substitutions encode each value as one segment, covering `/`, `%`, `?`, `#`, `.`, and `..`. -- Committed Go and TypeScript proto outputs are regenerated in a clean-tree drift check. -- Authorization is enforced and tested in host routes/actions. Capabilities only control presentation. - -The supported deployment is a long-running Node host with private gateway access. `web/` stays outside Gazelle so the Go build graph does not index it. End-to-end coverage is a separate required check, not a Bazel test: a Node-owned job, pinned to the workspace Node version and lockfile, builds the host and runs Playwright against Compose using the domain-qualified `e2e-submitqueue-web` context ([testing guide](../howto/TESTING.md#container-naming)). +Generated TypeScript is committed beside the Go stubs. Gateway stubs and the base protos they import share one package, so the imports stay valid after publish. The library ships ESM at the root, `./server`, and `./testing`. The root preserves `'use client'` and reaches no `server-only` or Node-only code. React, Next, Connect, and Protobuf-ES are peers. Shared UI waits until a second domain needs it. -## UX testing strategy +## Prerequisites -| Layer | Tool | What it verifies | -|---|---|---| -| Contract/model | Go tests + Vitest | Proto round trips and drift, status compatibility, `bigint` conversion, paging, segment encoding, trusted-authority links, error mapping, and client props containing no proto markers or `bigint` | -| Component behavior | Vitest + React Testing Library | Rendering states, interactions, resource capabilities, and keyboard/focus behavior | -| Browser UX | Playwright + axe-core | Responsive and visual regression, real-browser accessibility/contrast, non-color-only statuses, navigation, loading/empty/error states, and stable focus/scroll during polling | -| Host security | Route matrix generated from `app/` + action lint | Every discovered route has an authorization case and rejects missing/denied sessions without `proxy.ts`; a lint rule requires every `'use server'` export to call the authorization helper, and actions reject cross-resource arguments when called directly | -| Host integration | Node-owned Playwright + Compose | Real grpc-go gateway list/history flows, TLS and explicit h2c, polling, transport failures, and later mutation authorization | -| Published package | `pnpm pack` into an external Next app | The packed library and API tarballs install outside the workspace, their export maps match the root, `./server`, and `./testing`, the root stays free of `server-only`, and both supported Next/React bounds build | +- Typed gRPC details for known errors. Helpers classify `InvalidArgument`, `NotFound`, and `ResourceExhausted` as user errors, `Unavailable` and `DeadlineExceeded` as transient infrastructure errors, and every other code as an infrastructure error. Raw gateway messages are not rendered. +- A typed build URL on history occurrences. +- Status values stay strings. The library has a display table and an unknown fallback, checked against a fixture in `api/submitqueue/gateway/testdata/`. +- Protobuf `int64` timestamps become numeric milliseconds in presentation models after a safe-range check. -Browser UX tests use a separate build-time entry point that aliases the reference host's gateway and session providers to fakes; production builds contain neither fake, and a build check verifies the production artifact. Fixtures cover scripted status changes, unknown statuses, long and numerous URIs, long errors, full pages, omitted path templates, and per-row capabilities. Screenshots are deterministic, and the lowest and latest supported Next/React versions run the component and browser suites. +## Acceptance -Storybook is not required initially because the fixture build already renders deterministic browser states. +- Go and Vitest tests cover proto drift, the status fixture, timestamp conversion, stable list bounds, base64url paths, trusted links, and error classification. +- Component tests cover rendering and polling controls: single-flight, jitter and backoff, hidden and offline pause, and terminal stop. +- Playwright and axe-core cover browser accessibility, responsive and visual states, navigation, and stable focus and scroll. +- Every host route rejects a missing or denied session without relying on `proxy.ts`. +- A Node-owned Compose check, outside Bazel and in required checks, runs the reference host against the real grpc-go gateway as `e2e-submitqueue-web` ([testing guide](../howto/TESTING.md#container-naming)). It covers TLS and explicit h2c, and a slash-containing sqid fetched through the deployment proxy. +- `pnpm pack` tarballs install into an external Next app, match the root, `./server`, and `./testing` export map, keep `server-only` out of the root, and build at `next >=16.3 <17` with both supported React 19 bounds. +- Browser fakes are a build-time alias. The production artifact contains none. ## Rejected -- **Container image instead of a library.** Hosts could not replace authentication, telemetry, or transport without a permanent source fork. -- **One catch-all route.** `app/[[...slug]]/page.tsx` would replace Next routing and lose per-segment layouts, metadata, streaming, Suspense boundaries, and caching. -- **Static export or embedding in a Go binary.** Dynamic request routes cannot be enumerated, server actions and authoritative route checks disappear, and the grpc-go gateway needs a browser-reachable proxy with its own resource authorization. Revisit only with a separate design. -- **Web extensions, DI, or a generic platform engine.** The gateway and Next filesystem already provide domain and route boundaries. Extra interfaces or runtime assembly duplicate them; shared code is promoted only after another domain demonstrates reuse. -- **Library-owned process infrastructure.** Auth SDKs, logger/metrics backends, environment defaults, token sources, clients, and registries belong to the host. OpenTelemetry supplies the metrics contract; logging uses a structural type the host's logger satisfies. -- **GraphQL or REST BFF.** Server components already provide the BFF and the generated gateway client is the domain boundary; another wire contract adds no capability. -- **Shared Go/TypeScript view model through WASM or code generation.** A cross-language status fixture catches drift; the remaining presentation code is cheaper than a cross-language runtime. -- **Non-Next SPA.** Server components keep gateway access and authorization on the server; an SPA moves both into the browser. +- **A repository-owned application or container.** Another deployer would have to fork routes, authentication, telemetry, and transport. +- **Static export or embedding in a Go binary.** Request routes are dynamic, and the gateway stays private to a server that can authorize the caller. +- **A generic runtime, DI container, or web-extension layer.** Next's filesystem and the generated gateway client are the composition boundaries. From 2f2db444b455342c98ddc976e5b7912d7a1aa4dc Mon Sep 17 00:00:00 2001 From: Preetam Dwivedi Date: Mon, 28 Sep 2026 13:56:16 -0700 Subject: [PATCH 5/8] docs(web): align RFC with shipped coverage ## Summary ### Why? The RFC still described deferred telemetry, link, transport, and test-matrix capabilities as shipped prerequisites and acceptance criteria. ### What? Limit the host/library contract and acceptance section to the implemented diagnostic, polling, package, and h2c E2E coverage. Record trusted links, typed build URLs, OpenTelemetry, TLS E2E, shared status fixtures, and broader browser/version matrices as deferred work. --- doc/rfc/web-library.md | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/doc/rfc/web-library.md b/doc/rfc/web-library.md index 23d1b7222..bf19ea69e 100644 --- a/doc/rfc/web-library.md +++ b/doc/rfc/web-library.md @@ -13,18 +13,18 @@ Phase one is read-only: request summary, history, and queue receipt list ([statu | Library | Host | |---|---| | Gateway-to-presentation mapping, components, status and error display | Next application root, routes, and which subset to expose | -| Internal and external link helpers | Queue names, per-queue gateway routing, credentials, and deadlines | -| OpenTelemetry API instrumentation and a structural `Logger` | Session authorization, telemetry backends, configuration, and process lifecycle | +| Internal link helpers and a structural gateway-diagnostic hook | Queue names, per-queue gateway routing, credentials, deadlines, and the diagnostic backend | +| Serializable view models and polling controls | Session authorization, configuration, and process lifecycle | The host configures the queues it serves and selects each generated client with `(queue) => client`. It builds those clients with `@connectrpc/connect-node` `createGrpcTransport` over HTTP/2: TLS by default, plaintext h2c only as an explicit local option. It installs the library's tracing interceptor while constructing the transport. The gateway stays reachable only by trusted hosts. Components render serializable props and do not fetch. Sessions, gateway clients, and protobuf messages stay on the server. Server helpers call `connection()` before gateway I/O, host routes that call them are dynamically rendered, and neither side caches gateway results. -`WebPaths` selects internal links. Each substituted value is unpadded base64url, so a slash inside an sqid (`/`) remains one path segment after a proxy decodes `%2F`. External links require a host mapping keyed by change-URI scheme and authority; other values render as text. Build URLs stay on history occurrences, because one request can have concurrent sibling builds. +`WebPaths` selects internal links. Each substituted value is unpadded base64url, so a slash inside an sqid (`/`) remains one path segment after a proxy decodes `%2F`. Phase one renders change URIs and build metadata as text; trusted external-link mapping and typed build URLs are deferred. -`List` requires a queue and a half-open receipt window. A first visit uses a trailing 24-hour window, which the host may override. Both bounds live in the route's search parameters and stay fixed across refresh and paging, because the page token is valid only for that queue and those bounds. Changing the window drops the token. +`List` requires a queue and a half-open receipt window. A first visit uses a trailing 24-hour window, which the host may override. Both bounds live in the route's search parameters and stay fixed across refresh and paging, because the page token is valid only for that queue and those bounds. Changing or resetting the window drops the token; the reference host links back to an unbounded `/requests` route to establish a fresh trailing window. -A client component calls `router.refresh()` to rerun the server loaders. One refresh runs at a time. The wait is the terminal client's poll interval plus jitter, grows after a transport failure, and pauses while the document is hidden or the browser is offline. A request view stops on `landed`, `error`, or `cancelled`. A queue list keeps polling for the life of its fixed window. +A client component starts `router.refresh()` inside a React transition and does not schedule the next refresh until that transition finishes. The wait is the terminal client's poll interval plus jitter, grows across consecutive transport failures, and pauses while the document is hidden or the browser is offline. A request view stops only after the summary is terminal and successfully loaded history contains the same terminal status. A queue list keeps polling for the life of its fixed window. ## Package shape @@ -39,23 +39,27 @@ web/ Generated TypeScript is committed beside the Go stubs. Gateway stubs and the base protos they import share one package, so the imports stay valid after publish. The library ships ESM at the root, `./server`, and `./testing`. The root preserves `'use client'` and reaches no `server-only` or Node-only code. React, Next, Connect, and Protobuf-ES are peers. Shared UI waits until a second domain needs it. -## Prerequisites +## Shipped compatibility contracts -- Typed gRPC details for known errors. Helpers classify `InvalidArgument`, `NotFound`, and `ResourceExhausted` as user errors, `Unavailable` and `DeadlineExceeded` as transient infrastructure errors, and every other code as an infrastructure error. Raw gateway messages are not rendered. -- A typed build URL on history occurrences. -- Status values stay strings. The library has a display table and an unknown fallback, checked against a fixture in `api/submitqueue/gateway/testdata/`. +- Helpers classify `InvalidArgument`, `NotFound`, and `ResourceExhausted` as user errors, `Unavailable` and `DeadlineExceeded` as transient infrastructure errors, and every other code as an infrastructure error. Raw gateway messages are not rendered. A host-supplied diagnostic hook receives the operation, request identity, Connect code, and original cause on the server. +- Status values stay strings. The library has a display table and an unknown fallback. - Protobuf `int64` timestamps become numeric milliseconds in presentation models after a safe-range check. ## Acceptance -- Go and Vitest tests cover proto drift, the status fixture, timestamp conversion, stable list bounds, base64url paths, trusted links, and error classification. -- Component tests cover rendering and polling controls: single-flight, jitter and backoff, hidden and offline pause, and terminal stop. -- Playwright and axe-core cover browser accessibility, responsive and visual states, navigation, and stable focus and scroll. -- Every host route rejects a missing or denied session without relying on `proxy.ts`. -- A Node-owned Compose check, outside Bazel and in required checks, runs the reference host against the real grpc-go gateway as `e2e-submitqueue-web` ([testing guide](../howto/TESTING.md#container-naming)). It covers TLS and explicit h2c, and a slash-containing sqid fetched through the deployment proxy. -- `pnpm pack` tarballs install into an external Next app, match the root, `./server`, and `./testing` export map, keep `server-only` out of the root, and build at `next >=16.3 <17` with both supported React 19 bounds. +- Vitest tests cover proto drift, timestamp conversion, stable list bounds, base64url paths, error classification, host-controlled deadlines, structured diagnostics, readiness configuration, and polling controls including transition-aware single-flight, progressive backoff, hidden/offline pause, and history-aware terminal stop. +- Every protected host layout and route repeats the session check rather than relying only on `proxy.ts`. +- A Node-owned Compose check, outside Bazel and in required checks, runs the reference host against the real grpc-go gateway as `e2e-submitqueue-web` ([testing guide](../howto/TESTING.md#container-naming)). It covers the Basic-auth challenge, explicit h2c, newest-first list navigation, a slash-containing sqid, lifecycle/build history, and axe-core checks on list and detail pages. +- `pnpm pack` tarballs install into an external TypeScript consumer and typecheck the root, `./server`, and `./testing` export map. The repository's Next 16 reference host production build separately verifies the framework integration. - Browser fakes are a build-time alias. The production artifact contains none. +## Deferred + +- Trusted change links and typed build-history links wait for a host-owned allowlist and a gateway field that distinguishes URLs from display metadata. +- OpenTelemetry interceptors and span APIs wait for a deployment that can establish naming and propagation conventions; phase one exposes only the structural diagnostic hook. +- A shared gateway status fixture waits until the wire contract owns status values rather than opaque strings. +- TLS transport E2E, responsive screenshot matrices, focus/scroll restoration, and the full supported React/Next version matrix are follow-up coverage. Phase one CI exercises h2c, axe-core, the pinned dependency set, and the declared package export surface. + ## Rejected - **A repository-owned application or container.** Another deployer would have to fork routes, authentication, telemetry, and transport. From d9f78c22d3f7dfc123316707a49152baf472090c Mon Sep 17 00:00:00 2001 From: Preetam Dwivedi Date: Mon, 5 Oct 2026 12:02:48 -0700 Subject: [PATCH 6/8] docs(web): specify queue-first readable request routes ## Summary ### Why? Queue-first URLs make request links easy to construct without coupling the UI to the request identifier format. ### What? Document / as the queue landing page and //request/ as the detail route. Update the pagination and route-test descriptions to match the implementation. --- doc/rfc/web-library.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/rfc/web-library.md b/doc/rfc/web-library.md index bf19ea69e..3cda79bbb 100644 --- a/doc/rfc/web-library.md +++ b/doc/rfc/web-library.md @@ -20,9 +20,9 @@ The host configures the queues it serves and selects each generated client with Components render serializable props and do not fetch. Sessions, gateway clients, and protobuf messages stay on the server. Server helpers call `connection()` before gateway I/O, host routes that call them are dynamically rendered, and neither side caches gateway results. -`WebPaths` selects internal links. Each substituted value is unpadded base64url, so a slash inside an sqid (`/`) remains one path segment after a proxy decodes `%2F`. Phase one renders change URIs and build metadata as text; trusted external-link mapping and typed build URLs are deferred. +`WebPaths` selects queue-scoped internal links. A queue landing page and request list live at `/` and a detail page at `//request/`. The `request` segment leaves room for other queue-scoped resources while the full request ID remains human-readable and opaque to the UI; the host's catch-all route only reassembles its URL path segments before passing it unchanged to the gateway. Phase one renders change URIs and build metadata as text; trusted external-link mapping and typed build URLs are deferred. -`List` requires a queue and a half-open receipt window. A first visit uses a trailing 24-hour window, which the host may override. Both bounds live in the route's search parameters and stay fixed across refresh and paging, because the page token is valid only for that queue and those bounds. Changing or resetting the window drops the token; the reference host links back to an unbounded `/requests` route to establish a fresh trailing window. +`List` requires a queue and a half-open receipt window. A first visit uses a trailing 24-hour window, which the host may override. Both bounds live in the route's search parameters and stay fixed across refresh and paging, because the page token is valid only for that queue and those bounds. Changing or resetting the window drops the token; the reference host links back to the queue's list route to establish a fresh trailing window. A client component starts `router.refresh()` inside a React transition and does not schedule the next refresh until that transition finishes. The wait is the terminal client's poll interval plus jitter, grows across consecutive transport failures, and pauses while the document is hidden or the browser is offline. A request view stops only after the summary is terminal and successfully loaded history contains the same terminal status. A queue list keeps polling for the life of its fixed window. @@ -47,7 +47,7 @@ Generated TypeScript is committed beside the Go stubs. Gateway stubs and the bas ## Acceptance -- Vitest tests cover proto drift, timestamp conversion, stable list bounds, base64url paths, error classification, host-controlled deadlines, structured diagnostics, readiness configuration, and polling controls including transition-aware single-flight, progressive backoff, hidden/offline pause, and history-aware terminal stop. +- Vitest tests cover proto drift, timestamp conversion, stable list bounds, queue-scoped readable paths, error classification, host-controlled deadlines, structured diagnostics, readiness configuration, and polling controls including transition-aware single-flight, progressive backoff, hidden/offline pause, and history-aware terminal stop. - Every protected host layout and route repeats the session check rather than relying only on `proxy.ts`. - A Node-owned Compose check, outside Bazel and in required checks, runs the reference host against the real grpc-go gateway as `e2e-submitqueue-web` ([testing guide](../howto/TESTING.md#container-naming)). It covers the Basic-auth challenge, explicit h2c, newest-first list navigation, a slash-containing sqid, lifecycle/build history, and axe-core checks on list and detail pages. - `pnpm pack` tarballs install into an external TypeScript consumer and typecheck the root, `./server`, and `./testing` export map. The repository's Next 16 reference host production build separately verifies the framework integration. From e84958c73ba4d87b70500423561fab72d6075152 Mon Sep 17 00:00:00 2001 From: Preetam Dwivedi Date: Mon, 5 Oct 2026 13:26:43 -0700 Subject: [PATCH 7/8] docs(web): add UX mockups and readable URL reference ## Summary ### Why? Reviewers need a concise visual reference for the queue, request, and change-submission experience and its library/host boundary. ### What? Add four illustrated UX mocks and readable queue-scoped URL examples. Document queue discovery, pinned versus across-version submissions, and the bounded demo lookup. Keep UX descriptions concise and Next.js integration host-owned. Allow only the four versioned RFC images through the binary-file linter. ## Test Plan Visually checked mockup images and passed git diff --check. Passed the binary-linter unit tests and lint-binary with all four images staged; repository formatting, lint, tidy, and Gazelle checks passed before splitting the commits. --- .../web-library/change-submission-history.jpg | Bin 0 -> 61203 bytes doc/rfc/image/web-library/event-history.jpg | Bin 0 -> 55095 bytes doc/rfc/image/web-library/queue-landing.jpg | Bin 0 -> 73706 bytes doc/rfc/image/web-library/request-summary.jpg | Bin 0 -> 55192 bytes doc/rfc/web-library.md | 67 +++++++++++++++++- tool/linter/binaryfile/main.go | 14 ++-- 6 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 doc/rfc/image/web-library/change-submission-history.jpg create mode 100644 doc/rfc/image/web-library/event-history.jpg create mode 100644 doc/rfc/image/web-library/queue-landing.jpg create mode 100644 doc/rfc/image/web-library/request-summary.jpg diff --git a/doc/rfc/image/web-library/change-submission-history.jpg b/doc/rfc/image/web-library/change-submission-history.jpg new file mode 100644 index 0000000000000000000000000000000000000000..95fa91a90393c63d1a318637452210e87a3521e9 GIT binary patch literal 61203 zcmeFZcU)83)+idgqTr4YI&NarE z*%{t>2l&a%*wh%XYZm~pi}wNSOzr;3)WE>S#@5={)WYa@#%{omwD&9k;O8HLwKci? zv%Q1k&j;T9amNpyt9x+Z5BOgsUcT#tKXL~E`j!6+ng2KPArH@Bcb>op-W7u770#=y z2M-tW`U8*nfxG>I-~WM!hXjW3WFG&(v2a@h9$wAEfAab}-0kmh_dx6q`PV#|^M1ae zKg#-%e$@Dgr#}M5gZ8{j5?}%d;C;LRz5q|a82}961Mmj8@~}&Qv%Jd?U;r@UeM121 z0978;_?@Q3<6Q=5^LS@}zchIq_1`gd9v{M!I{TwNdHM5FKsx}SeEK0ZMOabaX?BPiO_W%Leai})yGR8zNmgzu-SE?`{=LIeZT%rd~$K`=J^XpV$1}7C&mE; z|B%xCohStO_pSeKrhgBKf6tu%hn6_TYZ2&og`3#Z$NLd>`Wq0W*7u&La3dq5Wg9@A z+H8)T^O{?9(hps^OUI?})u&U#PyU3D_q@>;Zv?q+=@u226cu~=O;Jc+2vK-331ATA z%Ty^j-O$48aP!&78(&4XhaPR3(sux>7B1W3uJMmHi|DO8fO}yvJ-Iu8<&^JzqwYI^ z=6d~k%N@XmrL|k*QH2$htbDI?ISh6ESj|(~)hD5LcfCzcr;*V)qS;nT{rbu-ch{?{ z#{wjbXg~EhJg(IlHHTT6EfkScOG)JznPRc~DiNFgu^XHWuI~<@x}{Hze#+_e`i;`h z-&rKe_h?~bS_=Ty)+1?H@KKO9J|u&ygGYtlQ1K)Ver9j!nb<#M72PT zDFWniG!d^(3zC;Of5w6~pT80#aQzwb+4ra&fY;IQ_kCA(0QNh8kJ+Z=6tn$_Uux*I zC@EjM8q3@o8d7JcmXu4=Mji1F-^?fCq~5NsbVZ0p>BWrRyVj#DFpg5LL`hkEyHm$b zGfDzsl<<|ZwHv1d4lS>AA1pW7Uw>iLcU3}3xX(N|nQn>z;!!n|*qMN^b8nOKTJHI8 z*%i>Zbaszl++YT7B7j&De_I$b$hC}Y{1u8Aeibnt9}}n-DBch=wVyf4QKp54*InWG zpH4G#s3f&JzP5~jTgaT?iESgCwc1P&oU;d4m$uTE+ltf z*mF3HmI(&&`aUE8OHS=FZmDCHW+9yQz8Ko*WgR~eG-}-}l~>tZJ$lK#qTOTN1!`nb zDTg@k4{xF(pdhvEmDUEq@ddkRO6B;n(5euGl2#WfjLsIwlv$QeKGUVT{eJS{$2|@E zYwLrm{A$pP6X7Mev{9RCJhlyoF;P?)_ z`BdaVs#|ek_m@4s2h3444M&C3pAkqkE$Sx|&|y5z>GOL-I~i9kFU5&p$&6bkm!j!g zbj;#+Nll@!yT)95cZT+Sj^nc^ybXV?!1lX6iVr>29tIw&S+l*FyjlAg;5JSs(AbMg z3*s9F=7(n^Re@*<224GNJI~juD{aP(a{@9F<(*y~y8m(a<7NWGW~k|FsgF0w&26$f z-mZb-G7gQ9RHUx6NjFN0YoVQc^%vSDJA>W7;zbVa0DivqYYBx7KIrFLUYG-32!|V4 zlXC1DAbMP{NEI!NkuI277YPoxMnU<{^KbQ;t-8auNFR2;;BYq$3><4T>DRN(4P@;X z@Tv7RvIRc9ZA;Ul*b^C-;uvzGmJu}8b!<=`;*=ud{3o;G`_ES-xTBwrGJCLHzTN_awd@Hy6k$!sl z@z>pnRCgyO2^l5(IY=3Hk{X-}5>IMi&KN4>8u*|ZS6`E@M#{rW45}CV$;QvTSvZ~G zN5j8`J)Xb5Uf1pbZnd=M9KRpcd+d;2!=X%By+?lSD?Zr9ip(lxR=~QWPx5(eOM4Ek zR~AHKwT25>lq^3Kx-|0Z{tZX^q6h2BQ$lOWedhZB5t$%6LV06qUn}i8-onpNIZ2?` z;Yb<=(KmdK>n@2+9Q&EQYY;v`NiRbVAT%_J^nIALm_CG|Nq8{aBK+gB&O%-#t$A2j zrC$w!P?q5o1C*XI zO?DVGLQ`pFdCGFr$&YK7@YrF_vwg(_YjT(+PGN$z)n`N$i&IfryyJ$cn7eersOzS7GS&(94d<# z?!&>Si;((Hf2}=$ig=D%+Dxy7pZ3qy5g#6x#S4B`5l^bMC`K~$=3qwjjOMD*MSqyw zxrIrGYSolf(KpjDd}$qO2ap&T%l}w>E6Ty&akE){@iaeOM#rHralYBe(E0HFaFWca z$cr_ZmeX<@cqZ>vHr^nEiH%?7n7`0!wOT>{WY~9eC2oy({J!`tp!=9&(CB~9X z!U?)k%rJOkLX`AP&!)S+OSEUE8yLMdJg!i9%eTUx@6wni}9p6|1q_H5rCmEJbx z9@qg~>*VR+ly3)oW4@lMmj0frxdZ5fhdsIz;{7{GIc~doq3;yPf>5HO{qp^$!u-imq@(`fa%3+3O}8J>?PuU{apD}(UA8Qdr?wQI`?4zI zc!TfJJ#Ms=ZVvmpV?sqSQ2H>QvjYGpkl$=v1UIVO0!Bq$`l4UX-T~B(3#J^GVE%fn zGazm43nY3(=b&d8%fa8OJma<-JUDA;`tA|k*!qz!1gt(un*0kOB9xD36(Jr!6@S&O*FO9smACZGOSKk#7eebQY2X)9FkJmM(_KtseDMc5)(v%!A5V?(4gazY)jvP}4LBQNja3$fV+PFZr=KXE+)Bgpue{wqu81Q{+Y&z1Th* zCg(;f&K8rIL~1dkOjE*FzI_)@?g9!b;a}JhNMM4eZsu==p}9(C-;}eeZJC_6Ulb;j zyYfm$K+uGIwhT$OHpmb$y`p>ZAo0(I`$@A{B6@3sAg|vN`S2GGy-y6Iae0IPd_ab` zLb1E7JEAKXpOlc0__nwvl9IMru_nw^@?(J=j#%Fe?rrBYYtc*k(%WTdgurO4u4wi+ zrl{1TFlWr8^I!Uq2*qi`%y1)RoqlDDMEN2NB=DISF`KvjO$ow>-vrq)zxw7Xo%bKV zBt#|FkYs8il1hIIe5)j=^y=+&LCTG$wSRQGx z0@^)(Dj0bPkCjJm<(KZ0eY32qPZ*&cvt{FH*3T{}>lT!(vl8Y(=r{6#NtHoX(zzQa zf@`ei&uDaWK-LWiCtV{57Dmn*Je?eTaw1&Q04CZM;Vx+n+x;5=c=7Kw?!O4%Q@}nP z>RWR-v}@q04mBmBIX+xT>~w(PKu#(MiX9}Wh}5nC#0%Fuw)%R;ild*KCo3DKc&gNB z2)|zU?n(1TAmz^yQ7iDK6HOgeko3@GA~7R-C0ZFKXN+kwKhFUdKw+Ow3C(Rv1S((Y z^NZ4ps(K|EqC&TPPADoa4K>IoN=#jg3wBIiXA{SgDAU_kXMN)gQ5V0C4PPq=eaYgc zuF($8f~ge6-C$!9&RL*4JW}!5t}8uZI^7XzxF-BZ7z~P<%_*uy7On)R85f{g7+I)h z5{ZGH)H+eIM5!zuuTrPi<7T=_QmP8xMLk`Yag`cNV!=1$gWfE^7?&-2K9Yy1I$GVM zUG_>A2gzPW%c5CR%iw2%&p3r6I*fcu+I0zul3G0`3jz1L4Awk^TkV$qZuy39+P9;gv?yW~&-zROA3Zcb7akC}|fEE(Ax2nn&e`Jr7;xm`&nHj*fB zY*ZKGbNp-P0GZ2ZBTbBMXkG*x7r$C;t*=UeyaE^Ve<;ZVneK6%(JXoha(rp6|M|pwx|`G#bHkR`AeNlBz7$A z0CoVn$-nVk+F>J5{<|1P~lM_b|VpF8P&q`+_d< z;@*wl=>>lX+3eE$onHEfP&(k>H~+iA{yj)=3;&)Nb^lFe@R!E=3;xht|B2e&mF!E6 zox8;EDU0v17`H%JfJ?rpUHl>ZdvYK1AyTSsSwj}X-ULhQsQL$_&5D&hKTFAK6c2pE z5I3q+6`|A&ZSVI<#SQBY3nORsV7o<4cA)4 zzXI#TpTQbz1eQc&28exd9OCAgkncHqi=fM`G_nem&e;*9(oJz_zI6i^eck^gQHgi_P;RFKSTHQ*P+M-=- zKY$Etv~eWK#8!M>DReLLIZ>S9*~2nKs>D-)p!Vh)S)aL1`NI7SuxB>yr}c!v{2Yg> z<3Yp_NMQD4>u!M$zyeY%Jx!csic&t`Y0|Pzg|;;?L%D1vv%Yp)TA45K1vB%?svS)> zk|D}~Z;;UmdE3_y_zK{hNYy4rrgr#a?fh^bbyUuclh~H54i*K&5YM(C5yBsm>4aXx zwnq@y!}hCY=^=IgOq9gyP@7c2#@~LeJJ6z6sao!y`UdL>5>Y6P{V5eN*CnGj^FmHdAR4yB%%&qvzv^NAv8$EweDkn&{GgDyiu5Orx3r&(qIxb zuoBhO(33WL+@5*SGOY1HM}aA53kXtcta!UL&d;HnY4juL6MH=H4%SGsO6G56RC_j= z0wUe-%R*0Y^Vjm3;GH-H@t;PNC~M^K(Cq^nRbk)R{bg@@a=SZ9tTN`iLgj;2)Vw9I zF7xXPkvj9_(gh#ZXH%=yxTIO@`Y@WMiV;#%)J5e$q4iz}zmHd98l>De*@Pw{fSDn0 zL!lr(J`>z%*~URGh#JfHwuh}SNXVmeetydwv7bRiy$@TrfNVKtp*J>8jJP{`MN0X#)}OBE!G^B9t6()!VbM;<>hz+H2Y|9pQGf z1-~PRcY`f++HGSqFfH^MtW@V@ZU+LTsn$hJY)ifT{b-E9Y`tRK_fJ`BFF`{~TabZu zGX-kD24>wbQ9XI1eg}Z~{>7{D(AZT!iuz}^YevR_0i84|U&$qL&%R1+V3(nFF1(oINEGUq&f^kpFk3Don zN{*hx$h8d33r|Iz^tj&k{ubqZY5u@{i%tF(!Q*Qdle$Codu={rhQ>i9Ch)!OpDMwj|j$T>z(H_Cf|C(VEIMw&0yjQ#ywW819iDK2i~N*K0^Q{Ynfh? z&IhbvRpDlblOZZycHI^WJ{D!3=9507r^zz9=6D#-u1$Wi`m>_A52w&;(yf2g@6!tE zQhcAC@k}H`@E&@=5P_xMkfDmyF75yXG_1@mLt8N4_=J_h;UDWX^i{?y?ol97_!0ER z%+brcQ)fTI2S>wnUislB0+Xo4d9L{+u$Wxv$(ZGLgQP|0_f|_EotL$vEQT|^MtlfG z4KSGUVU)#!BeMQx0t<5q>^;yW+J$J$jwlwIxLD|pI%YTOeT*P)pl0~`ro~oSn4q%t zh{)}z{e!#m2U)P_`)Pfd=%l~k{}1*0r;7aNDu4Ej2-zt^*!%_qikgb# zxG&6kSYkgJVT zV@oLKUo#4ShANed3Z>x@rxUxZmI&G~g@`lLC6l*Wmoi?NM~!^(s2*1=xmPt$N*$e3 z>IDg+@Yuvm&$G|l%ecY0G?dF1t9tnOQutv{HM@Z0Wp8O7VQ8w6k)>&CY{?DixA>uI zVV^2i2Dzb*!FkKZWS9|GNqN~{4L%NC)6jRFtVV|&qbUTuA^HDYObMa-s58PJqN)Cp z$yQq`@b5Z!#KbBaQTgBob}4tDXds!Ta(|vVDX22}I_X)a&Os^^RY)oFY_dC@+E-^+ zSdQ^hG4=vK6v62+75qa$pW)30D07&y(gv(j%yBJoD>{>Krt+Cc>?eJ-UYGUtnJ+Ix z8%-*!gU5Xblne8deMARgs%=ygALJyH5rf^_0k}>4dbnmtFSpUut)}0$auW)%UL(pI zj(4OR8CNAuiXbJ=L~eE*Ycw&vS=}1yM>Q|n<8QT9jVpDtcy{h(c6a#ksTvgJdAB87 zg|%9({DKIY8BSZ>(S1-{$*$n^UcyG*s(vJ1!SYMCp1YSIBrG zD8>xLuo33eNvne(?%=ltbG#DRk7a}C*Z!GFYx z{D&>#??bP=HtX-)2}7y4i;RD)zH!G zeY-+mz$`E~opfH$&yaYwz$e-4ji)DZ2y6jVCLDyYoGOlPlQ8kR`!a=dX=L()`!}1% zyQA}^_v;rO_?>w9mqY6jH$}J8rG6*!0c4A0QWIXkawf4b;o;!9FQ=^n)_(pv#Pctt z0|5WrPV?5S9ROW=dp#^>2awNG5+}axU0e}1M=UE$JsVZ<2exo6Je_pqjLX$cWF{|u zVoGmb@U2&xBG#eLAmNEn6hFcMaj#Vi4H1!^v>AwzI-RcR(vlZfIq<4@T<<)5Iq8h+ zF}=kHX72TOWmgk#J9yIU#=Mt78BFn{Z@&Iu&)X>(r&VC)c(u3ZBZO1lNO)J;l{cMf zj?Q}~w;SP0Gk9>i)N*--^RlD00hQ4tz1L8*8f&{HJmT39_2>5T}hLQvmj`L&c!+FGagu4?o&PuuYTIh zuWoT=I!Qy;zJ=f_p70O|)VliXM;1=+>9r=m!QnnXb(?-`+iDi`DXp7|F2D{cMc>)p z;MZE&a6KB#n>6bkJRhDfhx#QGs{y`3mbnRoTh2r7(UO z!x=TYsM5X+J!ZWE!_M6bo4{zT<;oS)Cru^_~xPu=;#NHn- z%oOtv)U-eZ+{WdoProdOGf!1FbgVdE19f<4U^pl_&u*`>H9XcGy(R>`vf&C8RIwvb zfk6GHT{AJUnU7xi<;3TAdNis{#?&@Ya*773AZy3Y1VhnpAjH;#_FK7Yc@p5}C=7 z+On)A?-uF|VzBgHtCe-%HRZ~215BZxawRSYmrYJj%9n3>y#t6RoJjvWJL$h(H~f!s z{L?g`<5X8dB8_0$<_T%xvzqPJ(zB&;m5{#Id1Ef(dU>3$xP?DVxEBU2LFbQILS<#* zHOOx_7`#Cs2quxoe(_c{GNK{*92B@4o9K|$(HfSU50=I-G7E7}C2cRw2p+mGTT7CN zqsQiq81PH&RgTX&`AT$xr>v()WIVzdOd>tA!u8e&OVIrEl;z;1$VFb{Gr4v`QF-Iw{58`@2)WZNUz`GdVb-Wf>WWVYiA;Qz z^xCD}IPmM7%NEJz;l#qF&*j?)h5yuM0s#DFRQU@6_Slbt>ywp@cK1J@+()yuV(C54 zt75iB>8K4s-nPy%3lI^f0wuH{_vCvDdu?CPfMbY(V~F+P{;;&`k(%Oq9jz&HM(;vC zaQ)g@2z(DJ4{?#_ri_}JpxxW!Jj7_5@EXMu!UL_n8r1CZjlWuwM!^~IH|b%w`i+^T zrK9>7W2K4HzQKCk2ZL0X$1+mLajP7gd&k-ZfiRU`yb%)& zmT^B1HB<`TpNy$@4yYJbl(x+n!BEDZ6EGpZDUneJ2mI+A|4?#f?DWBe=btsYqsg%| z-({xWm*v$QfEL-xoIAa=xz1=yj0@Al8#YDl09^S-cNL-6KZ&a+Ct6#u?{>gn`&s&2 zy_V%^&kAMepTi6Cw_Z4}cFlzTQ>PCD+26FU^TMw1oR(Nwefy#{fq9U|JukjXs@l9dW`bY{1 zIk^T>v=$5@sNf?B#YNqF(Ldt&PM{7#>hemLR%^WT4Bw+7FO!<_YTRkZTBfIF(js6aiLzPZJZy;oK=Z_Sggv` z1?RxDCY$-jUlt*_^_+QyYmQ*KXw;042kM@#S^-eE*qG!w(j=SO(DCqUgH@lYc?dB{ z$6=0ySCoy#e^wPuNj-_MAgDZ)l_W930<)~H+l}#?hE-BJtS$MUNCl@+&9r|GHG`x! zq^_JRH=7}`jJkjk8=`Bv*oywqJgMgz9q$(Z*HLr7(yU~KhCjR z5Gc96+*LIy0Z+X+gQVSKW3sI!&aDKGKRRjTGWs@TAj%ceg?qcGS3yJIp`A(u$70%j zU+Zy(t%XWi{ijK-lHuOa5lROM5)#3=}(dYTG@ty<% zlJ(qla#i1~cjBh8h*wtq&83`_ihAd3S z@%CmiL)ZD$I5kkHX}zDGj`rHQSBDqK64nx<0_jmSaG(>0V*IfSgiUb#)%PUhO6w>$ zB_~1v)1_#PQ*f zMxhe@2OG12Al}Bn$Z!XcDqR2g?~XP6kM#Y2kN>Cf*d4WHUBeoWIa)qoH$M)6S5u7* z-+onXwtu81Q?ivS_h+aPzsx;w>iWm?x2Qm& z9u0?8C0J!wVVdXYOzqUCaqGA9>l+-kGkcTuNAjgJO_xh~W)DL{#0on6QBdoJ5Bj=G zqf3qbTp!;Y6ThLgIa$Y)$c|brZZIi-|D0XS=)=vmE}>&_%XBP=!K zxwhc;{MhD)H0GmOAw7*&@1n}lY@>@q8v8Gp5VYBuXQJ|#_0Of_bDB-A6U&Ju4)00S zRJnZb_YTLG3N1!IF|_v63(M#_cp5hh{RmM3-qI83U&^2TsjhR?%*95c&@ zHSHGlt@5*$ugTB+MLx^W&NgsT#;rpDw{9{JXp%;}dEBdWzD=Wk=eT>^kSDv79n@$M z;jeLskc5W_;)OYC! z`q8_81$g}hcd^E~N-pO?KOqNg;7vF;QwxfdWtbYyhdo=4b&t2<0>od@HIl1WD{KeH z6rGN!z2LZ|*3Ek02EJov%R%9i#UKz;RQ`KHf&E4h+CQ-An^vhjPFpllU6nwPZMZ)J zMS`=OmF|16Ut&zmxVZ$U1xP=n(yrO5h?Hg0G6lT{M zJ~DrpgXp7)zh7Q%k{6giMs^5m?T@j1T$J?uxwe9P$WL(D0%W0;p;2O6S>LRy#7ihL zHt2-!aMpFdv%PB5b`M~zI;wb!_XL5ANTi@~J`HjGV+o~+FVFftrpY?q^HAixD={-q zX66@zazPeR!pOq%!S#9=h?Mh`_)784luEs{Wsq+&D!FTa=M^?Md5nU{*H~zw1*1tT z-eXXhHv0X@MY7bX@46By0pybM@)DebgZe;E+hD5_J0XF*v|v%-n3Pa@52yIn@%uIN zXO?b5cD9=4S*y40DXG*JXlE3fwfwG@8I{hxq`<KQ90QEYhc zR}i8T!IY6v0iCbbZkFZs5^wmKN) zyuyO$hF()0is0PM$cGQ@5QwmdsLI;q9l!(eTn~=7VxNu~^UHCzJxAg+7IJ*BVmT75 z^3Y2KJ#&`$N^17?KD&w?fXPL+qW2VI%+29_n%Uh7x9x9j$tD=LDwANCC4ch0eq4aQpq53 z3ZpgQi@|UGIVs4nK^_>265z?CCp5|&9)E=p=&7?mZs7`DQS`R9BJ8E#H|dUSG4ej?djUN zjI&{np_KlmI3>A|H4u%3P|3(gob+ISbeXJEJ!m5wP#G|5=Bng7p6g~_;BfD zT7RD&cl`2KAhgS0f*7IQmOv`a$=v_q@Rj+|D)q9WnwL^W9?|iMt7qHVf#t^9qB)g` zUmt{xfn9aKh*XToRChS=1{wl^XeiI|UX{%&I{Q#`u%>>Ux!E;v?3e%Eg7H6b_aRx2 zl#yi7*{D>c=(f-%DL_D<63ILM1%E3Us4g;y)P1jH(g#xzWg`-?{@h282Dc{23{B$SrBG; zQ}Hk7#$S*}`p3gtyFq*mV-P&&#rj1`-jH%$KC{v^vLyMBe^HI3Uk2H~^^AKxV-<5fe+wICh zookD}DLzs!>jIZ#NAZ&rFSR5j!mx?>%%qI6cDXKf9DE?l%^U7?2q(r1%LiW_^!1do zux(;5-Vy3olkYrYt11C*8Sp_fFeDZ6u}P@Nq4YBa>|@+cS&h5jFlq;k@qUEhO_;6I z)TCN!I2p=JMs(kba1|K!Twc>8fy#2?s?(Rz2H&~v?PJ)PC4DH`etp(J=*=t?Ool2D&S`q*?zEmG{4 z-8}QrA1O4~8UYdRbRuzF2n0UUqU2$tzS#&>vklaUor z$>d;!h}g!*J@#P(WkV=QRTCF$A!;hdt~mK4gzI}W{D3xb#n4%jAvwkVYMV_1g=M?N z6L4m1%VUKp+4l{@G9iK^*n-rc)``~J69~u0#QcfVq^(}+PW93sqie2fdSu|UCtYe>I~RUE4ByQ@(xn5y3Zq2$lL5IDJkM0plI@BN)%EX zohuU_EDrcvlkgg5PiGhkgYk+cnfkAR+7?U(#t1q1GCy5tQXPA?qH)>KUu|jThST(QHj(}TBkW~oqD=DIN_BN6SGf)FFNZ0!_1FC7V0BdEzkxM=wd0%=l}h;3}VQEtjL z)hH%p_xBC5H<0Qf%JF&lgX^6QNLi$_ps1bhc`f&N(?P$e`T2YrT=kLz$PN0YodkW_ zLh78-^Xz{~Vp)J`T2w8unAIZP=~Bm>g>Oj=C&4tTNlnyoF2bRN-U> zLP}{mX(q_i@Bzh;c4b{@23un#$--2iihw}%$+KCf3PuZ``^nuDqJ^s4%o9E9#Pj;+ z+^4P)kF(%*w9qpGTaz%!pO%!?3B}24W{Zv&4oAs`-n?IG%~eX3EPZXa8R=L`BA3MC zQ`{*PJ?6%(1BGf(dSY}n6Cyc>;YGH?SU180we5V1^w4QKn1wZurDR%A!EiFEcdYzX z1h`~he~IFY$e(Tvz$0kjHtw#y&t&2*fB7}aTVrkro?+z_4NT!{khNOgq9`kl9dnlQ0Od`0iBhFN1 zysjEinAg0gH08B%()sIga%O#sCb)d-_6XqM<3A@4zdWX+*)o6eW(lK=zbNg=)q=4K zx8M`OIYb!}rlb0d5Z3*a2e%XhMT2cqndw!q<|3E4TWb|6QMK+-_?5yAGzcN zwU~Vc^G$pI-se-9aiPx>EqO$ER=2>)M0_YDRtK}u%^w=+kvx8dPa4QfID)!mn%?lJf+XgM(L^2*nq< zFaFjoI-Mo;YOks?b*n4t?4YoAn+jTBc^?byHU99bz?<*HBlKvzbAneL{~h|`&h*1OeN)A_tV!TFT(iu;5uuADtg3;_1(|RrdQyCLotAPQRf7fNl0g-n7#RpD ziHg+EaRo-bU|%XUzs1Jfi`$ozmNaB~!%@@DPN!%kLs-W23FR8z$jK~;fmnw%fFh)v zgh#mi>x5Br4_-joK&Jr=YD3FyrE6c!I}wa3f+9d8O&=y(*KJmx-k5FU#(m--tAf!S z4h|@>@<<^OYJRp$4j!;%L_Sezc?kO}?`Z(FO{}>wY~z-qY=^(KN-SN9V_I zLTuEC10Q=?g%tzV$29NsUU~lN^TZQDtrc{(x`ZnVc6IpM+)InJw?1hZVFcYH{>xsT z&!Rpb3!iJa`1aEKTu?R2z<(rHDzr&Qtc(Ww9*5;UgeG1fxsr?zAz|R_LFoaFW1gD6 z^h!Hh#3fS?N3)J+>k0O2_~R_!G)N^Q_`WT8K8G=^P0UZ;j}jBK z|B7FJa5&SoLItS0J%CuT(X%-oY)VHC2dIszRMX$*OEf?j-6casOBwr8owLz|4_1;v z%~~6eGzvcQMJXeuvR#W!UWF9VZB1pJDMlH2mE`xvGYCPIcLP@Md56;@wa!m<*U(tL z#Yxu{UG&!yD1FvKwrYw6H_cYlG#UjkADRereD@|^_?b)ztviyN)m~Yo#B~yZ2DdAC+X_*a$73hS4>>DVfXLeOEsef(g67~rA9Q5G zfPeAZ`JgtA#L1*Ny2cf%5!}#3k71z#6%kdFqH8jdEH;KnsdC8;i67rvvFNFrb|suW z#zJ7dG5U)6;KXLN0|k35=-ivt<`G3~`YS0!rF|Bs^hAcSSv!h|GnUcrbQUnO(rS$n zOn!w~SVqv3_)@Ym5?_$6IRnR zMpSs0fvJx>-Ok5oW0lwuyb;dY%sIu5SgFwdk20i3Reg|Zbrub&8z&iTDO71B3GcRB zu&ZJRXO3(Tf?PfvAnv(5l1C>$L)f3lNE6MVu`1wT$b8OYJA#g$y^~5;L~&rP4!LB? z2%+y)=yTnhjG>0}Y0c&+dL(HP^C<%quj;uoRV#*5jqi@y?r(US`86!XYZL|DeaU8| zFxJpbTXe=9UpGPohA?=M#o1H7KmScn|0}TIyWj1yjsF|(j%Um5>daXr(kM1gzJTb~ zDhooW-D`&>ooN8+rg!c$F7X{Md~mlq@{Cqw%x-o!D-bv_Jg!ak64^6*oQ z?`JG4)YU0Z*Lj9yk18Fbc;kkgLJwYimA2ZLlGB}K-g^f~x3hFtpN;RhlyDcq!7c5H zH^%OX^M*F0`0Gm4huYSCk<)ioK9`nn=|3TcnD6W28YS&Vc`fy;HWcrdDS&=;n}op{ ziaE|;|BL)`6L-^n^K&8(cP_+6DEF}Y%)ASXLV$B(MsCGLtgjX6tw(~oSl8&bBNX+F z(VJ0qX7;&4mR$((L>#zbaWnguzcu`>#PA}sMTDO$A>Jcj zGsK$SBS!-se*?eBJ2)$&6hQ)eDfhRozw>>;kA2{wyjmTlZPpHU0VR^ye*T!Ugr{}V z%Tec}Gt0xYrnjX09(`DjA3^zKXQG-7?W$AL;r(x#llJQ+HDhE{K~P`>FY>`vYg&8! zqPSi6EveC^avCI4x4~16%q}P-$D@t0-0Hn(_m7T#hF{T>|+G{);;MaQe7(u1HW6}a*~R#>ByV6j=p=1aPdX} zkq5~ye;WTqoL1wm$Q=@$Evy?KF%ar5#j)`R)45T2L{u&Xl?k3lDg`gAj#T=X!Yb24 z{DZl|iC(10H>=1xBllc!S0FHk6}eea#Q%C1*|H*iO(bCvL(Rk_T_^QD*Ev+|Gl}z9 z#)4}cWxz8MWHW5*9)Vv!e2Pt~i?v_Q^s*gY7Sw&2r^4i~KV_;%nF+#$p zhbyY2k{ApJ-YZV&^X{29)F1YZ&%-ao$D*VIc=0uRbI3O{HOE89xh0Vc(M>gPR51ZtWS@}-0}B`@I{@M`(HF*W+tPmZlfbyJis&PgZ;9}JmW4}l_#rDvXZe+_f zJ)c(Z3pklihX>;W6Ym%kAjCV%7@4Tet{&brR?khD?0jD5m_g}U;ooOui@Xr4nDg7o zZ@mkvMwt4055Qv_CTUs=rcvOoI1yS}R$Mne|CpFZgQ$nl4z?Ais&da%Q5b#M#tdLk z>s!B{`GYo3T>R#6)qzxP8sayOkQ`gdmGv;*cIn6{5!mudY?`acSiCbN_CCK7oWsn* z^j$ABuFJR2y6;|q4t)0zioJ*5P~p$o)$cpo{nFj6hF(miS5_Kk5U7-SjvO2VIadTM zO-Q_BXm~lwv?}oJf&wWQh4L>i82pU|ZJiSA0O4NymkDv z@M=<2T(p#@Tpx*wqvu?!^E*Z&EFx*0ScdMWygARKlWY4R`_$FLl_+{n5cpc)kjAys z+z=*N2FxH0L4wD4&fBPd`S$=8cpaQizzw&IuK`&X$HZU8QfeE&b_u7cCM)C(=bL$$iAXUncb11<`y)MkgsRlLwi$^5nXmoP0 zA_{@Dqad~WSsl+(mk~@-d3YlO2-Hpesq1gb_FsYt1nvMx{R+)L);&X;|HK``E9I{k ztG^&1eF^E>-fUC4=b#wR+spg1J$pN6-@lRn&y67SlWH(A0;|G1@$k=u@c&Et{$HQT zKUw*~uti_)sDz2B@=XXn6q2^AczyoK+fLoD5Qf#tr~PmEtzGF06SRJ`;?=@h6cx@l zKzversV+wy>q)*(0;`DdB0nTyx~NQZ#MpzMqj~#83F!Wjr99AjTE63TOopMaEm$eH zXxVK}TE+4X-~h5pQ@n#h&>`bVQI_WU>y*>oK4SwWV40a`S_H4{i(G&X01#h(>1QF~UX?n|@t!G8{M3HTM25fs;p|8s zb^rk1iwhK_IJ={0Fo(p_lhQkR-ve|e3e7IGn?Vm)DaK8%ZK%a>0MT}* z-DBeyan60iwxRx7*O5xl;BDwd-XH1$lJyL{LfQt+#s}_+m!*=S9e2<*dYsk?$I|dtDI`CuvMj`}WJQr^L@%^WOOLZ|RryfK~Ijvmh(w&^1d#Oqo>Aggh zA!DvdNwfyeJPSB_%W9m2!+^uV9s&|2Uq0Q?d_1n-`k=jmPxLpmcS#*$bUKoPI33ik z6hZ}7V)|Qo!K?c={yuXdRT5dYI456QOl<|S8iu7&+R4i{i=k@uX^PZXK zobUZT&-eW^`w#B0_S!ppt-aRDTI;^9>t=i^KTjNbI&svH4=m9>xbe3V-U<3FaN1h# z&DnG@x7vo$M91OL;|1t~8@cvO!!NoYX?y?i83e5V_XU41LvC{#jjdYbEu9g!mvOwf zR3~P>Sp}WCoyo6eH;{hoqny7#%Z0xcgwG!M$8S{#_a@JE0U&i+s#BQ%H95k9J`>ND zu9l+T=(IT`Eo z!w=f0#0(LMgInB69U7tUD#We504!!dSwJ%Khu81`|i)8p5H^EJ=tkx9>LFZdAqD;j?r;hK?0>^I-MV)lB`T~jI+ z_SXn?%)^_N(huCTI@qzKERtAz>(ts8>S7-TF`~bnnT=k4UQID6immgj&zS?-*`Eat zy}y2LxRSYFxx)0LzGnaP{htMk|*ewn!ZIsziG%u*=4jiNm{r5+!cn0b`DL zI-y29Uh1XeS}XMw|Q!X58U_u5J27E*|PzF5hNw2S9uHI8e~SuL`wn|0LdU@>R1{a6(v&`;8i zILbOiWpqMCqutvN8)S1uJZQs4PKpZcO6@%v>9M1A=vH63@9pEea-*^^_FBEnmS%tN zTc`&vi;+anXr{k#JoQ=NJNEF}d@^TVvbnO)x2Pmh4D3dAne)|qIB)Sneaw&I)@FW3 zQE|da#!Gm`MlPS_tOBL4xxp^Y82!qZ0wr_FPn$E%hArOZN4@@Wq&|Q?%$>uizO|5l zYjDww*kXC*t+Hh$yc}r1mB%UZ$lyDb6SDKnN>61g#I+)$0luQB9k!|;wJdJ#lUJBW z#W0e^LNmpMfB;5;kT8L-2EDwh`le+0{($n+!C>#T?2OE8J6^VETVT8Prr?Y0TvvAB zC#8Xc4RNbllCU_$qJ$`q7i5TMO)GnsM!`P|46RC0*?^DVbIFwVdPQ{QH!OnQ^xQ=qyl8Gkzpe{PHsg$)DE3M<${x zSmS~@FI;wyCgO&|q-p@ijAoZ3n-_jT zUCbC>x%cx}rzDm^D~^6@cpPSFtRl8hQc>F7YS}f&=j{u|L@C2ddv2zgDMk2g;nw%| zq8=ygRur0M*I6#k8!Zo!HL}gK@O^;%zKfdc_@85w*qcE_BZ#m{z&vm}7~s+{#)*#D zt&N8^gS!2?eW1e|kpLwpB)?0EC-&GosZ>WuY~9xo;JRoxuVtsvcAY>4sEw{`OC>h+ z9Z0utlyl*xwDawuu!9FYX}JtOML9GB1}(%Z*~TnuQiYYKtADb&m^R4gb3~Vy7uX}C zs`@0Y$ftgIYF7Pxc}l9%cv08>@dmJAwZEsdBIx&ZH~Z~40NXIRa$xM^`;g{1us(N9 zI;BxC!zt|L>~!s@NWuxqh+{2McJKL)G+wsvS~jY-BHie>IQ_Bd+kyK_u;r7doHAe<%zvv>bCw zldpFq(8pXHpk~#d1)!6cZwUr4A0&-<<=3GZV4tpl>{rblXTUm$1IZT{VuTV5*d)UM zZU~Z;S!5{e!M(fvwpWq5+s$1^XA50oQ4oT5H z`RD+Vliu?S?U>3z7$+K%#wp_~+5L=5TO!I1PSck`Z@DfZDWL+P2@zGEU@d3`@=%2R zh?pd~ZanAh1AL|)AM`1UnH{$i>oMJQ@=ng&eC}`@v6g?0J6>os_8dO}5@v`No0;kH_3|Bh=ACWdr~5c2UT#2iX=w+6oTMfZGw)Hk<~2*Qn%{Z!UE*}5P1yUc z9&AJd6`#I^hWivHlo;9q72QR)yvw6ZJLpQ*`M8{oQzE+%X_Z)S;)s$@cO61Y8v&Zs z`tFH54tAh5sn^O5xH>FwTBmIHvaz-KTP#ea&r)Pavp1iHMBir#G7q;*lLHc_A**#C z>H>3gbkY0ndX8bM^ADjTt{@RH|g&;)l%#$231& zevo?yySn0|WuCwqSanr*gn_86_$cSfD$??oJH!qSYv#> zzeDqLP4({dfU~B8!Xsd3AIXjghp+Yv}W7oH{qthWe z+PArQ#T9|WVqihE1E?V~@@#qIXonKf3)2fS;`?wau_8TSe=ObD3GwBkK z{s4scrPyB;ZN6H8Zw8*?eoZ5fgAE?ASbXYKVnQm@nJ%rl0t_vDF!?U%DEY1z6F`vh z@uV9ASM;*QZJ3>hlGXw5dqs?QNl@5+EOvP6inKJVB%g{OFY$KIC`Lkr!9|4nj{QHY zIozOl%icaZKhEsr)8(eUYWBIzp$&*H9*N{&Jd%hiNfx_GJ1B~tg z4weDS&x)#X+NY3H4=5F=1!j1Bwsfq#2?Y=IIoF8OgfGHWtn{0YPKv5cD<=2gOkce*Ss9vWK)<))dw=J*634(KF)RETRAb$q5L;Qeyl zt&}Yy!YgmFgrVNqiFoUs&S@dl+4JDfX}?*8>-C#Y;3z%*Rn`vs+A=C0nk>yFo1%uC z^GMpPP^npkhBuF*Le942tojyGqbZbzWbjSWaYZK$)EEd~L1&%(bl6*eJ9+l!$c;r= z<#V*G-Z|g<-ezurM5UcQ?ET7yZP6L>C^Fa6CYu>F(TSQG*L%e%s}u6C?z^d2qE)Rp zlY=LT_*)Q`=EB#F>V;47C!Zkg!Vt|p7bUTV8&UBkSbYa&LqNhR8HIzZot{#hTq`N> zQfZd2TbN)AnwlTp3VOmDDm^2qx9DEwF=MgoG_Srt^n50+>QYr{WkVA0CVWz+2RW}d zXchRV=TF|;(a6^o{SzvUgZ$BZ1TK3S6JVo8G-{`zKP^(|^Lj}lT?ONZ07J=rX2`*I z$w27P^0}CH)B6EZEa3L_?>rCN`NGwZ#)isR4J8?ivhU1>k~()U=)fYU6w<;7p_pa9 zuC8-~8LoQ@Yp{?p^9jxuQXfK+b>jknE~urTmYlf;B9~|a?J<@sl$sTFJd~vxb`skb z%iGAsx~UJdIceFlzAuGyvK9s0_7tRhDR<&2?7=>erKLf#!CW+=Hef-`zUYl1Hv}yC zL?Af6e()0hu}LQz^|AplXek#nU3)p(6!G?X&=%hNh`xRqZfs-l$_*cLYZ;5Uqe1aQ z!#9#ZCr|a&-o5$rcoTCN>*^1e)zr!?09<~?8oan7F0q1R`6qVuLsU*4F$C--r^+}v zi++X7yjz@`qseNcZP43(0m+Ad|C8GN-^oEcU28ZF-OLEe8y*IvrzAu=rcibXRzM&* zCN_0vw*!X7(lK#vn#mk8{aO1Z1+b8G633y?oXltf0%H3P#Xr09^bRxaBPNzas1m!N zn?Qdbt>w<37;Fw@%yh+W4~ADxc`mOgFwQ2Wv^08$#L`Z+fN43RfPtg=qoa>SRqN2A zD~N_!qY*$#H~R#R(j7NhJiG3(t?|o$_2gd}U|;Q*ykDihzghvYoDrXo4l8_>?PNg$ z-Q;W}tqeYBk<@TOU%G#nu0qw9-~VZc@ii}UU(sL-0RmL)6LT})})fflRP+JNa&wa*Q`L+K&%wZqL6@b%E# zTc)QS0?Mc7skN{t$= z*d=Gb!7yJ${G1&C)lX2UhVSGq^TmKG$#jx7!sT&OiGJi1M%Eb>>*DW!XG|3ba@TOa|yEbn8H z@JfehRO!?)-@Z3wy}M{n_c~rL*v>tYFa@~rcWgp2UesdK2jL~Y;v9?)m(N_Ze=*at z|44IF1rqJ^djoeRq}>HuU-bT7`c1I880-AT!D#yY&D-(spD3HW2G^6T?dM7|DixSR zuW_P?SeaNGI00)Nw(Ov7#1hiu3D-`#b(IAlE~e$=OdL90d&SyLd?NQ`Ir|i?vpv$o z>F6h=me{2qZ7yz4m5+#-;@l}{yc&dUCEQhmB$8NSuoX+73Brj|Ea;84Y<-HeYoo|W9qa^>bgtU@?Y8)s}D`gtqr|G zT1tZpqJh`}hUNEY)Ggqnop}&7}ksI5>u92kM~Xr;M9{abT7l+yrCcSZ?3G>J6kGW z^%NzUSNO0@gEf#IT>)#0wPN)-p9MzWoZY{EP2k5r=w#pIVST$MRnewUm?;2UJ@cj@ z5*#DnpHW398sUdJn1NjmbgK3tadUrP=(ib_ue@qhQL!b`IX2mfqt?8FtQG_ijn#lj zZ3^p{-9DO_1OhdVUiWq{Z4Gn-TtVlm%{7FsdyBU1I`j_l_)lx0QW7Fe(MNF8j zNTT{!LN*6FwQW~EN-4k=fTd|n*HXUD8%!c*&VY}$s|L7kpr>jbV|v z^7#v%obr-d-TJAwP09P$rHwf@(?u$o#-qwgPDiHVZCzd0oDJT@O2fl+pf}bi^BNso z=EGrQ_c1|Hu@nw}#Z+D+5fjt#JP???kps@sdz{wa5hQHC^3uZ$2;}ZjzScu!!_7cbuV(>2_snFffW}7zlP>LsG^v zsmGSrYwwMqTnDrlwL2RlhZ2>_eR$jG3f1a~39H8ij7R_jE881%Z!ou%THx2H%3Vxv z1QSNWs|LrY(QP|jpzQ6M2WBzk;*@ib37m&a0JGy3x^p^ppEP#`=l)t!Hd|2{v$C}Q zrlO34Y=WpWPOA76-xe8ch4$0uwtn2dt|9PWXq5foQsFD^_Nx`p*5AO)NaGuW`13@b z)z1evot~L4Oy`At7Wmd$YfC{OXY1469PG-4k{2?s{cL{u>-=B!^H=-$tAG4|Ha=9@-BtS^kM#d{se4FbJS1339t7>wxrWjrdTs(?-x<8wdRuv_i6Pf63K*Z5Qs?Hi~B# z(1;4;^vUS=MwMi-ah+w19qZt1kj(`!nLO7_g(U`LhfBVm-PB!GaXD=j!V1xF=_?6r zbtprSxregb&{J;GXRFlHO4p71hO%kihWOLudfbv@3Ydx|P}jQ<{v)nVV@v*2B3v!FAoeHyZeK6ai7sKdjgPNR)?Z zcrDLoEYU|tOWO*-!QVrc2t#(kHyo6v zhkQ>~4_DsWa&V3F{(+I^?M;&@K$+=fy_$47ZpMLjEYvtj>30+jL%2oE_QNkGJuBrp zukM43{62iu@>*-cb+@2p2}{5jY%moXN08bT!~doybe;GVZBkKgGCpGTK9)*PGo1_a zzBknnNLpe#D#JsL;RFUh3w+3fmo?oWEWO7ZDh@d@{+ynCa_})P+%i4?QV zNbr!wuCbkAX!Y=?{eEjB8~sp`0h=L&we&(Z6r)+VBeu5DXP*ci3E(CSt)i|UOLMjw*JnO7Dg{WVh6IPO>-s}DAJ@**TsrAJ1E1^ zaXO>b1v5~VoJ<$=y5MiIW$Y(0XV6vFFmHcdugnL3r3@GMF<91(3of7+xMUoz*eV~a zNx(tmT=4i8IR=~J;_h`^ZO8#GrZ!_k%}(}^3rfOa1f-^-?R)Wr7b@Xd)Yti!=zWvn>!#SEnW>ONlF9& z-AmB!4~e#h>=m-6=5X2?gaCh%Jgoj>*dF!gW6(fNkdl6c+Ia~XS z*opQjRrPg4e()UDl>M0-t{@WNn@oPTP}3#sa!32_RTLxZf&%ZuSZ9~(X8Ixh6>VSj zspYB90@git0l~|!bme%>r7KApK#MSHF=UMnb|EM(ZTI|MhE{1D@?1X6O${PC>)t#g zVYbyZtUWpJ0vfYlHt1}Nb2%4OifkXF(#)0+6`co zy&lJ&b$v;5+i@;9%#0frvrNsM)-vUB>^njBPdne0w@Oal)8FH|F`~lUpiS@8%gec@<7BZkAtXNe1YhqHNCfy1VS!{7K7u?HWG z$W?pF)A0AUyfuEaRA~2lmI0r6{3bhZtk$vL*lL2Qm-9YE=^0tk>2RqIOpwXPbY@t6 zP!&F%>Ea`@EtaW?TblBv1$64k;B%IpS|$P~>GL6bw@Cqfu(N<>b|ZCMSNV5VbRGub zVd(T@sr6yCc4+RFP$^nU%Bu~KAjD)e^Or%{B`^0AD7Rbi>_)bsvc*tD#^6xLsJL`i z3@#0VtChM2~00Sl<8((R1(uk zNMZ*08CuMP*5QuxvrXrHcg96k5MdnM&VuMPPhMGr&IMm1{71fUkV0dnrE|%P_Y;zo zhP2-DK^`Lid>0Z5JNGL8NRmV;do!ShR%jz7MR5!8*{KC2Ukw62HIJ8z=ytVfS{(}* zzjJIT?32i`Gqk8wylQ2wX_*MKY&5@0iyW(H$1#g?u61yRoR3|rJraUXs@Z5NEo=2D zTVF5ZmB*V2nrG*f@HLCxgP_DH>CC&I1rB~}r#5W$g*_Yh$vo*&R_1=K3I4E0aIgVP zSYDB~9r?(S!IQH`pJh)TJ;A*D5VgFTo0m^wGVhde7kOqo`Py)k(H$N8HY)M}&*Gbc zQRO%Oj=t#$u@4BuKA*}ytbYO-?08G#eHO@YPUuA#XO+wwY{GX^LmD(gh8h;>QVBo;wlsjD0wqj~=Y*c1vpy zsI-CMKrz^Fe(fc_FIyCq~dXtVfj^O6{;#8Nmf03 zksO_z;@bGVXJG_AtqZdTck-2EhK}4tB7%u5|HxW%>&aTmr`6S$s@rZtjD^h zfZ>BG=_X3j!Md0AlL!yD!@@%_ZEQ#1z>lN)j;*B#aZsR=@=&s@!Hwc;988A0iD-3~ zi*XG!rrPRAyL44iC3MKaa|3pjUP;uEinKH%i_2wu#m@xh)-Sh6=s$D+$ARTP|JTak z589WT1}6PdwZ^NiI7u}TLWc4aE!28E77d)j_}c+Gs_*pZjax#uT^JnHl5c5qSAu5n zk!VDZn7&5A@??>Ry55S;;-Vh`b5m?g z1$4pmIkM~^-6f&e1prFRRqS811l;4koN2$LpIdMLz!jeA4;?Ctteh--+vu;Aq;4Tu8`YT{9n;z)C zi|RHtr}jt+2U$ylx&!8W!t#ZaA|6*X!a9a4heY^R8K?k|3{bN*&{kmrQ}8HK`YlF9pZ1 zERw1iZ%(ez!@S(c;z2`0o6|VYF?Ic79jv+9T1mEO6uPK_t z(52IBG+M27qsuC1oXR_P+2H|KgL25YuD#HDiQn}*+LsMo(k0X0@hg7&3{^r2!!*K{V;i{c9CoM5p3^MdQe%xdJ?t4r%n62DK$Q?tvOMEs0pjs>W_ zhuY4!AFeu3w6R73|KJ#ZOrP2~1*(AbRhJo*km>s#OsVPV8g<$e;@*)^r4&5`Y<$CN zpIvzM817alzRunOX$m{uz&vq6O|&HHjMxP;saY7%$m#raKFaSwQ>iS*uBee-f5x#C zGDwFALFjH!A^ncJ%g=iGx-|duhhR+oQrssiy~^+-uXF^oH^yFE=p>^9wOD=-(cD-b;M8@u9KmMvs?b_TlrK91uSQdRwcr zmvhxC25c%`PHocmo4Zg<)zF9`8hX`S+0}Nc_bqC%Tyivkdab2+tk%u4EvH`bdUU1Y zgl?Y*)_V?aXu~It9=VZ6x!N>w-#jzhoMdCcAEyq7h3N2+ub&ps z&thMy}y11H1bbrby(RX{R8mw(qD0Spa|A%Ic+&^csnhm$PBn#HmQ3B(z3%(9@b)o3!R zLw;UfUS2(goe(3SvAvsDZQm<{P7-twH&YxlU;#1h4ceJ^rJ+n-y1c}%Yp^bf?>jX& zeQp@>@YD0n5FvFsqhoowlHLO=d%7j5kLvV5=o(~8-2#NTycRVYQt>wnw}|$PwN}C| z(zOnaO)YK3pz8won}vM+7scg}!+@*Lz&wA+aKraJjd@a#j*`q~Ro^fmY3zwW>{tY za>&nY9B)j4v0ee3JdjMEEi7w$95`%%3o0p#i)NkVi@{1RR8_I9%Ey-~13IxKR0`93 zmP~)@o0gl(r!LosjgD?^=z$Zs*VS2$Ybuw<;5JXjw=d;Pc-J9lPCT+hY;~H?zJNCE^sHlC} z@lXNsJEi@+v68K0kv#Z2S068R>1W9@$q;*)B*u8mwnsE|{&HaVwr&@y7PunmAj`WU z+r%DXpVv=?pCj29RrDb!I*!#=M?=2Td$l8RZg{m^NuK_IIE$l{udN$$$YK+LO9&5@ z&5&d4yC!RVmi?sse7i(y*vIGdmY!9eX!}L=90*1S#RIys608pH(ofx8e7X$U;M1-k zl|277kcg%=K@e>*bU4{Hd!lE^ikp|j38?=dgp3A7$iL`K1BWqo*Aed-!34YKD6=r~ z&9e?(VlpgmK0t& zDz)~f6~XZd*X^wb*+c%En~IZT7ZSqShLB1~6+?aq9EvN?4>ytXgtJ?r=*BV+;%N=b zay%=n?JO;o?t_cX+llNJBq2|Ycs2|)h}FVPxMHXAt%ufoGg8-cPEAPL@8}30D5|@W zRU%^uJd4II>>6Um=#14#K4|t$7eLQ|t||#}Qj8^3V70`P`it3EWo6|>*Uc@2GO2{> z$h)dhmFgR9_L$(VztUkJv&N2@>lJdCYTv)ie%Ov16&t?d%b-V7ND|`;JTGeC`M6w& zob4K(Box^4%c)AeR-o6;jvo?zyg$Lvc=()P;>VN_rIE|?-*?wdKBz#gc&{WQukL~9 zl&U%I1Q@aPc*p~H@A-UmYiJ6up2nW&>Zx-7p-Kv92dp*mD{N9xk5JcLet@>6MfrWm z3k2G7$ZqoZIW}o6kIo7gVoX??i*=r3YRTFQHrJD&0_<_=6c9YUN+Ic0pEg)F7VrUs4=IlZ%3 z(NnrO0d)v2u6yEGw3#lbk{tL!^`;(f5yVN;36nEI}}I@4PQ2G552EFTVsKoLF> z`ei+M%DAAsObC~rX7+o7+~b9MhIG0?(c%(98t{+F?jT&**k8lmz3w~a-ZYWREJ_Ca zO3eiuuL4Uwen1Oq%F5t*jZ=W)1Tes}yzwAM@ZDMJua4z|T3R(=^+^bbo8e2EZE2hi zx=etxLA65YeGbVMoUg(0zSq*#q>YNK(u@ ziD9b!2QWn%b&pHm?bqXdzphk*doM<#(J?~o?*};SmwABw?`(h8v#ih;?KkH?3lQ{l z*ul!g93UCBmTggvl8^&;Q<@{k+Q5t>AS&qu*ESZkO5n@erhzrfIHwwy)(e9LdrW z@P1hBxbY#p6k9Jj-VmKVyh}QyqQ*goZ{1)QGrXY^9RGO)>%N!J5)VGxJy;nrhz&}o z$F=TTAifKHkV7QvW(K`z^82;N-Y8iohKEl-8d$#)6Wc_~suf}HOr$-wY3RH0AR?+H z?b&;Bh(Vi4>PD1w!pglA@D>i8I&i=GH04i*C%#as7!7G7Uwi8O@v?o@x=}Kp1?pu? z)yvI3@kN2`cS0x`Jf{`;x4K%*L*rxekH^!ZihGwsLZ@|ZU&gU6r>6@`MmUz7aDTm4 zG=3=jTt z9CJ6HOk^k>8;q6I?fN#~hp0cflvH)mzSU_gh<=ldg(x@MZ5(g)$;sF{!5y|12?~US zFbc0aNKe)-hRk%tPFMHU=Im5&y?!=ZLj73&>DDL5TvLaA_FLzhS<^5ETH2mx30}xc zY21dZCtj$ZU>(;gw>Z9yL=0ZaWfg>X%9vUtIIXi$Wsoz4{5^}EnQODwzEdsUpUO?0 z{43aOz3NOu=@1)TqvG4+LyHh0P7-~7JL2sb{SRkmUuy)GjO{KjAy!7cmu46R0i07X zm;^1VX`(csjlZQLmebq>(drn_r4el1T@?~tX?NK-RX4CVJ_}HvzPM|pHQV}u7?@L~ z@oG*$>-8^x@`}C^M!woF+5So9SwPZl;k9HL%2wPGinN2XOuUx+Iavu7HCz@PBju(} zr%nHY`+0c@M|=u3)#Rz)whlU8ENqBcc)T>7z>AuV+K$MF1BO;|=#A~srBe>F%?TCO z_FB1v5b2P&IRE-b?sxXnH?jFs+qDT2;zNe++qf!}Y5)~Uv>V@b^tep%CsH z?|}MA_@O-qtGvCb)Tk;!NLoRx%wf|^I-(?yoUxsN$8v zE^F@alb>|Cb~chz7OGDdgQ*4%3wm!}x33wA*H?yu<)UYdWi&qvteSL^nTZQ<$1|_? zd+OfYCifgpTVQfYJtg?OLcAP?&5fbg1;+cgzk^%f>|KwbRE*fbCS{4)q{B(e7fZZF zd&KyvSi4))y^=-ePpn#vXNbM~0jr@nVZ%P8q3H#{do@z6PVwSZFA2I>R}6c)RzZB> zEG&LXQg2KHV8IQ6*({gn%UlZn(Z)A1UD_V3&R2vU=d2^TLHW;CuXl-^FS2w~(bB3ng#i3V-tA|IOsR zN=3`7%R8Xo%RGb2ERR`GsX7vTAKzWb$xnxV`FHNI7b6|W1J#B8OkA+O`|grGYk0zO z^L=(RG4W=$B*neGM6?$I_Bds&0X~?QbHaRYe40E(haWt=C*X_pTc>!R+#*%$%cbHO zm(I-X>T`()pC0C^sUv*1Aid8s+r2z8Qx2dgRI%V#c~VkwiOK9x_0T+DAn@Z`)!*Ni zY-9d*ov-WL+bQQCQ)-|{o#RBRBFWixDIOPb*TcNAc_#es<4--uPwCv2gTam%%-xd* zS*Z7Es&U)R1t}(v9nS$4)Z4SMP-*?(dVzP+6XFu@BobVpKySc|kPdAN1X9nsR{Upm z@wH!lwO^|2pZeGS`dfv}!Uiy33Ftx)<>EhTCFjsa(}HpR>m_ z8lXrVL5~z%dIstc9*sZ`8|grk2J4w!<$0)OWXNoddc=JXmEN>NcNA8N(4#c#Pg|OeuYy2pBkh67sKKETBv6@R7fltJd=Sn@1ONk!=&2sqv=se1P``KD(AH z4T}WJL4~wkO>DtQCi6Y95^Rxt zj%9U#v&9d$9&m44|HCnhFB|ZRr?LBp?;y&20L#e%ErMXj3ATHJEkjyjlrKP|RNBgq zeN|)@=f;rqrDK80g~b91&51(5rk!RdZJ${`p|-ZnJx9ps1!>cBvi3>;^ng7znnvd^ zZf(8UF?A2rY?A1WdQlTALk5YK80&!i>!8BZJ}2>L1}>)y{@&fv+#F=4-`AWc@y7W= zTZ?+K2ZWy%J@_;s7w0)JByV+u2W5EW|Gq#bn`U}{7tc}NP zfQQ~GDdd=IWKa(*1gS=Ko60;XY7Nur-~&x!a$ZM#o3t2IdpW=$HxKRNl1#wR?)y(0 ze-^lDdWx^neiC6{263PX30sG~I61Dfmia@u*N+{Fn-x7ovM5CATw=2RV87bChb&`y zVN*)~F+vQTP?TXcKc^@`NIG(-a?1v7@mMoH`@s|~etHXG43)BK_3md( zvV5x`YLoPsFi&NZR~)l(dadC}42|qFFgour%NxVf(_z)SBL_)4Gsj|)l9sQYutUrW zr*AVm#+J^28Bz%hDK(o*3)F1UkX^Rw?ONWC`CgeWh>nss4<}h9L|2GwvPpgRG^waI+}LslYrgKIr{(u|_Wq{>>vdy}l1Nck=)bLpEZsn6#&4En0K9x93< zXI?Km;l_an%rs6C_y?24WPoI!NnM<9R57rphVI~d>0=OXjvf#W+Tus?WrLpZHTnW) zanZd?{bF^(hs0ruJ=SI$8{a0)C0kU9gCg{g49^7E6~lTQ+j|$!K@<`Y7tX8!4$sed z{RX#E?DHHKY#Y3F$`tS{$*>)jwxzp}TyHO8z!5lRS_7y-EB4oschR6} zI$G@94plwpP=bMlVU4+%)#C(~w++J#OjjbI8Fx}7-|F8v81M4Sqx_o@4$qCIn8FP+ zsD-Y5rwOujTQHgBsA5~ObRQ8>a`#aD=?4N+f5bNV_jb$vb<6tyCC9(_@YS}gjxGq~%w)}NNe=m*>a~VWnF+{Od+6vJ2a87srVNGf2?!g1OE>y^rU&2R|CSE@ zdnP_z;jfGTs<6Kr$N18pric1KZ3-^P~HN2{OzL`&hT^W>`)5Lnqvx5Gk9 zUyiRbMwx+gD2J!pb@7)bL3x+$lrk>Ap0Wz8XP$(AZdB2e_Tny z8_cW{^p1xoAT3gl%bI8Y2DGKQ0h1>WP8Y&XPd+g%8+__uir#k-M7w$pQ1%H>+ud%a z(`Zm3iM5@bv*JJNqOx-fgK4B~6W2y#nM|tI*f|@w(0QO2ZyR%OHa*}HT8lD*c8-{~ zo48^sl6>_tHqhBt#)X&Y!r#FwnuBk)pVfQlJrYqwBt(k6KNR7%F#UE)gU;-WdReBm zQ>&81ssF$aL#GIyDzAdU$E00BTS8N5%B=?H!OcVIx}ZM5z+xs;4!OO@eSbm3#DqiI z>rwCwBgiLB6bv36_Vt>}{HRqAbj$;r+o&}u3hPLPfbRZvx0+oSt)8~Arw&J?>2pcN zmV;3GV}w$9c4!i@O)o1eG&k=0gn~+?qH5sy2BP+=*Ksx*sLfW5vnr+-OHbzXomTh- zdv>GoXo>kHbkPs zm-!2-9j9#Dk(m=0>Q5e6;L9`o`t;9U+#d9}B!!V*H)!XRwlJwO_-KV>S~z+2uu0LB z^{sT(lPW?&bVk%hQzCXkTO2f#X?o}!5BFOF4;$2Z4kcswWc%^~79TL~Vx|HU-Pq%^ zpA`JTd~8MOaFwlG4ojQvT#zifJZI_>PBgHzK;)6{*;An!@p1t4=&C0!QV-ES{PbDW zmRgGm8``|~cv(M-&7i6C91pgtXZ^C##PT6+bKbls(IUG?uWtuWuL7vuOdFt686 zFK|2LPV6?Hz#gWyvc{u3lV`>NX^=IGJGf-gX&`H|rkd6}^4Su1!o}i?Ep1Y4p)g}Vl<7#*r&%}SA%LGg}8i2#TbOA|bxiOP=S+LY>3|i(oJn*7!}`FPPd8cCfgrxyaBqh96e5dzzap z1N~{lWZ2EV2Ef_h!$|F@`0pP&a@9wRvU=UEnRQ4;7`6VwZv~9;PR@3<05h)p-o?PJ zV^M@U;f(RV3Zd4$ub7hFcA)RJ_9dH;N|&2in@$1xYOM`(*YqBEWlFQRs;Zwt?M&UN z`NaFTFSym>Xt@AC>{2_&m&6w}o7$9jnZR(zGiA~bsY6klHJ`Gtk@Px2A>Pt92rmQY znuGwV#KxM6z|^BZYfJ(lD1U?W9kcQH&ELNSM>#0s?(O$D#|3>$=C!W*{BT+)CTGTe zG5>ptn?wbgaJr6k`OsNeR~!6Qc$|5IfnE+NRSx&Cx}O&wor z5eid$WWX%>ax1Zkm+~1;wD<}D5%ui#TJ+RUi%Q})q;s}BC}OOe5oi zkb-dqhvCQRGQp}vF3w>kI0;77>+e}R|8bi^_!P6E%%&ai&xz0~T(G$rBlaa{IE3_L4KEKK#Lw3CEZzl;(1Xn$`R{K)aY>4Fe1bQ4V*-XqU zV`c2XAiD)~YpUf_o9D6Ome@K+uqQTH2&feFq$4N?(K49C@c01&&rzXN;K;t7F} zr5&mHbmN@iAJ^+wgxFX6CD%Ve%8q#W($Z#q(cx*j6U>V}fMbtMN6_UO2)LdR#ock! zzH!xk|A&Z8Ne{d2kGmQpm(L~a-@F>(-sRIOh?c2F3|N}#o73{6wJroKFv#SrX>d$+ zv&-G;>1X)-$O{b@40a$OmjDXmq-0kVoO_E~6u7@G$6-@$aq(l}#cLbwNqx8|nHHE!Ljd!13+_`AUM2Y+1T zuc_@dTDik3)c$;Lc&U!mG}W%;P$67OR&*k!pw>aTYOlA?$Bd5@ltUmK zvb3&NDQm>eejk{4>&9jat!#Z?*UwtXBP!iP#sCbr{-OyAvts64KxhH(Xz3)7Xk6Cp zcIWD&W9qJGsBa|})ZAJ=Fo>992^DLaD_`Q+4xCWi63l#@U{7ytflfwb?e?*?1gqEd z)MStLA$0W&@hcc*QsATIm0)9Ogj;~VOAvW(q_vaO7x3)Oqy4{D1`RrCT~8as>CS5c z7We^C@3VKyx%4^9mHeW64ybgiisvT!xQ)@3VqoQMDVs$D!QIfxd=Dffdgu;cCv=vBpL$- zv!N@Mrn~HKe~2JwUh1}K4H&30OY2E=-(!pX+5H`k2(j>9O;ZD&KIA#XuU;@@Xk4AjOH7YI?aIpI<8^rJ_D@$?( zY*RgZ#*uSzax?Uv@Lk*3e>R%}jX zC?#!R7{agU7seg8dewb)&COvqN5`wt*hn)DAt>Z$R>(uvGluYFYx{aCVDb8DgTPI= z4Pd7Vszt1mf|H3kliazQ*U8q3~-}VyXJIHt>gQg{cV``(T!5bVjW4pwI;l-*7J#)mcX-j02aNtEzhm^NW zU{WlJA5xqCY08(omfcIXBv#!XJdetMXwIUqbvh$>5Gg!JdVn($$}-kN$(^rXy)!Bx z3g8ytlb%YFP(Zwhw=$ZSftDa=7Vaik9c>Tus0q!!{9M0`^|Ev;NNXvCXJfjD++#AC z=kAi-3JBNGsa%2Aw;y{uaJL|U%&t6WCLvKP^EZ%Ci>w3-h0tKcOi>4*ZwoKENe)!vs!HI?*f+pTsh3O$GsWz%L;62N8^NTaW9!X7Xr zHxUxB*#yE)!Xk*iYJ(6Y7$iXuPy&Q31Y`@Fh=8&R2qY|FlYNnZ*a|9Qf466j=gj%u zne)AK&dfLebpEN_n|te4>i+6iRlj=bd7?H+l{|A$GeKWEW~Q#bxo&#?d!}n7sbt}D z6@LS#m&ImPi_l`rv|qUB$DSq{DH`FtGKh)K2O=wU4dzi91R>u4k@VO#E$!~5v9xa2 zin0~{mC(Aw)hH654pA$0v$@x5mYe;5+vmSK{#ThW*{kbboEl&)uW?)|?N1r&*FDku zyR>z#_w#+tGQJq1m}J>fn}_C0<8sRzeMV4ckNcGtFtd0NPPq2=8@rC5z$H_Zt3kF0 zgnX0RAPzEFZ6j0f`x0!%yAGHIJlIw4ussv8L^AK2I!x;?b=MzAN1VGl2G5dhseP!1 z^ct~$%t&F*ojw0SwNjo4z%DwJ2aj5ny(W9K$U7rQ9^BlynTbo*6+Ey*a|T}3I%D6nCIP+98bw(lqf)IWf?Ld#Mg+7Psj zCQB0x9$ft?<`S4;uxj^iH67A$Kud8%Wq&{ZIkxM}yN&Xa7(`Jf`bDHPX_w!e=OR|D z&SF`{;C9SVVcb4KX#NDeTu+BbZj+k_=e`ImxO*eHjx%`@Kti|;f{1Ew?a4x@eKeHTvQd5 zhI5x7(jN9|p9zbts6$ix-KB0MM84~sTYX`!6cbHjTN$}FDID23JjgH0_BeC;j8T0< z8#L!mElM})h^piAdwwp<&X2EMl%lM0_=PD>9e#ptLN3~u5qb`zFzQh(d9A8(j3RCq zf@oHI}WLvR}N;BJ@|7*c(1gq@S@baNNjW zF9a+XlUpVzQK&R7S0dBN6z*MoeLNv*Er6sk4wFyh)_LY@eoo}@xbgFe3C0_-&t(B- zY6Qxpd|y3}U`*OX6~2Zw2$x#WkY(yhNpzGCqGdEVVKX?(!d!zFOs$N~3$H?}+;*sq zF50gi`^NKZ71MSJO7bc}b;DgZ`T4PU`wUq!8l#VN-ve%UtQq=oMEUWfzEQqbo=;tx zQe9;C!BiLTKmplR3Kd!L)Ynn=U!2lokGe{fn1C~(FvmZieQDzf?^0(N^Si6dJ9@@??Dkn-s z?-RMQ80|=*L2o$B_>C2a1F>LS3seOl3GesgIxcY%E-$YBzzH)pQlqGO|8!m*YoL$FxTPPd=-F}4y3#9Z9*&V0|~G# zT!UyO3FDdvOeZl}d$>`~rx9M+9h2(oB=zc>cjX*UaI-^aGLRk(=OE=SydQI8;5V0* z_lr-`kL;YL#2f&Ei=ZUDI`8Ua&AZsB^HP&s(#I1s#mHRC%P2XkT9=P~C9N5-xJ4@O z-f783nwUb71vQ*<^3)#j^I{JmNG3!9UR`~La4pxKc0=}FohF5Hpaa4DwAVN5i0kH> z4_;_hRT7+iN?F{=DhbX0m)rr@fFDO-vQOfP8Ceu6$Z(s|>qS;uwua7(kPLbv@hYyl zU%vfyOz^&PQ|Sb0adu+h#W=cAChP74g<~lYV=Ok*d7v8clhyFO2^7gg0R&tA?cenX z|9fA*Mu@(qf0pDwjCcR<74biR^4CItP5;Bf@4Pu1peU32$BqQ(HVvc(8tHUGjeobD zUGQ%FB^Y4b2){cJb+*x0$MO^f47UB-`H+9TNM^_Je><=IuNQ$_{(s&4SB3p$B;$WI zjHrKb20L&11Y{>Be*Uroa*(~82VK!uuk4h~%y-H9#C(=~ z;ECqOXgVk^ibdHZ*1Y0HRBe&khF|keaG^^i0%BR>K5{_gQp!(R_ivqyWX~z?dv3M| zH!nwP^qb17v$nQ`#2DHVc9N=X?$lXpyNUoT&>M+1$USmwyR535n#GN^T8**Bc^t_w z;LKOs-#wEMaY-C5Nk>|3y;0@f zeP}81BV9qCjK26ADOL=?2aa^OM7CZ(#%3~e>&mo?T#HO|b?Xk(LrY?yY%>-}Vh>J6 zcENnUYfu{^%vJ$I1rhKpl39Q|RU|5=^X6G$Yt3Qi9aYBY@p_pSY_VNJzXkX3eddc< zqzxFdTu1a6Fc3Wm*pu%H(L(x@HgXL?TJ^Tg-bwdO=LZQLl^0qQ4o^^|=093d=c#7~ zN$zc-ER6)!ir6QI=QHW8Ljt(_TmaBc>tv&^=@%b|JdF?h+w{l7Z3b%K->Gw@)`)6) z6u!ti(zYt!ZBWI9ajFqm0r)pI{3Ns9HZ^#CV$RszRNXsKf5tX02In&rqA)+pQq9?% z_{7CmDSzx>^a5Do$!og+#B`CV)UCd{AKe(I^4 zlob~T7ha0+Q5?@uS1;X#mKi?V=PJBe85kI~EOGIdq{o%m+?C;pE*0X|r>Qw3Sof7z ztr>wjGetL?mNKkub%S$`+1!6@L%7|}<=+T%I6m+G3#4MF``rM)*mFnhod_;+i3Mq_ zELHTg5d~d*7;>7L+yruf5>=)oRGr|CU+#!CRN+f5*u}mduXH2v28!mL{^7odJE7`{ zf7-}+mFPhqj$JljxqjZTw$}!If8Ly!+Y)iIiaB#+Ej(=6r-H=Ep#&*4;RbcLGb;HC zVg2I`9s-4irqv8eZ}fI|2}v1gsxXg&R7v-#ujXO18&X~KvTJmFp!3FT+aEIU#RmY zB{*{x>TEN(gvsr#KW-tY5T2{Q63FAQFL-j8tiyd?H_XpyJYXQFvqKYkNzX&o2Rr3x zrT#w_)|FF9$~T>DqvS=pHgsE19oT@!qt+s@J;nf%f716CXi&L=muA+n$a8%!!YBwY0dlj>Vz}x~vKIXy@{L zFHVY*V4MY=1A`$Dm3ufI>vs!$P*&Y*$Mi}_73D7a35B|c-p>*OUX1WrhtSm?yv}u* zvFkiQ+AZAWa>VH(+HTl`lg8SEenB(8rjbE~f02h=^L!z>1fc8{G`M*Ws)cEO&>sUH zv>vxfYWje{HZLRHSG>|7LL%eds$BO%;$G@eG%9t%JUqoA9+>JPZRP*Omh5GyhX^T{`(bYVL=&q3%~L6 z?ataEr%ohoi%~>nsk-`ApP8q3f{uy#8x!L;3o!rJJpastMje=4Hj5)Fjr6YP5ORk+ ze#1~*k~mkC(Dkf&DWKAiGxvY3kzY6&AfWg?`eTQG=(|oR&uiaDx)JS&!ML!};JjEQMvv*_I1U$3 z4m96yGqhgx%1WH;1O@Kd@ZVs5-!;k&JlBQTF}qkeOvCNCLv#F-)z3>_NiFdEq%gX| zzU%|R!_GF$je$O*c5c;x!6QS{*C~DG%IatI5f0Gb+kRM22Ro?>m#VTREr+86!MZtj zy7f+f(k_FZx^~~uEqx8SK{w3CXnKy?5CZZz+-iJe(h}VJQFCj9NAk?YfVZV8>OP&h ztLrkO--zAT(uJc$$f~#ar=AZZ3jPurc@T*RmIvT(6AsoBY-I_*=BCvdlb&@Z9Wv$X z6x>yE0qG^S*$a+n!%XM1Wjl$NhWegN$r|~?26dKmtRe18rwr}J^684WXc#fGO-0|( zU5``!gn6TIba<-RyWF4`lnO4ZBF;srsmRBcUw}U)Nk;=>&>}1rgU1B3XpwEkeyN$M z;Re((b4)Trfy!cI%ub7f99H-sGgsEDiBXK!&nci6%qtGuM>?Tw`7!d-Uxc9) zp&RSQ8lXw3WN>%l5I&e0l!)5qAFj><$+5>~9cB_77ytf`@wz_;WM2b%U(+2C88Ps9 z#3NK-jUi(_KkLK%&A5Y!D^XP{;!dv{tgWHO+6l=X~k_G(N~Tvx| zJ{^8n=CQ(flbkRptyI9_aO&JOaxZ%oB^|Orjk?ku(iW74s66P&kK2!ecT}c87s^cz z3=NGDFgxe3n8>Ew=`S$sdhA(M%tS=04bB-bS#KOl<$nHgczJmgeyn~>vP1}SJuF|@ zen0(ce0aUYEqFsI6Q$EqpY-?}XX83)qBPce8zrW6CJ`Vc-E_Z?qxnu7{Xo=rvF6}r z&#mn@)ho9`9!d@oHJFTyBW0+AoVH?lA(CO3#GLXWj~7`EBe$zTh~pJyr9~a1-N+}* zT84r6oR(_soo8ZCSm?Y)`7DyEO-|@ zBUn?ix=V;kvOmky&}td4aj%t+rXk7e6S+eNF(Ka;T>cDK41M4W@;5(E--i!i=L?eF zEg5Akj->juzXPeI+`p_IUW026*LX>E^bPbHqqLlH=9<;zwtb%==yKkc9^mkWSfm1t z6~5A^vs=m>T}o29f}3BqZA~-=v*^btNyoS5S{S7 zt>eG@QC>XvDlefTuDWo4q9$|Ae;wOVU`O&ho~GEnKm4>}KvEA0S~iUB3@1X1KIa5Q zWKna{h)_;VDBK_Vgf3yGYa}CYvhAt=BpL=-KhEe*`x(KTh zq5+_=FFice5m^eC>q5><6VzgjMvDk{Q&nS>b63~K#;yk!_*cuu7v`>f z;vAS5E(}D`8KxUpORkazCUWy+1(S9BU{vJ!PB+Gt`wkf{yjRWUt0*zl+DI}FiwdEu z-l{T6?;)=cE-S}zarq@gz zwjWz2f?;+W_VWf`3JYnV6tESKt&*Ir515spQN=Q4#mEXE9dL|bFH7t$-``0(oPHam zA`%6AVX*;*gDj{&)*%$3ajuMxo*ciZ%sHgRjl)-kc#23@0m2iYCq10UR?ulOx*7Cs z0SPr+v!&hJ{Hg8aJ7K;iHg&J_GqQUMws+T%vf|_zcg?J&?EJZFX${FC6hlDIE6qOk z==oH4s3;SEGa~GBt>Y|cGfPT2`91+B0t9kdD-9ai`570l9qk_9ipp7pcs;!3J1J{9MaP*O4Yl&dS59Zd@GvwmJ;SPU43T6n?bY3!#N8IV>`%jYzMfRRU=|~6ORL65vyUhQC znEy{d^k4m``mFY;4%(Am%m*(n*V~n?45nQRS{c~7dSxLstW+GR>+IaLQ@fC!&T#Iv zg}5o94x-z0MUJFe6YXdgi^Z0=Y@Od{)5jV~u7XTF_yqWvXrc+@j!UD6XDRMWKxax) zNif4908p(WYzwDPJlYWl}0UOzD@SlH(hPhs{7Ese5@c2_CQaqGR6XVwK%{53VpMA z`PJCdIy%?741F%JIIpOf?3tUz%;YV;71#iAh0~dM-;Jis)7>E}ok#&GBX7a3 zJ}b{PbFswQEBI#lp53)i#U|~SGMEObmU0{t6|)YkcGP?mq2Z9>1tl%Ip+f70-qa+K zaY>MV&Zvq2Aa55At{8Az>_XjD96O~I3@3fy1a%B5Ix09YO@4+ z-mE^B_0-};fN9C@2~l~T|FVD7%X$a+W6P|&_-Dy2`&Kc*-_i@tJ+g)5RLa(9gCeqO z?16mD)?LlI%KS(7S`9Wp@{r{S%L}#nY0xCig_`)Ap_j* z1}Iv#zTMq#aX&tjfjzWrGiT#s{jLW|KKNN3 zmBv1?P-WXBc&rW9f0 zIUmHdB>L+v!Yyb~Weu@(CFr5ENwQT}$GJ*pHy?fxIeSEjyBqqqr7CmCAs=gx$c6u;qc4hE<^XO#m9-VL4~*EgRlQTFiUwOwe(^E4Ia@_gCA~i#LF-TV8g&SaXMk zq_pm$iYM%7Lsl2LjQ_KXYM-^k14mP3TX@oWUR&N@bBuT^w)YPt+Pxx z)VVIY!VT!j4CoV5`1yKgUDeW|es?b?v^HxSJLiL`3eufeOP!|n# z)y1paMq2S1ME-9Gk~)v~7GV&ybvCd@%c4)L32wukP96>?krnhEbz1i1zLgWHn&1W` zI^175%u<7%((%QlHFBlC%AZkmq$BM1kslgHGgbQaFc7+PVZfLOK*UFQEd4f}+f`rl zMpre_g4&Q@<&3wswRAO&T6}ezOs^Y~70o)FIxV$}4~{zB0fyJ9s_&8B)T{{qK4r|w zm^UDz!C(#l34C#t{cacuMv3U7Q2NkC0o z<43j-kMi9TSfP;&YztlS#*CSBQ~AzwtJ4 z({X#z%FDTQC8?KA*IJDi9yz%`Q!~%oF@u1S;beAtL@(&vj#~Kp&GPS&K;=8rPFL%T zM~6x5cTENT) zp~|t)l8_J*YnMT2&a%}|$bnoWsg@{crOc?DF%8>#qvb8(!Q!vHJ7B3^;)8v+l4{RT ztta38-OEv+!*?WK|L&O_+a8=Nw^{z&&G4nV{OSM=IbgieFm`5^)+N=G{le5Lx(gvB zpmd>aryL7r3W-Tv`S47KqHn&BmZRTCI?%^SB=nEfFJGiDp&60yKg+kLAbP)to=OPk z6p17R%3w@aippzU^_hkp^7540x(IE<%&C?yyHsDAY_SJ0qk7CvUg9hxz)b-Y zraU1U6dn%d zUoW4;eToE5yE5~2ehqTyOaZJ~rLJyGW()T9wWbmMEh#0KD5{)Y<{k5 za-h87klEoh%P1#@GPfd3bZk(Mf?nqlT+l z*11V?lU+Tzw0!TQH|do~cS4 zKla2V2A9aVjUQMYUOI$Dona_Z`5)=mX3vi9sR3D4VPNhj z5=G>UTlL?cc}+PgJ~TGszFZJ)(mw1yUnPm~=tcA=)69TlE7z|>CK7zuHVf8zi2k#R z(8?OAtsb(FCLzquy)wAwO-+@PBpFN2{UzIn#8FQvRJyU8Q+@Vr?+t zV>FMYu8**KCYOuK7d{W9KDn$--K$17IO?Qs*^BLw&x$x1zInXXp0LIoP4-tsVn>_> zYJoHF)a#E?7;wOc%`VJ!os?pqH>MC2#`s5DIf=Z%^)=#;8J5eF zJ4xeu_UOuD@4HZSo=IsB<5e~}es$-g?*Y@7l2>(wb#?`IRb;RJ+u>CuQHQGBlL}Ry z%mSTn%m;~^r?U1@&aYkK1kBPSydsn_zn99HhgWg3;X`*+?^r_mbc`N#lY{_rNt_q(X~he?oM^O&c^bvaP4fWCIISB*($&1&bhJ4Q`?lHjTgy?b^a z@``*si<9cfIrUwdWIWAiOl+iEeX#V=`LQCa=DP!ic}uzbMWXQa*~}9w-|&d0CG7h? zE>{wIHTx_}GJfe9^p95@iDh8S!#yahlh;1y(E7$+OR;aonDb{bwod!lnQyVH*@(Xy!EMhTNi3_wW9fgc!__mdXJ_p?5Gc&M|46i@6EniW!F4ChGSM{>y{ffAWUi z#{gS-%TDimV91|0aDuvH$5(3Auj!u|eWh0Yn(jFK{%FpbraNAutCT->?66tV@#8^F zS-cq+wM74EJCZh!HK%&Z_PCVMKN0QuJNyyW-@l^z(zySyIFAr`3O|;Hq>nBHSo>sA zW^Ob@FHnDNs$Kz5s=DcMSyY48y>XZAiInE=~mf9z0Ak?RrT@mL^8g~H`!L2>7-joxtD%sb~I zl^z3Q3S$YwyEX8&fi1_1*l`KkrtDmvMFEX<8ItC2eaeovjD7XKnFTI@6-U-rOxv}y z3hh(0CQ5u;G-=*Ww({L>`u+SSkm#9aX1Pno`T?@6>djda)2eS!jA=1ecvfZjv@IaR z)x0zS2+!%H-g|pad#U0SvVf^173AA}kNYV>WlQ|^xTSxVj%6p(oOKZZb} zen{%%e^DB!|CU}dEZDRMB2X5FRD!qISyV9ErrB-HtGBCggrK`7`SoMJq642dGe>}eX@n$-)7??>7tGRBSUE!r)5xMDD874sL8h>!D^~IZ~<&SNe zOM4IY?%Hnb7?!HCWBh|pxoyK0g#F^?)IkA|!g+4JMB=H>MYHtHPS%Wrij9JLU;gUg zAW<_x?PZ1?wRNEV<1z2D2IJ81Q-sSbUYO&%>8RpzY#j_$D>^@L-Y{wq5FQzaLAoP3 zBN-k&T?`fe?O520(Z3b=9Zd}6-e8s6sfsFyda0}nM^$JsQ$$YL5{boojcw+|X4J|} zF9g>&1o~S${cVFVF_K*YoHmI~JKid2wpuw}oxLzVzGfP#qpBi;ypZ^nP`cSyoH3?Z zd1-d@e0jAJ(F>D^t3I!4Hp9-z-1p^qMrbhJT!KB@{2mHjry&^f@WxY{$`7J;PX`?X z{3;0sQB*rKtvDI<%O+qy2m!@+G<@dG4*b^a0rsNn!4=ZoLi*i0s1D38$UnHi=Vu;Q zgF%osVhF#X^rqUjC(9bXaW;W>=P<`<1w}=fg1EX1BxOy`Twt0hBAow@Ra(j8@e*r* z-kRnSNvy!J_hN1*$-OUJkhx;3_Q55uuPTcUQ0Jy6j*xsCuRp$SRkDTb31Z~2=;>iY zFFPDR&?{=!J8H>_lE~k13wE38Gq*02x{y8*&jYlBjDzFKT~8U5n=cMEbc1Yyh7+nE zklQJVGFI`Fk=QQ5UFY+sugALaWcE%Pr=sLi@s(pH;nY;@%F;3|A_xq+Ya zXc)IJ^Q|t;Hb2nj1xq^{%B#4graHg4TcbDu&bzp*nMLxcDAu#_BI&=^oMN~iZoBq) zd1d2%&Mp8~t8BAHEO*=xnc_9uM<6}Tf10SqM-d`URJo#zYUxFj_!lINH*FM?nVbeksPh=}~7=6L0 zpkB$)OWkyxe3(P_zJWHc1N-dvlg(X+^39+yIs{z9j-HCn`I%rDR}=^FI>YWF>~3aP zt?QNsK+3Byc5tiktorrUQ+ITfzFi6O))hLjnB}a)Y+AG`Msxp*v^B%FDhNn@AiN)Ny-b{UjQhPK&Wlk>N5B{j;4@(Rq)q+bn6YI9v%gfH%{JvX(h# zMdj3Gf7VUAI^Iq4y<2_ zBkuKWmM@6)x(@0Z*RGT*^gS&gG3z1CqZCd_YWa%=EnMOt-Uy~=wO;E6OZ9EMvA!^& zC$vukce!+j2C2Z#cP6yyDp)ugSy+c5y~0xbazB4*9o((qB6#>%bk>hI_EM{L(y);% zQ7f|%r@XirV1Iz^h^;qS;4r zEM~{SR7+HHaXhoF*cj+dkaX_NOXFQoX7WndwE_UUk#T~PJEQ%+LebV!P*kP0i}JoQ z{mq$J*g$w0^bN`1&4$Ct1|SA&f4(P-(D~BEV z7O!Y+ED8sOrY_^*In9>iNQe9PF7T4;Z~UCEaO)Xwq4Y&IZAIqiNuNMPSbUbGb7Nqj zugM8eA+^C{-rv{T$O5@L5x`~%UM6bG$gkdcoPdv5L3vZ;`wS}InlI0JF@P>6+bDM} ztP*_Lrop55AQq=utSMI*m}arpiw>*?Oe}bG<5=qK0!NwJZCYWF;DP|dj zbbokWVc=BK(U%QYnU8J0#4m#!?0^0ISGD|Q4u3U+|9S5)W%SMnHqdF_pD5 zOqYB&AYUv1Wq=F$XA5uySOWwBx&Q}&9l)F%`vq{1d?^AH01$F03b+ptBHzV+!%2|S z9s(rEY4?7+#K|f5e~aBGr;C!Q?)~H^xqLFXbN~R77Xbi@=l_DUxDNnSJOBU~L;nTG zNdy3{Rgv*`{ss3hJa#pAH~+1;pTQZ@xxevFx5%mg_ML74Q~}NaOMn327C@NXULkRkt%p*Tx%{``e=6z49TJx@*U z^mYy#~ z_4K`7y^hPuE-4+@o*|dY__MlyRUx_7pQVyhcxZm&&z_;6ICtj!@2#OZbM`jHIa<0K zLca(@&9^{qFESdpPe%b%6l6jg3L1bs;8^E((*GZaXJu^MGr{He5w4r=OF;oL@)GYF zx+~}!s2NrUb>3^2H1$PyzWOZ;2GFi;?O1+$|67>x;M}2%EaMSc`nT}W8M)qTO7h^V zzlC&wKQsQxoIiWc|E$p=(0ffy9?aebYTOisS)Kw!U@k6%E9VvU^h_53mk0QlGhv(h z+#~OQN<-S59|nQ159zqow>}(SCfx;mzvg60Femw_Yig@&bdFo#Fh4Q_;%+k2IMpAz z>A|W&Tt(Ki@v<^U5ywUH+uYQrfR%R*$IBs1LCgH*@*5NBJ9kb2hsq~0W0oiD#8bdS zms3FLJc*aMz$S_pcA^)J)C~E;1GBlYMWfz2VS`_(vK#rl#5eFGRcwNekoPHg>XxCM0kY`vC;ZXr%*zpM}44Cx4wO5DASoKXd} zP?iBZi8SK@v7zVoeWqT+vtFg9JC*xW$3@t2HP1O;24@Om`ALW>#Dv3MW}e%pnMneA ztFC;^i26f|-IJ{&x!g3Sa|XlD#=89*UO{0)CB9?9r+`PYt}JyyrPOgv%lAgBYn@}H zj3F_q>Y@ZgUW4!kYel@#a-&mQs2|p+Z2gsnP}yp!XI*N40nhPx@?pm*pk!jQf^N?Dg`+qgnM;B?{Qi;kB8 zMd-|2!yA}1aj>EO3L2T9zBjfQ{%x0!-NDt^?0Vk&44h-!z?YI6R?>x#_GcAl0f?iH zPkXZ$c35WDTe~Z+Hm^=a4790+4Dxds<2jO0pChbo>1G=`7sYO_GgxiQT&-cqXw6@I zpJ6YRvoxHQ2|<9WkjWiE^A`=M`JD%+OCLS{4ucCz6#H=?gFD*=QOi2_JyHn9 z*T+1;=1)L@a=Z6&{w}iXw*LH;E}&#^XSF}rM;ig9mZ3h_yhOQU6Q2k-I5UC(s7N?+Nq)r{35HYC(k zu1_3Ktal$eZz7`BHxF)5qwn7jFnOu3Ry?3DrJTjKqxe!g$W370wq~hG@6K{4qWOfse)Bi7}XbI|lD0Jx^^V-UL6)Smp^EWmq|44}^Y|eIeYtr2d9j_g<=}DRuSHVP$OKuz4N!67qbSw}o~9M~s9in&8w2?WplY zCQPI~yDFssg4aS|Jtsh#W2XK<}TpXD!hXgtiY^c)^{u=I@5({3)e z2NMMnOy~ELlK4xT7%n!gy79y$?z$F?y|J8E5++T$moa!XZ1ey6%OFL1w8OoHqE?%jW0iL5*?PhI+>tg{o10`xAunmFT80Zlf`xH%vm0+RtR3>Fm$<| zDbM%ow*R^#rwV>*+Tk9_kTMGnUD7Uo@H6d?=}{|T#{7VG?a`TihC|b!SuN&M06{3| zaDcrq`s~SoT({e^y!?z&>hu@8WpsnbN&fnQq85_I!$R_(D*_6`+bS!QzG+(>I=xuK z(Xzr3rM_NIVTSzzOpB`Lt@O1w<|8+hvTFKRofpLP>c5cWS!`}Al>73#o2$Q3NA^J! z^Barovoif%M4=4ZCfFYdF^0a^b}l*w9dMVjpD>FbXC0pzV?POBzew)?-KPLMXep^J zdZzMZSn)U=Rn&MFZMTGmGLo<$OZh9P_6Se+DoGzV-CcPSd5&(3Og#l`vY!I(=zjCQ zxi;YB#x#;|PJC*?-CnLds3XTXc7UA>3!e=fA~}_qEd@5sFw*9zT4jfOu%&kHNtzx8 zCifr$UlZEo*UO8}=Mq=MoJ`Ni@xM^liA1L{Plmp&->eO9(OJsxid^%P>y)}IMi^1X zuQ}XoDYtnlmQ%I`;~1j!;nP;>t65hE*Z3?1#SsKu2J$|;;qPp;wiefs>sPPoSYgRv^%+ZR5yC=aGX z*BM(^ctAxp#>Y)z*A>X|9bRhYtmjMW)qXxB;q6#i#$fBOwx`U+x1ncW+`hPhG1Tu- z_SqZh%F53r!PgZiV(rcN=mdzquJafx?YIaLV}ggS7Z4u7@X`lVx>pOo&?Mxqn(wAY zX;kfpOJwQeK#>qRn;lTPE+pe@h(wm9jzk|*>xrJ$wEQhqpbgJU3kia>eg4*{6F$BW zryqCcnFvc{X>|C+VTGPP#s~LyO0Q43>~eW!?#1X?X-)k~P$S>=^mWeQ)%%*)ej;T`9cr#yC92M61pDu{+^0ET&J> zB(#rEt@aKSAv$j9VQ}2D=UfH#H3li&BqQbX%bS_>PvG=Om_=%4 zQWX#3vje?SRgA5VxLdx1=@Gv(cm4|%z@_&;MeBbuoXHxck}5Y=xZ1px^Mc^%_r}21 zy*Q?IM{|Bs5eBI-LYJG)`2rTWn}qgrGMaM(+3#?uLpg}*^^2cI(z+*_W4&O;@%7&- z7W1tX=FSt7I;C0%2fH-(>f`fcvcwBwdZpCRgL+4oTO?0Hjj!lPqzKv;*RnCrWq98d z^8)gVDqvW4RibDWDt?B+swX=duSQ$D zcBV+%*tym!bM@p!mt;)`6p%oMtm8<6-agm*=ZP29N(rousj!l3pPsM`8KT;lKJW3P z3hlRjfToux?XrndRcW}GC(O)w&1?(y7>rm3klCuj-z@rA>oaBXCvltY>Ri<$H5S&T zaiLPG2r;;@vgp!+M}ik-Y%I7ChY-B6b0{CFtgQI8mnyb@R@IP>mY^yu%$KKB{8h51 zv;Hszi943pEj^pwQ?0Atr62RK@YURe-(h$)U^`H@ zg`LLXG1;ZPC{7RNraB*{6sN`>xrRQb5GT4a<`3Nv{s4!)c^ullHQyTlkkIA6DgG+X zm)oB|YMN5%6;so;;GE~X-0N>+G+AZd79sODEPYHDC0USzrgsZw<7Xo#<0aL)-?XKd z>{J?id2WWk^T=mu#wJ}Ng0V$h@1{0spips>M*i^%-Tvp$|X%P)t^*SEm6eDpZ*(mXp`pr|o zSGWE%|7J{F?myy_fA|df#}@tPKsoE#aOK*Ubc@%^f%NPdaxMSKgXcf5xWBfD63Wl8 zA85wl-7I`m=J$hytEj$mqt_w7FSp*)w%ba|D%%U+?9qmfz6EICPMP0jMgNX`bVeq` zBX-a`>o;WngLB`0qk8ijG6(Qy)<4#J^W{lBM0bf0Cnr$XYV$g4j)y z3*5g@TXV#H(U@2S=fvsm-@NtDlJVZQv04IU_PS_q0BFk5u8KL^y{a?Pp2LW&mB55I z0zO~3KpW9#(Vh6j+9UN!1y_{H1no$9HOIRhW$vp_Y@d@0iUjHbOMfNks1WTI?d8NP zs=7@V&VD4@9|yg@=&Qq7uEMj(ug{Tm8&LhKKcqOq5K>&OB$`f!1X! zuOgc=0qpd1VP;L_6@<@eZc!TU$A5dPmpr_miN1to0^os8jH$0ez zu~xy`k_M|ARWwUT9D+Yi;!Mf!W&eZ2Gyk-?e)v!G+4G+yEz^hoT70zSz5P1v0tg$T8;IuMGa(_#5u$J86$ zU*$Iybm=nkN=yz<{Ndx{gQyDF zuXfDhXxGfgo$%=pvYvEXSgC9sg(hVZyAfqUNnlXMFDl#P(ifXKKJl8I1J-4fLU9mj z*X3K?aroj+%wGE%k#Bh0-q2-gJfw@&I#5uIUsqY#xbrf2X-F?E1ZJ4wz!G(`vhFb& zr9YA10%fR^K7K%{EdJp>zW=dHl(I%KzhYD{UZ*n6-{66)c88qs58sKJ{AQ{OgaVF(X~zM74W zdI3&^(}joh35TyWS*NLRI?z62nn&Tnmo~sfc(9?IT4<53Zj(ACM3WX24umnbW`azd zYiW03I>Fg~1Tn^l3f;|_0a%;v{cdzjZj2J2TeYYbEoh4GPKU8qy2oS<(x>j$edo}uj+4ieLA2k z`8C$~shtheIc_RzJp(U3-`536#l@m`P>~bL_2V$w{lr_yMbgH_LG!myR{U0;APkwY zkApFLs@IrvSKQn=Du7TyPsp@uM6ez|UtRLG{Jf9DjPc64gJ0BT=Zt*&#rf_o))^q9 z@J}mEWXHIRUM@CA3uvas;F0m*1EbDXg;xZtf-Nag#|SW==ES6X7OIvBiCN|D2#B4I zyZEYqg8*%4J+3f2 zsu0y>W1T7QEiQ>^hHtBnRr$KzXZBMnh+s=#$;K3-PnZTXFnM`_#?DI8Le9v1c6LAK zT0~Q{+lpa@W5h)1BMNp^ov|F97?Og^!o5r;yc*cQdI+9P z(tz8`hbu$is+w2X-u9@yW4%!j75J@;raeI^%gJ+Q(-kK5fd_Dg?jJ1Pe^&Q*iTMA9 zcKuyd{;}u!L+|@D(_gL?W}X!WC}xxVUMRr$rH0@HS<9RpW#>%{!mqO&0Wy)tWCo&H zodqLiD*1Ws-QGNmd70X)(r=WXObhEoq7&RRP1|eb6$Hfb24kGg4s-q-NsG8XXh0m@ zQR;e=i_mz0#oevCe4$bW7^w`XFEAyktzg z!>`jP*@HpFVl$EV74;As6DB`4 z(m54P#b@XnexYbgT_2`z-nuqhBUBs*dpn47nRV{~Eeuo%dY3_ES4G8(zCqM8`t$-E z8kdjX={PyQjrmHD9o(K-+JW<}A8AgNq0lKlxbgf?tL7K6ubOU=2$9o2LYQj&@U)LB zwQiLoi`l+fpA_2XvF%j5BHZwMY>NbCQ5FIOqMn)e86c@`m+S!ffDjZAG-1y3ue+U> zXTMR<4+dwsd{YNuia7Uizkb6sIM+a4Kc;TpUJp%+VJfx%qJggh#lfJC3;GkXV^s`a zombr`b^tO7l%z6QZ{k|ug-S&Y8`+RH)8!a1SgM z6iR;tqi;ti=$Ve)Mw6W0te=z6&1%^Sw|H4Xl>~8~O9u%t1bCB<%y=`)pnjNZ78hwu zDsBt}a5@vYuCRi?v>6gT7`!(o_Iz*$dn1cN@{Ze&953`*%703QM$RR7XE)tO>90iV zW3adY({X+;n4)&ld;jfM;g*ax4E*;E(m0frxpcoxTPv8}R9S+-qkw zUELEs`QCr>Ht<$}7;luhgd$3WzUA&+Gw~lz`DiP(Q^0(bURAO#l$u{AcCd@(o>Fpe zj53GO;3B4$=32Yl2#J=K*lB!?dGx7`Bb;m@ts4zBJ47diAtPKs#{CT^Ehf>28LnMWd|(@wAH78_F}faS5Er9b6(f-8n%DV^ zr0jE5=C!;bbq%`iflo+tYhNixsIF0tMuuCBSbLqysH=%Llen{4qHUIZz}!m5dDEBnMd<-Qo-(` zMp1B3W~Ly!U!ZZ+l*K(dVq{#?*3*SlyLaeiey6XJoeOyPn)s;<=|UMlKk<%QKieNC zq6uc9}<6@DVBa=z6@nXqaUMzTcPY@T;8=|zPamh4uRj=ZUiws}E# z=U^xPIIiEioyh4f2{alT^TSR|MjQ=m;ZmLZ&Goe6%7E$(bi}Kcpn!?Q%IFD2dvJBP z9;|HryV!lNNBaE=x~ja^d2wixEY{Oq&^<-t@V4oShHyr|f*cQ387)jS&O-+e*FYCe z#K`-J`xu3L&W2lNe{wZgF1L`mlkvvUfi{ujR=oP1ZxxMRRZgq{_2PDwL-af9-aaFT=ByEomJs7wG0$~bQQNA9`njwR5 z^U}4ZAy~G1!0jX-A=FgIYQ5LZ7bB=Ma;h4`ZdtqpFa^ZCR1|r{v zwHi$-p74SvI=0@{ zX7PHv4OI?nF&-^Ns&%X|^XhObqW7(8Dhd|xS&s3F_`TSy@;zIjk?l^S6{L6B?Uy-Q zLgTuAOkovzdewr=U_@~6g+8d}YaDqXt9e@<9JU!RM#n6rf>( zJ7s3EiRY0I1kX(&ZTlgqlRDlTs8_nm=@fG}J8}h0;@>k~&2%neyPL4F$x8Xf$@H=b z-M4{ZaRJ5vg$WK;ChHSVILM>{V|Ikav0pWa7MIMho)wV=!K=d=q+L2-C2y4?T z-*h2{#k(*Auk&KhWSsLFhhFrkV{EcAJoJau@!R}|3DItQCM7>wIX`RRGj`}kvft!7 zaaaUQu{gg}RvDJ;9E8=RQ}2Q*}+3|U5PZ$jfU=g&><`9dAX*Y{?DJD!!nETwTfUkEy#$#?}3 znl*oS{i5>}->;FPNzoY}j4%Jn$gi0~-AdppS|qlHY*Y^2XJobu zZ3#X!ZE_&JVr82ltlUvdc>h?j@p9f zue!Q;Fkp zO~9CS))l?gGHYT2kYlHS=9FHdLEzIA8|N&U^GlKE}cl=ilq*zqR3xo`4 zkG%>(a{*B3c^U}>^kUV3iIOeW8mbYCRyXKO7 zMWA<(AI8Pkr?|YwGE}vC=Ub);jedLnY(P|xV=&0^>ctmMV(h-{B@HuzE4}&(bc{-VvVCFmK^f3D*0AakE|u+T zneHS^X`-vnTG59M9QeLX%<@cIPLzhrg(mDmBwyR$0A5*C5`;0G%1DR&qO73UDFs&Z zw-*!l`k=rhESAS<&sD&~o+QL>Hzo-^P6H8_>`m7^ij@^h!)Xf%7CDoJj0A zXvf17kLcRBc%k_PJblJ;||dy$$zFOx~Bkg1ix2LY`4dWJ=@QI{$bg zGlYpVa#PQgMQ166I(o~P_lNRU(M+k?r#&BOHU)R5fHC*6a2JWuBWn zr5MB?RMh3iwgcIyX8Rg3U1=&jlKjTJ6t*5bww zJg+(2!b{Wb?yhG_`NAyuxH|9Ey zSaNRvM=gT?Rz3fIUieA(hwlE5Jv$%>2qo(<8ol_!-*pE>c~fIZWoRxut@^`jAIS#{3*2Agz>-PN)pc|B{L`{yFK z`LFiPbZLr0tTpZnDZ{w#>}ud5SxAybcOUS>&1CN0V6Bl|Cw1H+jEQ_D;&9AUK|eWR%%|U5nO9gWhh@<97E`R zxzq^r&xJh z>^TMaZ~eXhX#C%`^awXR0S9sLz1b>2A_9ZpbK^>M zyER748gCiIGi0aG)PJ97;omIkZ4j%V%(rQo`QZhl@@@XLjmk@iucpvnl!j$d(rFWv z(+AV7siRv95ZN#Fw*79mwvP~zw@oJ=o&p59iZYw+^0%7vGcaj!ZtdAw?{R3y64CH; zNOTb#?30Ow8kgfu9+e)7M@Xp%(L)CZiXB$$=|kdnR{1nhZyZdHXZh?aEaRXIrvQU; z)9-^rab1(R>7bu=t$wfAPCO<%r(xM|E_zm;cLuUDH@s*72D=VJNp|+PJ>I*we>LpU zbMS$&M8fR(D`;Qtr5hB|z7ZY4u?o;6QhPyI*5Y~QRAyBAIRoH+&~f2PLy7U7!p|p8 ztcgdXwu|crxk0^~L0&)hIX(-qTw_x7xSbI&8&g;h@nlWx&s5nlI9_&+w2V0%(%iWG z@gUT8+rYJAppdO7KFcPniO|6rG%+X?b7!@1GwlEbHj!|fY2KOqr_#-m@fvb+h_PM< z8_ZC`jo4z5@{aI6y@$t(F4nDYmlhxmSDd?=8tNyOpHcM-B`YYuR;Fi{RTq0@7p$?#iE|G9KqB-0Xf0}Ta!(xRaMZ?*kcS8DQ}67p?dP5XZZ-_B z*~-GR+3t7_XnOFE?yY~LzQ2%vWV-*W{Y3tnkpCO+{@;rJyBN>( z*^(|M#7KoFpA`<%`O3keoOPpH9fQd)kxb2dpW7@J3P9pz+Bcz1e!55D9ZFP1vj)S5 zdOZEJs}Z9L^gMxG-<0zgzB2mN(=!qGtt8v)fPH9 zD`JU$_e_i9#em#h7$ywQVLcfczK=2uubFCoSSP_I$;O}_HUlgfQd;KBCi+W0Hrdte zxFHE+i#KaV4&qM%a<-HF3Ky7vfsgd98BM%P@{faK3i`9M_9nb$H=m6M>3pht&SnC` zk34i@^|~=2X&3Y|N2e8E1s&Lwt-`iNtffcPe)W#Njx4&6Ycw>#^;7~V)2FAe3GU*Z zV5;5{trbUgv~(Sqy}SgkdewVR1{}>gTA=mRh;4x5?%lYW4FsrOe3QSX=z!c5OABUQ zlgNSoq0OQLQLO_}50tJjT+(Pbuwg<7OZHm70bF`~mY10p{p=1i97-#~8N$#$6lkr4 z$z)->Qb8Dls8efEYX&!I?BCRi!eIiep7uaY#><6Zkq9uT4hpZI;@aUES-ypO<6qok zU&fNU4%7PHv(R!^C^9|b;wY8hJZiry;_C;}E_G+8x+9LYunD|Iijrpo~} z6ciNTjP#q7FZM7;*uBsW>4=_n6<`m?8-iDCu#N%-@7^fFO&AMddKLS)1C~~vmqXCC zlb&8Snh0q|=k8w=SNuLWPpCh_sgwMef6N4a+jif`N!WQ5ZLe9-$Y4KF64ZR_L|{b6 zG1%V(3VSv<_oE^TzZhpN!TH+Kv%PoJ0Oc)&#kJ+Idww^j5wca-l2#zsN?jd_X2uDvLVAk^bt1vCl^Yq)QZ@lZ5X z@)Y$P7}P!|dc8wdDpQl04Y@?nS&CAeP0*6jX2~Pk%$PQQ=&XJ!`j&B$mP(=qwQa3Z z@&L<$+EYYeea70pv*zKA?AS|mExn*salX5H@3KZWNX4ti13}qOddIJp+g6d?iqYZi zU+qY37tw7DmyzX=g6^l6eK}Q9d2eh+;;}v~JBo-hR!{sl-S^2ya5nYVYdz8zh`M@R z%6da>5qd*iyel9hszjQl2s)LT^*CsEHC7i{2ZIMhDi=N2g@eIUFD%*8w~M|B|Cf03 z{=KsO?-Ij|zG*j=!&_V71LZcwW8HOqM&%XfweH#g?guTUT{#7OZa5lVaay*U$R zOA>3La#AXeROfhvrugxjdpS&t$8$rzT>EFEu5fJt&Z}o;6g9dc9odpp^7Y}>hV*vU zi7R{UyLjFd>{KI-d<^qX(l`jetXi@CEhNlhqGnCmxya|r9`I)Z86I1{6Jw3~LXxqF z0e5Qd__u&fF!>Xn`=L6~81Hg}`PW}@vL0|UUT|~iveM_3u zwlBXI^WPNyp_%)`S?6an{@8*2F@Xbq1h6brtB_8@$W|3SxsSA+L8jUlmW0!XV;if< zXVZC({bZQm|BfWPc;@ZSZ#lpE4M{%L{_Qs^s^5_0Bk%uVR`jT5+WS#s`mD>XV_aJ7 z(3)iWlSR@hc@iksn;j(UJSBp5Y1a0RJGhU?M@;w9($2G)pJd9WodT*jPXVdvC)@w# z>H9#V-T#K*W42%DK^Q6EWIp!9JLs_OU&VX1&!QIDS2&29hcVjwWOeA~zj=_Ap;Ues zgpRgt*ie=KYI_Q({WlLgTRbc_?ExZ0r|9OKW-<2=HL0rG2JGBVo+emS73!4`bn9?) zQy*7d4Wdn6^LMpWYfjEn_Pu;J=%#6{!TV| z)L53+$QS=Qpk7*bjFd`{EEdp+aRGzCCl_!v1GP)hAkvJewcJpEbOLpzlb5B?<#@2I z8j3Tba*}cvqIlv>QAcFO6OTW9w+SB)JD`Aq)^jeXFYJk#ZDeoA zXL;+T_dQ3H#357$7BeUT%S`|F)&la;R_R6bs-a^o|5O9fSlQ8)&y+HpIf`H&$LRRI zXWXVb?b&kTjrO*WZvwxG!f3>GUve~H3}lzs6ERrtm&wG*?sb;~4`jE=o7wC5%mm3B z%)ArcN`vafh#FfEe?l}xp-tbc265BzS^^!~@rRSfdN$cmz2ezr(rmk+zK2-6Mfwov zp8P~C{fUrCV&m=fCuUc?Z4zi=e?ase>1m6McD3)d=hqIxX46HFftqn9Hd7V>K>QnQ z430pRo-$ z=BL49{bo}1%`D>D)e`#V6jEP*i7?F4C+-GmI$iGj_wr$Nw!Q!v;{L!BZ=`LX6UV)M zgh>t6R+aur%;?hc%@g=k$hQee|Aw*yt;RJtYqk**nS!K?mdZH%rfO~PA~`Owu%E9S z0MTW&W&u6|7w9Sx88PuD1ogb}Mq-LHb;c)-W*)m$p4ouO=BPp-Qc=IksKWjfz|mg* z?A=h8(^Sa_YpHJ_D*F8 zj}h6!H;5(*S@mJKr?pN;rlQUnJ;vWBu@`hd?3e;MTgs^Ts4JY%q|VY`erbZYAPO}V zoPU6OGw@yD?|W5m!rPHF>2)ToRce{R(9O`tm3kuNW!^*K%tA=n0*bVUl8)mG!*;Iv z7g=3gTw{Jxp6qys1Oay&i%^J_2#N67u<#Bih5@vo#J_I!fg8>babjt|B zJ-Y!z$^ktP*lalr9~c(;fIQazk#NtA&y4!hko>G~Fc(wD50OPjvg3l+tSyVcsJ6O7 zw0CJs{=Joj3m&2Uhc)S3E z_k!Dt)v(|76!YfD-zm{0^0V5z zc_(^zA(q2K{WF8^gjwJ{o&M&87`u5Tq3{3`)>_1v-n|u7=W_DAnh0`MRJF;hf(9%+wNIfxj5zAyW@^T4 z^T)bu>+|{I?sQtd6)k|9=sbx}j6&oEl2#<;m2a_aA(3JE^WheB%>0l$?7WYI zcU{{Ir7c;gO?Z@e`Zk1zw)MS=-vPBe7{UDwRRDUJCddsa@3t;~Uf1+Ne#)2EvtM&;k`x z;?G^SUY#>qp`J<9JphB*m0$OFT%|28$O~mRQvM|hjxSFup-)N(?EhR~F?i?Orv-bw zA_On%i`%H!U5~;V9l!kqP8|~zo-S%VUjEjrmi<5v2ZK}lSZzu;PG!Bhcd)x ziOuXLugsl7^7|GzV>CH2t%3S3RX)1=1}h)gG|SRjJ}@D@yYM4k^sM3hj<9R-%IyV8 zqU~Qfm|Mu=XhTuT*n{ZZW?9*-#e;lY+>6lZ?nsMOX^thI+H^pPR?d`3+pCTvE*CrV~+OIN6F{x19(kd&5Rh2C~9Ok z#p$DNp|<6KX3e+&7;B4f5gTudv)A*hCf*d*!`5ac4zCrCZf<_|WZtYv57@+R))vl8 z1te3ZCVjFmH#=rU=NR658ZuzTS5(~^k9V00m``ybf7Wn7vqVC1B;<+-*;=Jf)rNnu zAFUBz7uLpAWNU&B-!vZRUhB2WX?*e_&;0JF8V@_a*n%Q1hC$YO!7*%or~0VK`EvW( z1D5Kw3tfes4K~AbdtXSum)hdBqo0*58DW~+ZvfkIB$jeVqMkkNR6r~+Jic-=5@E% z9`@L}h%q%dlG@HB)5Ko2>6sDE(KQ&VBZ#PeT0`Wn2*Ge0h@uxu@5%k-9}9YrvOfB8 z-{(JTJ(ofDi3!5Vf6LIFS%Z0hXRY2?s5YTHaqb?BZm)jvK-=3nI}kGXcRi|e-}*lx zKldN@*Ve=TZ<#4B3awwj(!KwfZW0U^PAI{efcSVgvTH`k zGO97Z#ibEmQ+YLo1zsANh5fW-o!6Kb#k4f5mY?GRB|=>cX=r?TQ)+2@6xYShe1kt6)S6&rP{o_6fFCLG)iX3Hm*g!Sxbz(5zdS9D{3~Tm0foxVwSTbY5j&bm9i4N_$P7h+v=C% z#wZLSh6wl_F4`p%r4K5_16|MirSj+?Y6WTH_5U%?pX)`jwet%h?AY#Up$w{Wn}3P-h5_Vg32V z)_*)WY_q5r&q}}q^iKiKiQ6tN2oG=axgbRJbVXO~(7ISZ`8yt-F+wrrY2o%UcQy;6 zymwLb-Fiw>N5eCn;}4czynjXZw&miK2v)z1OMK(;ZX{c&*tFbU(s*#ZdQ0<|pflhk zM{^Z)aFdr`r;QhQLmcaasu@dePp%o7s|h%HN!>2$?sNgjBJ}xSWQ^`D)@T^RkJt5? zs;dm-oUYYBq7rk0u)?(1*;v-*(O4rx=$fZ?xVsq$T-F}Z<|aK*rN{~pHL&?Ivwu;LE9zW_k%zb-UN=LF)VULQl9ZWc(qzKT|s|v^TKC0ypPuRoEy`bu{ z()UPpDBTD1Rss%5ktNB_cL%lT%OZcJdx8~nD;s(3F=S!zdazGxG#-k5hZ0>!R3JrJ z(8#cIxPiRY7OeHjw#0{nC-!!68yaYX!GKg3zsYri&M>6mJWTw(j_40>y3w24mknWX zUMyF)Uc92aVtLuS`04aKTBtUjIwY1Z??g1BsuGFKb+5leHYyClMG;JfFsAU%Dc)@< z*SkZH8I`x}O+R<8V9-oM!N_(2 z;^is8cWj`!VXHXk#z|p=&p8Dm;0C5g&9DZfRK^?;9|O*U4b6Bd!W0{p{8HKR3r(($ z^qDX5w(GLz6=5;jvYxBje3;e2fCT+AwkVW9BxJ84apl%kX4?<4c^`8lD6`TppPXTJ zEW7+@!GEwo8`aMz9Y0Ywp5IV6ae_#fmVE9cM$IaAsbedLIC3X0;34l&u8MJ?yJA84 zDh$|;JYJYi9oDS@_}MfENMSz;@o~k`NzmrImU){5u!~@9H3<$3{EqDt)_d_AkU1;$ zt&b#^k}=gVNADJ$+5FIf83~Wf!by#0jDIoEkTy%7Sni%PQCp$7p`O3?;2K}EY?=jZ zO!f|g?va2u)Y7Hp!%+vPQcrY@a)E~-x2`${aU_6!F`-10Px9o2M&V*(03jxufM?m0Favh*)NM zq>P|YVzLCdC@|<+P;Y(5xYzrCyl5bw2g@2&qdZ8e1r=Sf=8O5#vv0zxSQuHTtVnXz zFB^Y$xc4+tU-Y>}WwXKS*c>V#&_M64^qa&@2h$=LWKtirF*-aGaFkHH_KO{hoHQN? ztX%ifa0>BP+YPo>b+EtPr4JGfs)>Z+UG2dp2x~C|Z-$7OA8)prj%0rr6N(Bv@x1X? z%7>lJ*0^U2)9V|XsDU#&GG8f(80674MkUEFSqqL5woigTPvjwC@%KISdlcc|iYkGj zj4uMrZ{Wk`y9TkYOVXk?-X_wM3tjCo@~t?{uP$=O?P2Mny18djEsh}_gVTgk2fYz? zRyx5Do_>5LypFydiIVi;m`;HTwhom=4W5Pl=}6HL z1SB*mLAnJ3LI?DFQk-&U5N> zo_pUp?>XnW=W~zi57=4Ro4r|Wuk~BsQbX#shI$n+1jRa}Rf~INT+-N6N%1J8Vn*3= z%@RsP=S0|xvLkKo4Kw&4L1JvvPf&%|Z?=pTs`@=S>}o@AYzJzh>IHFt(ciuoxUa2I zDmS0#S`;O)w%lR4ESZ~RwFKWH`F#cRm6wBAb9XL{1=l7Yam=gt7Y#kXohoyNJCFfd z^G$-;J^pIDZP|vhzaG2aQAkP=QQ8S8EKA{wG1exfiR9!Z6}Vo-7*z^dwHMk~I%Kv| zK+7kJEDk+6oNPzW@DY7%C0a40-P}61b=r*KI|eh?8P(a!_|{=HE)WXuw}RzB-a0qt z*ow(Bx`wafVIwg6qEk^5$JPV|l@fvu%fD9l;I_fI>FM0QE$?pPaoa9#7$;>})!w%U z*!7jaEJizJT0bfwiTy8tDzdST}bT5PZr5LGYoqEvBtCZ%sBRx>+R*u za({GYYt2~13EiT7EN?uXsT*;k*5E9OW^%g~aW%sRsU;{Vx8KiUw&`Iu~1VnW_(AmsX zBp-8=6R~xzaRqBRB#up%3ph!<318Li#+7>vuuio#mELV&N`NF>yS(@37~z+jg7w77 z)fBqzurg}w#YMC4h4+6U@n`_;Eg=}My%TL!f-tkBPIjN;bPk^u|C5mFJ|}UE#?VJt z#jUmLi>c})+#OtA8xu2<;W6?9nH=0f)qs3 zI=e=qQigrz6>uOBtR!MvGM!NNfKH+Z_uN>{iUGvFrx@Qhs!}NjIdO{{d_hjiF~C!zxY&oXR-;O=J-VB{MXMMDC@Iy;U=9s#|2TMP?oEBWjc~gxFK}L^sDO?ER%1#bSDM!zul* ze)VxK(pzwvc73+mrfc2C?UN>-6QD&XblY95lV>Vj+xPQr;*Fr?2WdaEuPuGSCgBwl zrx!wsKAk_qtUe-S+Un<^s$s@%6K%KYJvD@9hWdl?iYZBDTsLo4z$Kz{;$yB^S?1tI zO+)QZZB!M}NRfOR^%12v%`(%X^}zwV#5 z8B*{~G|GO?Az+b*2{p6+6(J?_cBYTDWSafcI(2xkC6?nGYAU@~rbh$ODyJrWzgTwL z+v;@p>}&4Z)qk0aEqKD$^sC9*fu@@s$rm?G(<>de3!C;#r|3FiT9T)2g5TWyY~6Bg zXV09JTaoU63v4MbJ|}xs=#++Y1V@{cYS+Pb1xwu9e>r}UA|zFMx+yO$w=fygC#c>P z7=V1`xS;VJrC$`lp@)aA(f!W*Eyd*K<)`7w1)Eh&55L!seuky}Tx@(axqS#oK`15< zy+Z(G1GX}6@Bghnm@l2XnV@1){P-3x@nwu@xNAXbqL+V-D0)bW?{}_fy{U;hpwnTe z{|jC6`z=MQeGmHpcC>WdVB(*X3yQ%OmDT8iK%w2G0K4w%NwF|$-^OoH)iOFAZ;HOq z)27z19#GtkxXyN#S$ArC+i$*-+Oy9HS9B};g#fNhbY})jK=-9dW3VHI!=uZ@D0uyjn32W6pHD2T91Yj=>trb`Qln6e=l#vmBY=BlN zcq%}MTyfJSEj}6<@wC}6Tt=~nGaT}o({H&XhKJ1;b6+V71?YgUTS_4k?X!)RX@oxS zEOI?BER;m7KA7X-2YKPnE5&zY?~19-^Wu82LR|3`2Gm|U4ZUF3R?UgpU$}JQ&#no= zTN9Rn=oe(l?_36p`}F4M{$BGQW?`e~ob3SJ0xesP_h=;7H+Ihv~wogi;?2n;MhYnw&J*OCW%q6vUO@UCuWLHBD zMfqDy*o=PfIh9D?W4Nm0xo#jnE1!A`dAG#it1}Vru9hnmvJDMu3ed~9jN=TM8Y%91 zl$WGr+T*Mb9{}{M%nngsss6V5i1eV#d?mRoZhZyIipY0aS|gw13!`)~n0HV*@GN{8 zFfo0uMLfap9b%8HKY1HwuQS0$#i~&i2AJpli?#Hs9 zvTVryOf2oa)jM_H81e~BXO^dGHwa|t*w5sx=C8S%I*4)LI>4#_;~l4&A5LyQk($VR zOSHdUqQbhM!yA!}mcf%qAW6x>EkU}Z7JqcF=DwZeFqixoll-J412Nc2#4yIwE*=Gg zEgPQEkOCb$#hN3_al{7fCJ8~5s|*QOhr`(I2qfxeb)3$w2O|Wszl*CRaQ##04cSB;dB)nE*OXEx87Oz5?IakEb zy0LC+qDD*0omOM%*EysZSP%3aLV#AeG-}jB-`FFShg1&Z#^Rg5Rev87{_g3UJS&ln zkl85mTq{@0Vi`*X$GXAV<1(o}oPEkF)4*@NZpnr%k`IiU+ZV8#J{p7A1lOtfi6!;h?}Y zN)3ZDYzWSOS21LTm=GMqKsypIgTz#RId{@<`+2z`h%*=8DiL1G7qg!{JG z?MrM2*etjeB&HqeH*Ib?yM*C0rj?h#*z@ry>Ycnx`>i1*Hi8TO|7H>5=AhC^(j$H98*Y&!G#mNIr@yWcW$`3 zTO3Ml^xM^q#=CKfJj%X?Z%DTPBJ$*1^16I>Hikokskp5|A7GhAFP@G1lHAm|DF>GOf;4( zDB>uiK>qy72G80H&gNVc$kz?RsD7ekMAc$-$` zZl5oEFP{frsl_8yMB^qyc>3vIM_>63eDc;vO;?L43(7+|8uTyTFB;ym8hQt#GI<5{ z9p~deY0zwPC6uH=vF}t>3(KQ!JV7BizG2H6R9mf#GR7jtspncBG`Qux^HZy`)SecA zc2?`x1xJ?=>fVwkQ%h`)uy$x7ROclp?5Z7nl|=;DhsP>SNWswYuCVJ(?44st@$pLs z&BYR}tf0Lg6oC#)4`hvDVFO_oMVl(OEiHWrQ?$Y;lhWS2fe&NXK4=?8oT5Tkn8h^| zV;{R=1gZaZ#X`V`}Rq{|CAc%xiw=!sb8 zsT`KBM(tC90+c#mA4DNg4^5gA6tpb6B><~gE~gb_zj|-&{27~Ar~ix1mt?S%&A^I$l0t?=OO0koswPzA5l}OI zfiG6cq?}0QwVQIQ+eq+jx|`-OGaKy7N6z6u=exTsz-VYNHi`%QLJHoSH}yhPl4hBK zm`?EASI$)A2uWV`SjaOqeoxKHz3Hqs5cGK1g|z{eS?ZlzUMsHAVn2O@^s_5)Hck6N z8nU%YZh20DQB^2a1^v4NAaijA%$MQWm_ja&TlYQ^v+LE{;1r(3x}OSTsMxvcL}#Wo zI=`AhrTHY(Tk2qlU$O^7ikCWmkkYE33h|q6~kY?~L>~(Rc-;61DJHL2GqYna(Q{c%%Yv9|rI;Uv`RFZVB zW6P7H%2L^!O`$g`=QcMg^g!YT%xclXNV~)kV8CSL+}B}<(?atcKxkCi?>H!*Lwn9J zbzRA&le6N7H+_rU{h%kH7zmHls|WOGM(Y=u#6`pK3n<&Dsg>Gw znfVZ>`Ph^(^}!l*rdRc+aY3ln2WONr`2qLI8xOFj#oO-mjw)^Rh9rf+5E!i8qq#C) z2?A65h<2ntRg}g&k_I*r%Pu9WgP)N&vVwt@!@^&lg*WLB+=QiH=6EMEpc@^Q-0KB> zA5@KuiWP28)7#6guUOZEEojdV*f^bulTnH7FuBA)fyW6h>vbUND$MEU7r?Qw93pEo zPuJKzSfebnbXU*bA_WmkPt(f%w&aqJ>Qx>l-kG8^;T_)aeGex>6V>9R{C2v#G&-P` zcrXWfbUYd>wzk~Z2c@$X-0Zg$v7z@DuX&pv)ZhW5^OP@j>XVq(ZP%KM+v}$2l=52m zN@Z%?#I}#v0qY6PXo<6`Bn>Uu)MDCvO)Hw*xQ1>QWy&%mVSS+#B|)Jh^M^m=9imxX zwo3H*_E`zZ5!%O%7?G4#qMi-j)U?>qQR;-cXzDAY$A24Jw`^pd;|n9^1`!tY&ut}D zb+WxbJn*rFDP5l1RlyjPis<+s3FQdyrG;7+L1EQawLquS(r`fjY+m0))Z?Cau@O2A zb4b50ujfwc+2x+?Vh2I&Qegz*XOe9MR)P3t>E7RQmikY(YT;lpcwBHJg|{3H zfrVsX5CFgBEjw~clDL6DUc=C}o$A5y{QC@5@Utmr6`ik>VEMZ76`+o-6tNhRRj{~W zec1vgmAkmAe+ww|izu4n3}7uAe#_S@Q-AML?EK+!Y(Ip%LVk!}Iyb_BTE>w#1hyvB z1aZvYh6xUhMVE3i0Up_@1`O%?tT_t->n25A$l_d#{tKSu zNL<-aYfG6CRXHNeA(7U5C#t#o>G8Zfy)YU1M-yrjR77h5+10mWu|0vFAUi&66hZ13 z;mGqmj}DmzI(i9|ya%aaPs0EWe3DMfMq0mfeRwDyMo|=!wSVZmxu&?4)1$BX;VTYKX0`Yu9XVzaap>ws z`I^IN5qb^sM1OP`@_inl>_aPSp~plNELo{pd+RC%J3yz|WVY9|z4=^BzQ^_8ZosgEI!kkl6Rsw3sYFc<}XL&F2{8A8Ptae>~m40Y-6h{|#nA|FnRweXWL8 zL?JP7@rMKY4}19IMi&9c-hKbc!NZj_{BS`3pXGqA|3}sTV*`lP5P3cs=;8v?zuoue z>Dqy(dXUAY+`nuL!UE+Yv}x}p-zIB=YdCJ9)uI{jJ;8{o#EiZrrJp@mg%JIgcZ*^uR)(Z|NEwcxc6$j^ zY;XwKq1vi>y5yFaW1O*`yL21`BCtes6RnKrcVbk9W?Qy@7Zyf6+_X68;QoX^;dow5 zUaHe%do;$lvVSXcnGI76vR{Q+_O#;*DCDPn@t>8lZO+=vO<_ZZRP7%w;>Pb{f9E20 z_4IomNY|qAw%E`rY9t(fvubS>>7M-z#;3o6ra-OE)_;5fx-*NycZ_&rzx9I39cx`z_@7MoN z$onNd%mTfIBjx9?&Xc%_MLVy1HM^fF34OL*!eTwvIfhvz;E~1Mfx~3^_gz#+L9x-! zjjg;-;_)Lymo`7hLl%6jO6{Suzt@tY(s4cAZc0wF3G!@vfOeO$QKK`xA4Xq=jU9GV zV)Zs88pm41Osuvjn)Wu?OKU9YKD9;olgKsA?Qu(NhSL;KQ?@j8{&nP)DuMbnQR#=g zcO)#1s8IFu43j!NMKA&ExvCXOCO-yisdW4L;*1!9Wd~pl+@$?tf{{6kU1xOf#7m9_ zl%2&``=?U^ByC~BD4nV<(xSVTI1G}X&eNIOavd{X6fx={WPFthQk9At;j85BLIjo{ zQ@5AceDK=pCQRU&$RoZg5qAk&155C?p7frY*?v5Lv%SRGkb+KBM=U+>qQ&w#s8NHf z^=~=P#W1X3?R(uI;Qk4J$C)>WYn<3c9^CWzS43KdOjpkE~)D31Fd}-iMUt zwMo>?^kqkA!W|8$P+>qrn_CO~Vb&@B(F z#-6AfxllW*FZ)YMd~hefo8L~nH2!7FtIX1OZ>JN34J3@5r%mhF%RnW<^fzUc*8Sx% z&NB4xpLp&_#RuyeAIaso1ANd|Tw3t)Y5bz>>AxrRB_xfV$1=KMR+wz03jffnXl2OW zNa`M;N-{}t90BRHJuUlq@0^!KMDkm}YME7=BKHcmx6gEzH5p`ai{lT_GFlhX%5bqc zB>xx`XQF+r-VzpVVo=eRwMm=bfI3b&D=ks(2-membi^?)(=-G5lEts&{?^~wtkvmd zC1q1&4-_v%`Z$Kle48hFl)d;lmN$wUizB*V(eYx8s#cC``y_5{rpTqY+6rxii%UGrAzBK-DD>O(2pB3>-CHYr12 zSBu$Z2`{B)56-^eo2)g2c_s-bPK4wKWON@cfeCJ(I{!HEm2vx^Uw7}()G7-BGG`@B z$%re2`35*r3|=~15Gg8bm@k$Y?+HeBF49A4I#QC(-o@CZcaKEvCh_Vc@izv?(+#30 zu*p_EjGPh`!T#X@sa~P>f`HttxN1Q=QcT}OnStxPACd(mc^ywg3pWVN*;>kvB)EdE zW>h7unx9Mg=xNu21p0BE_*238{p0Jv1UKW~xr_i`@9q98KEl0g|B8>W@6x~GBOLr! ze1w+*KQ8?XZR1BV{R6w@N0azRCeQ!lP2w~UwlF|aYGtR``djSa-(Wy-UT^W(GQ{M8Afxp*vw|R#=hNk3uFj5j3AZ?+ zq!Ethjg5`3>D-o&-K7n{HqDAGR-C;gFf6y%%KWVD|fw$!?LnscQm+$0XN7&1+bsm;Ik%-I6O|IcUj;j=nE6_L)m}bxM;oH#gi0zgB z=~}MDMQ5Ys&B(l|A>0zhIr+Uc1a{D@bhQ@GvzY48h-j(C1#O~$ zXN|HQ&_p+c;&7q)BpkmbvFqocSdl!z({THJ4SeC+Zx>V$SsO)xs-~f?S#pyx7a)S~ zwZ!`ns$Vy+V;55dF#5;O(omYiK#?4ve;EpsRKKjBN*aAb$_S|qS<#H=J&%bSdj1*( zKdbq$m%tQscnrUi=r~2+lCRj>duPTm)H!TEEB6w^I5wJUD=OK#>{A~8JC_pN$oGYwvuMSFplebJ_jfz`jc41btByx2+ zhe>Q{dFPg$^EgL|BXucwV9G$vy5cdlbw<|?eYE-#lcG3(OLgCJ9QM=W9j zSan&S-yn2UOft|lCF=SLfGj#Vfa2@mV4r;h@d-@E0o1D5u(j~wv+V~He%Gc;B;~O4 zTL78qbv!w<-l2@nYML4p*IRQ|kq(v?N1@u{4Ig6(r6`^D8IvQ+>h=EiC<%yhH2?g;eA;XY<$SKgJtu|Q5CGsd19~^e z-|xD%d#TBvTjPkGww>@ttO#j5$!ycK9YK?{#RYj5?D|ONEv-~%ZccdBWcE#zcpEXB z617h;4nouv&1V$gi;K`e-eLP7D9l^~<|IGjB|C@?&p7i8Yg48IbVYeM3Q6ufvWv?z zWP@&1RrD{D%KgQv+?<4A)@p9ScImfd8}rd+wPpFdNl&3&wo*bA2p}&BfLmsJhw1gR+0&EnLW(YngH6dimqycNWKw()iIBe)NTZ&&Z%JN+mxHdu%xU z1ojt}^WR!C{97+#;PYv{m>ZUF_u!Ogb86)-9Qb0llSFGA*_G~i2XRT`#+&9fH21Ol zo+@@RA3jJWrMIIOD&ehhacJ^a?o}=ZxKt$4Cfo1J3*Eq)Iev$oFfp+#Vi58wWf)f8 zK9$!rd#3rbo)Gk^1(OH4bdzh}8N*cY4;h<_5hIZ22%R`IEZTWm{AIH=5gq+W;aPiM zYVwD+qp8&?=Esqd9Kh}GTzQ@U@TNbM_r&8hU>I(u`s8E-NkwF(4lD?kkn$c4#*fCn z`%Ub|_w!uFH~I!K0BBEl+ZaMCZd36?SRuUfVs;ww>rrhZ4Ws56+NnvHCx^!-8})SO z<>^aJ4Jt>>tS~eilp#u>JMek3Q8|bs);al&W98V>{tvhQ`~KRuhoDK&3n2?m10Q{E z+`YW#G9<;jRw>SyKr`raU%5En{|iv|;m@3>`%~@X7=mS;v4kb&$KVR{@F-6gZ#|tU zr{kWuT|yaHwsZd8slX+^hr-RPbDpnv;806xnMHy1GMgFK#E|OG2?6s2XsdsZNAAQd~L6SXsdQ&{+}li;!{~H*ZIv_?!Ym8J8z_)^U&_ib3w;ywl<^ z;5EmoIzc^wBgT3qN!Cqq-uv;d3iA;R`P?W2n7#J$w{u_0IsS%%_Te>n+jDCoR>%QH zb4f4w)Lxi>dCVuPh2Wy9(T0jeF4D}V3=XewW`nk-57;xk1&4^e?|u@os$v0P^5XWoKEMlrrR}OoWCs=t(>3u(04c{x60qWLkC#f)bmYIklaUG3 zRWDtu2MhSsi~3MCSr||2WJy26{kzvFUVIAZNoOEzsJw=x4vwUxk@E_Fj}jMsE$Q!@QPyE@&$^6C4Ew$x`>vm{8XvwDX0@n)q+hFc643_?eP6SS|LGmueFTtbc|- z7d~KO-nnZcl|>n)EvC98{fEbaWE*xg)cFSst`*n0N6GN=6Q zN6)tVrD>>V&&g}?M2Xmf+1JbxJxpF3$Dk7^9I@sf zXtaNLlNhHrCq=TtrWS^WXgPY0Zb()qKd5vpc`n3%V33TIAv7W3+S;4fiaXsL;tG@9 zwkqV4yL_VAs395vS@Q(c_<~AZbOO zv#N#zWfzQ(+7%dAh0UVl>%}LHm4RSlUdtwo_POu%IO@e)m-{Ps%+z~LxX~LUupnP# z-sT3o8fQ-$+1hWv7+mWGcF_SDN$H=hp;I1{GC50kuN5QZxn;Z`SW=>r!@@eolUa{% zn43zA&^K{Sa|1ld2| z3du5B0(=_kX2(o~jEtHho<{kwr$CMjbD_G0(Z;1UagA91_+n=$l#xUm>T)xLB=Lsf z0m^*-HwGP`3l>6RhOI)tXcsRYBeEb2Rz@p_!QkuxtLg0Mq9*@pH38Dg2EpaLw^o^P z3{x9?s(2iUV}!x*UZ(g=NIL3AHM5fIP82pG^Be+>oMXnBTxyqXY@$m7B=JQx&+9On ztWl|a5+@KtuRzWdJZ_OMS$42C(dWFv#f=4Zd)E<23o9LZ*63b5q zs9wV(lhHQBieI}KS zAKfgqY>_y1+Qhtd($;41l_v*{2PY@D)q9arCd&j8b#AT=`|=mQN~;U&L-nnjQIb4Z zNtJ>MNm8e%T0|6R6pSCLs#tlfZ6<#_o18{Uj=>#Ct!u(*+6~lUzD^m^*VGPiaHW4v zATv@gF@SwG;;tdb$dt5i^OvcMMY0crPFgIqjj=g1$7kQFvv_*k{>bDAyIb$9hhDh+ zm&_wSh5d2Xp+7P&o%?a=k7D}KB>pG%9DUIisU$d}QVSsS=XYLuz3=E)-n+R(e#jH$ zb(@$ri7hTuA2Fnp*f5x5J+E+O#J!P+SwoOK_s(%jrd%fC+D6r{o?Ci-WuF*cWriS& zlyH1x7X>b7434+F`Kj|UnKEi4#fFUzgR3wFICE$2H-QydJ<#!rDQRhlgz5)a_n>4D z3XvJ|lp`4VB3e*rKGEK8rY{{L>K&zjkVh@YxOhR@{A;=xt1ozp(iGyra9Z${jp{fu zyYD_E;XPct=9z_EJi)2Bi(iyL_zYgoT}0RQH zx0Jc=9>w+p=GDduYShA?S(O^au$K)vNZ*p}9OPMDj_O=@|C;`*rx_aPxB*_Jb*}t^Ets;s zv_JjQ-+Rt-=*dx5^=Sb@eoP|XE$WKa&8|G0OouCdxpK)6l_dN?xs_*38li1%)uEFr zKO_cgAADXEJ~W9j2h`#DvkM;-A}d}6Vn0*QTH$F{-EiP+*74gXe{FtQ_@JhQp4vVc zbL-7+Zowu6t84Zf=YLB;zC^jq@flITQeK5mrZE8|$=|tPp4CVHH+0#*MnvrYKeK;& zxHKtbrfAK}R|LY+lbj}*TyM2kiBObY(r!P!rN-?GYk(SX;e+J_PvdIHWoh-kpv5Gb z6|`*Qm}4VncE#69s!OQ)tT9%aXdznfuV5{K&-C!42U|g@a0Jy@(X^34Z;r3PjnMJC z?Ks%j6^R7g)7z`89W$%qz81PBB;r8F1VfPSUa=UywdR%OxjLz?D`%QYg8IYJsR$I$8HqF^WYx&0mw!TIr zKIgT|#J-(;d;Y2%$<>vXh=5qjN4!uQE)36~L)qVni{b3xa?;^=@4LmKkr6D0jQ)U8 zr;sOf;soHjs=Jn6qeX{g$nRXTfd)gDPOJXT^@!t!ov%!LoMy%cf5RLZZtZu!9NA(} zJKX49F&Y^0z~5=|qYE*>7igVk(_nM9ZoFpZC6K3jy zhid1GKCU1YD|eO+U!-hZPLiGa+Os)Rkg=8iuJ&llTv(|du>x~Syj0`?Sm>gj{p8|G zds}$>bd~B**%k{|7e;<~wDH4%_`+9()SCj9@5Dr=TQ@awyK(BvThx{1t+lTfj;&AE zzs;(i-K(Q>Z#-R!ZK+Fn)-&Gv922-2381GOzat&1FQcEjCbQtUQpthM(TGim2Z3L( z4d(%Any*Ri+8#uIIg&inT8A}RB3M%3DZQJPc$J~tKxfYoCQZKF4LZqp=Q{h)4tu0- zWjiMP?#k`}b`h%H>uvt?vq3kI!06jNyOh?+01KJV7s3HrAr-%Kz1SNtchGZsvIqNS zRL;Yk=T@?HZSZS1HId%)c_35lxVPv{#0QEOh8zUjwRrP`(4ynWtT z^%}=GdlB$VI!VjQ6hRa69<+OmBt^7Wp^2WOQ=c?KYYr4Pl26B7gZ155ZemKCsl45q zZW$cxuR`&yIA4tqGIWyLk(<3|rMZ-lLwxAwf0Zyd^9pC0mT#q+iylxBL@2_9F;$7z zZv}@_^UzcwX^5Wn>(8T}gtPfbM)6XlZ^WqNw4OL)D-8#A`ZlTOdc+v#3>Cpi8H3UN zR$u`jg9<@_fdW{0F+SZ2%hlqp0K5;|8iSoJ8*}aPVh!Bojup%!lkyXe5{$I*hYcwK zoea!{kWBid?>H!c-gf6Gd+w5zrsA^(wovc*#$e28Re0ZxXN38b50v-8*~x|xl;tXv zO@?=b{ba~Xe(0Z5eEX|vZij(yzJu;{pYFVI`*F>WGWdVL9W;A&gC@!iq=jbD_x@$? z`RmET_wW7|DCl2Y^H$AFa^m)}yU2xw+cNccV~t8o^n9#ejT)Vee=5mzAe0$GK``2O zyuMM_y3@2)?XGb06F6EQ{Yp01ruS)?A+{(L6ND^-4A^?r zDd`Gasp3Mu7Ps;Oc{&&5n3~eHsBReQ^o0b`&rnqIEMfA?8Jgt1Q&BKlMW&DJLq(xe z^O2{rg;D&-PplcU$6cODz0124go;-=%--LSzHj!|Pk@V_&%Ny!+CLMeF>**GF`Xwe z04#Zh5s;IFcT$|jlkO-08NxRAfK?I|&T2QN)cNgmFxlBa2s@nKi8bHPTO7ksR3*Q?{)j zAo8eB@Hc0mdax(aV+vX0G?U})I~P(ZhMGQXeoTg^wBU)ri(^fG&>T_>@?1&)McO6# z)jOmXnT{r~-=#_S&#lutPH)D8ADQU#8Gt3g{)c-EX(&p5{LpJE;_94u0zGR-qczc< z6gVa^s3nm#6z&zQZ7V0ok)_Fcfb5#YipS07b_DWTKYSX#$yprmZ>WpJ(mJ){ON-J( z;lSHOGBQ;$LJFtR$)5BwgH{)MhLR$x1r<^D`{rJLio&xLoF#IS{Aza4p~a>SDy4+! zVyd3UBo2fCC_de7Ev)uVsaFninD45_Jw2L?L?02gV}-X^!i??F#s^etM4mvH4k>p& zIWWK)d!ej1A(uYQLpXHyMuMlk33r5+#-T+!MD6vJY(r{MRh1jGhEmhKRd-Zgf)yE7 zB@eUP6LQeLzG>^hmH^9idd|4OFF5j}Htp@v{$tBr;XiAdfjOcns~P6;eJ>hRDi%Cm zZ{}E^?fUk$vlJ6RQ+BUxCs4-eH8b6(OEt5k%S)rOf=h1Qa)X|4!ZGY(8!8gh!v~C3 zw7QV82aQHC@9RhI{fpl5Uv+r$@gC1Nqm$3yy&0WUzkBJxwST(NpV}e%r?dY!;FeN< zt0Y5vK7IU@QafZPEzLvDeTmn^d^$U6cHqJ^r)vhRmVX+5)34O>9)D$O$qUL9yI^v;hBZhgX0zh52-^}AT? z)#>q5lXbi^?DmuUUA9xm<+B#XG+tgp28?f>Pze2!zIv`P`z0DjtEYnb}_P2+hH>>bK^mLyU5nVfju)J3ZGqm|>4m-!z z4g>vSdpxd8GA&ik`goH+QU(M*c(yA)6|o16pQ4g-5LO{ zDU@hKJ+IdU%UjJhOZw1AaecJJH~ZRq7mXxLjtO&H_bUjfA8&9J<5hS=X}k`T2tZ_a!M=|E#bzHy z??lqoN;zxRyvX(&DYQ&la-iVs}gdE16q<(l;!kVq|KLm%=JHG2?Jpup&F*wy6TI^A99vE5aNSSE$NI{b|K7UxYx@Ib;ZOmO3)tS8J;ls2;ZDJwzL+$B%^n$9C5Ck8nK>d z8$zl1#Mwh#`8aGlqzq%d@>Joh@X&SJ59RvPRz?tHM*8k(Y*;sR%O_>UUO2lP%BA|M z5x(@+Bw_s7b8m_3?u5qvXa@CdDj(U(FsZhH!r zYbLCT$mz&(7Rm@x@q6Djq(Wjj9i5>Zu`hV(n?L~p+qbcp>!!PLzEAtC5lmG8cISFc z1XC%!btqqe?yoYsB>DiDuJd#Agcom%rP>Sg#;Y&GNvgLZI2y!W%fGD1%(ICuwwD*F zICK^rmu4md2$Ms~c}ykzjG>vC*ik^qp6p%1l=;t1*VBkKO=UXUk8D2Z1YciMP~z73 za-pNc7IAmYzt%V8sL$5g*h&5+47X+#Ars>8S~d5X72>Q3^JC_2RWZ4!2894BVc>X@ zBuNfZ((?2WGt!th8zfvov}mYt7uFYR>#C+bIYKN#YM9cIa4C)xoA!dIufIjw*8NYA zvS(Iiuc18?>M#%86BIo&i06_Twz#dnJ)J}e>7H`~89E*Ay3=R8XHr`FB+?g63O5nm z=53Q=LNe=z+UPhqWwD%^`?R{AG+2G5as$Q~9JXlA*n#B}5)%T>rCUhlxWM%`5We!G zH7l}rkJ{|M8YJPMo1{Hkte|;eR++Ie7{{=cOXlf=Y*3{OGdNX45bd;JiI=AH?X=z| zk&10r;m-Wv13%BoO-2Hyec7#L2-!d%LI%98aV4AVf_Iksh`LfNfvt@rmDLpZF|yu~ z5eJD4=ZC|dm2Olx*myhFCa7Fb;cHG-8-;LmjsZ$r2gV51=9Lx4L|FYC%s1g8nikjJ zPfsN)_Er(9MiZ)H?}l(`4PO*v!CeGJ+=6Tz-9lDd5E@6IK_(ETb>MHUTUtY{3-os- zcN+qh*SndK2*DSpoBT4I?2eT88XO>7gN{zPoR;}I9-y^cl_Wag^z|JWAGx}D%WZ8> zD4o|e{j!0zwN3KXd0K-w6Blyl3aAm70N ziLOHil`nrB{3wLKZV759x5f72$`0056McK=epk4-{;;_CqsjkGv&MfTFLL@grpTUD zx1(ph$ievj)*TR@*ypO2k(Ev3Y)2btwax2T{w0&M9nC!>OIR}cBlFt1Unc)J>*ODq zmtOw3^hYuMXcGSud(O5O#52kA`d!9+-G=^~KPN}dbx27n{@VC&We%p)v}9SOdHpbZ zQNTI~w*TDe^KIh2sy0qcsc@;ZO-gTTO?$#8gIUgyc7TYyNs84-GwL|?DYcqGcl-{2 z#pClo|MW7`Y|ZKe*wRwUB}PUeS+B#@(^834mx~5kc7c#=Vf6P=@%ZzRHjzY3R|I03 zLEp#O9Qj2*Ph{RXKeE7UJv&oOFtk$4lXO=;KW^##W@&EMt=n+-vmsmMzMezaH-y9O zt&K?q2p|VxYeZUun(xYPSe($mA8#Ai+Y8}_p;QbMhL~Ov1suR*rR7D7)NqdpVm>-N zr0lAjv)&UVTl~95_UE7OeMvSlilb^#Kv1MSZh#{|efkpT(f-~ExSgo=X#8oJI9T9S zPHNYvk;S#vVG2EWk(8mSd{2za+0r=(xD4;67F3S*?{#u zOIbo)yX>wF>q-(^))?ykxDL)8mlPC$)G+U6M8^KsSG-IOp(I7zV?I30 z)3iEl`Thb=qa2|BV)Jii%nNrjQ|@Q{SzNG`ue*)P;xUT}fo)T&b^?N-a+=RkBsCaj zI1&;LAl*4=Si?9r43OMf6VcQ@nVYwHLA{h&`o1ByySRo#L9r4`G0V^qj<}+&AdmZ? ze)%tj`FI~iMLkJNZ5tAD?c^CmpL|MKNLq_KKxRHCl7GZrR@vep@l=RJc%4|dO9jJG z=xodTTxp6KAkhK3l9pWrlX#Xc+fpj4+vR_UNnyGepe=reVZM<+M10dPHX`ZI=$n({KxXM+lG zv`e8ENl0s)u@(9yy7_tX`|)>)bR(FB-3~C>=l!mH#vnUH(%%Rmy<9ESua^_Dg*Hz1 z=J>mg+Z2RuDqBLJ&vkur(TC~h=Cfwm&#Tb!bs>IG=$19+Y4t+zd|}~J_gP01B{K^` zG*)#+Tfo&c0c9&XAkXVaM^BpnT&MJ@@Ta6{73b|d;Rn_eT?OCH>~|+-V_v^IyLe~E zNvx*JXD0_^krm=cU9voHpD_JC6=mG-Y03KO1Cc6yEs+UkDm! zkAznUJkicU*?Zok1WP+@ypSNi3Q{5j+Zlveiefk(t0+O?8l9>NQM)jgmrU)SUo}e{ zg1OlvJ*FGa<|Fh9QK=az9RboAkL{(3?#LD;95KQ_$Scfto1H%=QbbP9x=>8(9u8ph zeL?qe@QDE->*vcRUU|%&pTrd+74+?zsnk4KvXJK1DPl;zkYtSrdLg%Hv~g~q;8Ya7 zh6xmj`~cS%jf9<_o7@^z6HW3_99UbUOYZgZr=oWz(M5a&W+a@5n=rV2>B0qacu=+uNSMVm|cC_pW$7W+Sx}o*2t)V69d>?IW1SO{sSMW4~Pe z=)VIm9QpvwVJIZ)N)nfh%r|L*Me+O(6ze*_t8~Y30vOaXQ97|0Ir{?gz^X$m*|-Li zeARU%snepl+|b^CB4aW9lE9N+mv|9gdvn&;VG05^(Fc+lp!nL*3vi?CVWy^5nK^*5 zca%N4827m|r&Lx2Va(8Jk z=*BT&BneQLFd^_74*k$fj4mc~qZ#gQP)vAvGRamrGkKav9zZA-Z+3qEjA)TqcK>l& z?mOh$X<+++WKnf_II{xt^yPOc zx3?rbC6%jRq?)HQYXTT*Ct^!G5Xr?(u7!3Lr$~%i`{B4rC*eS0`kc?FQi+D3C%P}) z;A-)`Ru=IS=Ns#q#HSv->O}a!XpiamEue7hEN+>85=9fVc|i>~t+f2q#|fBfG?A`{c2OrkEC2#6tt$EK zT(@q-!)iY=G$l!RTXGBA>F1#PynLI6;5AO<{r?zoht`d$)M@0+|IVd8_J{t`->3Hf zU3WRWZY(7-qZ}apW;=J==FX#C0sUW*R1sFq5>j?C>K^BB?Yp4T6<#Y1E}B4YDgVy( z`J4O2nWMjR;mfUF{xV(nN;Uy?vS`+1f^EtroA&KdmSUg#ADQR4vOIVALdz}xlKJwd zus_Z+`Xkfo-j7Rv6w{9;@uTPb^(bNcOT19j1tLgVq=)Zls_&f7| E0b-BhzW@LL literal 0 HcmV?d00001 diff --git a/doc/rfc/image/web-library/queue-landing.jpg b/doc/rfc/image/web-library/queue-landing.jpg new file mode 100644 index 0000000000000000000000000000000000000000..abccf41f3c04a65e704e1ebb7502d44bfc43e8bf GIT binary patch literal 73706 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 a-FRpF%Ecj!S;qNCPsi39CmL1%5c~rZ)E+MY literal 0 HcmV?d00001 diff --git a/doc/rfc/image/web-library/request-summary.jpg b/doc/rfc/image/web-library/request-summary.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9255f009fd18f4c2d9915a459b0e2db81d3caf24 GIT binary patch literal 55192 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 D|3V@t literal 0 HcmV?d00001 diff --git a/doc/rfc/web-library.md b/doc/rfc/web-library.md index 3cda79bbb..26b62dae1 100644 --- a/doc/rfc/web-library.md +++ b/doc/rfc/web-library.md @@ -8,6 +8,69 @@ The package resembles `submitqueue/client/`, while the host resembles service wi Phase one is read-only: request summary, history, and queue receipt list ([status/list](submitqueue/status-list-api.md), [history](submitqueue/history-api.md)). Mutations require a separate authorization and audit design. +## URL reference + +The entry point lists the queues configured by the host, with each queue linking to its landing page. The queue is the top-level navigation context. Singular resource segments identify what the user is opening; the ID remains a value supplied by the gateway, not a string the UI interprets. The reference host currently serves only `demo-queue`, so its queue list initially has one entry. + +| Resource or view | Route | Example | Availability | +|---|---|---|---| +| Queue directory | `/` | `/` lists configured queues, including a link to `/demo-queue` | Reference host | +| Queue landing and request list | `/` | `/demo-queue` | Reference host | +| Request detail | `//request/` | `/demo-queue/request/10` | Reference host | +| Request history tab | `//request/?view=history` | `/demo-queue/request/10?view=history` | Reference host | +| Batch detail | `//batch/` | `/demo-queue/batch/4` | Deferred; requires a batch read contract | +| GitHub logical change | `//change/github////pull/` | `/demo-queue/change/github/github.com/uber/submitqueue/pull/123` | Demo receipt-window scan; unbounded lookup deferred | +| Phabricator logical change | `//change/phab//D` | `/demo-queue/change/phab/phabricator.example.com/D12345` | Demo receipt-window scan; unbounded lookup deferred | + +The queue directory replaces the automatic redirect to `demo-queue`. Queue discovery belongs to the host's configured queue registry; the directory does not infer queue names from requests or require a new gateway discovery API. + +The request and batch examples follow [scoped sequential resource IDs](scoped-resource-ids.md): `"10"` and `"4"` are stored string IDs, and the route supplies their queue and resource context. The UI passes each ID unchanged to the gateway. The mockups below retain earlier illustrative slash-containing IDs; those labels do not override the scoped-ID contract. + +Summary is the default request view. A `view=history` parameter makes the History tab shareable without adding a reserved suffix to the request ID. List bounds and pagination remain query state, for example `/demo-queue?from=1791208800000&to=1791295200000&page=`; the host URL-escapes the token, and the bounds are epoch milliseconds for the fixed receipt window. + +### Readable change links + +Omit the SHA/diff ID for submissions across versions; include it for submissions of one exact version. + +```text +/demo-queue/change/github/github.com/uber/submitqueue/pull/123 +/demo-queue/change/github/github.com/uber/submitqueue/pull/123/ +/demo-queue/change/phab/phabricator.example.com/D12345 +/demo-queue/change/phab/phabricator.example.com/D12345/67890 +``` + +Exact-version URLs mirror the [change URI](change-uri.md): replace `://` with `//change//`, preserving the authority and encoded path. Do not insert `commit` or `diff` segments. + +The host resolves change identities; React components do not parse URIs. Exact-version pages use the gateway's exact-URI lookups. Across-version demo pages scan an explicit receipt window; unbounded lookup and git routes remain deferred. + +## Reference UX + +Design mockups with illustrative data; the implementation displays gateway change URIs rather than placeholder titles. + +### Queue landing page + +![Queue landing mockup showing a newest-first request table, status badges, displayed-page search, receipt window, and live refresh state.](image/web-library/queue-landing.jpg) + +Newest-first request table with displayed-page search, status, receipt times, and refresh controls. + +### Request summary + +![Request summary mockup showing an opaque request ID, current status, copy controls, Summary and History tabs, request facts, changes, and expandable metadata.](image/web-library/request-summary.jpg) + +Request identity and current status, with copy controls, changes, and expandable metadata. + +### Request history + +![Request history mockup showing timestamped lifecycle and build events, an event-type filter, and expanded build metadata.](image/web-library/event-history.jpg) + +Chronological lifecycle and build events with type filters, errors, and expandable metadata. + +### Change submission history + +![Change submission history mockup showing multiple SubmitQueue requests for GitHub PR 123 across two pinned versions, with receipt times, statuses, and a displayed-version filter.](image/web-library/change-submission-history.jpg) + +Submissions for a PR or revision, with version selection and separate status/history links for each request. + ## Host/library boundary | Library | Host | @@ -18,7 +81,7 @@ Phase one is read-only: request summary, history, and queue receipt list ([statu The host configures the queues it serves and selects each generated client with `(queue) => client`. It builds those clients with `@connectrpc/connect-node` `createGrpcTransport` over HTTP/2: TLS by default, plaintext h2c only as an explicit local option. It installs the library's tracing interceptor while constructing the transport. The gateway stays reachable only by trusted hosts. -Components render serializable props and do not fetch. Sessions, gateway clients, and protobuf messages stay on the server. Server helpers call `connection()` before gateway I/O, host routes that call them are dynamically rendered, and neither side caches gateway results. +Components render serializable props and do not fetch. Sessions, gateway clients, and protobuf messages stay on the server. The library does not depend on Next.js: host routes call `connection()` before gateway I/O, render dynamically, and do not cache gateway results. The host supplies a refresh callback that completes only when its framework has finished refreshing the view. `WebPaths` selects queue-scoped internal links. A queue landing page and request list live at `/` and a detail page at `//request/`. The `request` segment leaves room for other queue-scoped resources while the full request ID remains human-readable and opaque to the UI; the host's catch-all route only reassembles its URL path segments before passing it unchanged to the gateway. Phase one renders change URIs and build metadata as text; trusted external-link mapping and typed build URLs are deferred. @@ -37,7 +100,7 @@ web/ └── service/submitqueue/ # reference host ``` -Generated TypeScript is committed beside the Go stubs. Gateway stubs and the base protos they import share one package, so the imports stay valid after publish. The library ships ESM at the root, `./server`, and `./testing`. The root preserves `'use client'` and reaches no `server-only` or Node-only code. React, Next, Connect, and Protobuf-ES are peers. Shared UI waits until a second domain needs it. +Generated TypeScript is committed beside the Go stubs. Gateway stubs and the base protos they import share one package, so the imports stay valid after publish. The library ships ESM at the root, `./server`, and `./testing`. The root preserves `'use client'` and reaches no `server-only` or Node-only code. React, Connect, and Protobuf-ES are peers; Next.js is a dependency of the reference host only. Shared UI waits until a second domain needs it. ## Shipped compatibility contracts diff --git a/tool/linter/binaryfile/main.go b/tool/linter/binaryfile/main.go index ec5fe3ad5..89939b554 100644 --- a/tool/linter/binaryfile/main.go +++ b/tool/linter/binaryfile/main.go @@ -44,12 +44,14 @@ import ( // text header an executable format might begin with. const sniffLen = 8000 -// allowed lists tracked paths that are legitimately binary, relative to the -// repository root. It is empty because nothing in the repository is: the tree -// is source, schemas, and generated Go. An entry belongs here only when a -// binary genuinely has to be versioned — a test fixture that cannot be built, -// or an image a document renders — never to silence a stray build artifact. -var allowed = map[string]bool{} +// Only explicitly versioned document images and non-buildable fixtures are +// exempt; generated binaries and stray build outputs remain violations. +var allowed = map[string]bool{ + "doc/rfc/image/web-library/change-submission-history.jpg": true, + "doc/rfc/image/web-library/event-history.jpg": true, + "doc/rfc/image/web-library/queue-landing.jpg": true, + "doc/rfc/image/web-library/request-summary.jpg": true, +} // violation is one tracked file that is binary. type violation struct { From 1421aa9cc98bb9d5b7b7449603a6061a9a7ecbd5 Mon Sep 17 00:00:00 2001 From: Preetam Dwivedi Date: Mon, 5 Oct 2026 14:05:24 -0700 Subject: [PATCH 8/8] docs(web): describe rolling views and clean change links ## Summary ### Why? The URL reference should reflect seamless refresh behavior rather than timestamp-pinned list navigation. ### What? Document clean rolling-window URLs, opaque pagination snapshots, and git change navigation with fake-provider hints kept out of the browser URL. ## Test Plan Passed git diff --check and the repository pre-commit formatting, lint, tidy, and Gazelle checks before splitting the commits. --- doc/rfc/web-library.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/rfc/web-library.md b/doc/rfc/web-library.md index 26b62dae1..444ccd9a5 100644 --- a/doc/rfc/web-library.md +++ b/doc/rfc/web-library.md @@ -26,7 +26,7 @@ The queue directory replaces the automatic redirect to `demo-queue`. Queue disco The request and batch examples follow [scoped sequential resource IDs](scoped-resource-ids.md): `"10"` and `"4"` are stored string IDs, and the route supplies their queue and resource context. The UI passes each ID unchanged to the gateway. The mockups below retain earlier illustrative slash-containing IDs; those labels do not override the scoped-ID contract. -Summary is the default request view. A `view=history` parameter makes the History tab shareable without adding a reserved suffix to the request ID. List bounds and pagination remain query state, for example `/demo-queue?from=1791208800000&to=1791295200000&page=`; the host URL-escapes the token, and the bounds are epoch milliseconds for the fixed receipt window. +Summary is the default request view; `?view=history` makes History shareable. Queue URLs stay clean: `/demo-queue` refreshes a rolling 24-hour window, while `/demo-queue?page=` preserves a pagination snapshot without exposing `from`/`to`. ### Readable change links @@ -41,7 +41,7 @@ Omit the SHA/diff ID for submissions across versions; include it for submissions Exact-version URLs mirror the [change URI](change-uri.md): replace `://` with `//change//`, preserving the authority and encoded path. Do not insert `commit` or `diff` segments. -The host resolves change identities; React components do not parse URIs. Exact-version pages use the gateway's exact-URI lookups. Across-version demo pages scan an explicit receipt window; unbounded lookup and git routes remain deferred. +The host resolves change identities; React components do not parse URIs. Pinned GitHub/Phabricator pages use exact-URI lookups. Across-version and git demo pages scan the displayed rolling window; fake file hints stay backend-only. ## Reference UX @@ -85,7 +85,7 @@ Components render serializable props and do not fetch. Sessions, gateway clients `WebPaths` selects queue-scoped internal links. A queue landing page and request list live at `/` and a detail page at `//request/`. The `request` segment leaves room for other queue-scoped resources while the full request ID remains human-readable and opaque to the UI; the host's catch-all route only reassembles its URL path segments before passing it unchanged to the gateway. Phase one renders change URIs and build metadata as text; trusted external-link mapping and typed build URLs are deferred. -`List` requires a queue and a half-open receipt window. A first visit uses a trailing 24-hour window, which the host may override. Both bounds live in the route's search parameters and stay fixed across refresh and paging, because the page token is valid only for that queue and those bounds. Changing or resetting the window drops the token; the reference host links back to the queue's list route to establish a fresh trailing window. +`List` requires a queue and a half-open receipt window. The host recalculates the default trailing 24-hour window on refresh and keeps the URL free of timestamps. Pagination preserves the original bounds inside a signed, queue-scoped cursor; refreshing an older page returns to the live first page. A client component starts `router.refresh()` inside a React transition and does not schedule the next refresh until that transition finishes. The wait is the terminal client's poll interval plus jitter, grows across consecutive transport failures, and pauses while the document is hidden or the browser is offline. A request view stops only after the summary is terminal and successfully loaded history contains the same terminal status. A queue list keeps polling for the life of its fixed window.