fix(site-secrets): contain secret-store outages per site; audit removal-only deploys
Secret-store outage (final review M5): SiteSecretsCollector returns a store read failure as SiteSecretsCollection.StoreError instead of throwing. A deploy now fails only the sites that reference a secret (nothing sent, not stamped, DeploySiteSecrets row with the error), and ComputeCurrentArtifactHashesAsync omits only those sites (they read Out of date) instead of the exception aborting the whole sweep and the fleet-wide pending-updates check. Removal-only deploys: the site reply gains SecretsRemoved (proto field 7, names only) - the deployed_secrets rows the deploy soft-removed. Central carries it on SiteArtifactResult and writes the DeploySiteSecrets row with a removed list whenever it is non-empty, so dropping a site's last secret: reference is audited centrally rather than only in site logs.
This commit is contained in:
@@ -141,7 +141,7 @@ spec for each is `docs/requirements/Component-<Name>.md`, and `README.md` carrie
|
||||
- Per-instance operation lock covers all mutating commands (deploy, disable, enable, delete).
|
||||
- **Bulk site deployment (`DeploymentService.DeploySiteAsync`, arch-review WP2.5)** redeploys every out-of-date instance at a site through one flatten session (a template chain shared by N instances is walked once) in three phases — serial Prepare, bounded-parallel Send (`SiteDeploymentMaxParallelism`, default 4), serial Finalize — still **not all-or-nothing**: any one instance's failure doesn't block the rest. **Disabled instances are SKIPPED by bulk deploy as of 2026-08-19 (arch-review P7-2)** — they are reported in the summary's additive `SkippedInstances` list, never flattened/sent/re-enabled (single-instance deploy remains the explicit operator path that deploys+enables a Disabled instance); **Up-to-date instances are ALSO skipped as of 2026-08-20 (arch-review P7-6)** — a redeploy is not idempotent at the site (it resets static overrides and clears native alarm state), so `DeploySiteAsync` pre-filters through `IStaleInstanceProbe` (trustworthy since P7-4 fixed its memo timing) and reports unchanged instances in `SkippedInstances` with reason `up-to-date`; the filter is conservative (every uncertainty deploys: missing snapshot, `ShouldQuerySiteBeforeRedeploy`, null/faulting probe). Additive `MgmtDeploySiteCommand.Force` / CLI `deploy site --force` restores the unconditional push for what central cannot see (restored volume, rebuilt node) — **Disabled still wins under `--force`**. Also P7-5: the three phases share one scoped DbContext and a failed `SaveChanges` leaves the entity tracked, so one permanent failure used to cascade to every later instance and strand records `InProgress`; `MarkDeploymentFailedAsync` now detaches pending changes and retries the `Failed` write once on the clean tracker; Prepare's per-instance reconcile also runs under a short `SiteDeploymentReconcileTimeout` (5s) with a once-per-batch unreachable-site circuit-breaker, so a down site no longer costs 30s × N serial before the first send (P7-3). The `PendingDeployment` staging row (5-minute TTL) is written per-instance immediately before that instance's round-trip in the Send phase, not upfront in Prepare, so a large batch's tail instances don't have their TTL clock already half-spent by the time they're reached.
|
||||
- **Site artifact revision + fleet-wide pending-updates indicator (2026-09-14, `docs/plans/2026-09-14-pending-updates-design.md`).** `Site.ArtifactRevisionHash`/`ArtifactsDeployedAt` (migration `AddSiteArtifactRevision`) are stamped by `ArtifactDeploymentService` only on a site whose artifact deploy succeeds, so a redeployed fleet's artifacts are trackable per site the same way instance staleness already is. `PendingUpdatesEvaluator` combines that with `DeploymentService.GetInstanceStalenessAsync` (one shared `FlattenSession` for the whole fleet) into a `PendingUpdatesSnapshot`, held behind a process-wide singleton `IPendingUpdatesCache` (`ScadaBridge:DeploymentManager:PendingUpdatesCacheTtl`, default 60s) so N Blazor circuits cost one fleet flatten per TTL, not one each. Surfaces: the Sites page's per-site **Artifacts** badge (`Current`/`Out of date`/`Never deployed`) + instance-staleness line + header **Re-check**, and a rail-footer **pending updates** indicator (Deployer/Administrator only, 30s poll, site-scoped). **Upgrade consequence:** every site reads *Never deployed* until one artifact deploy runs post-upgrade — deliberate, not a bug. Also shipped: the rail nav now sits in its own scroll pane (`NavMenu`'s `.rail-scroll` + `site.css`) so a long nav can't push the footer/indicator off-screen; the `ZB.MOM.WW.Theme` kit itself is untouched (register row 123 proposes upstreaming it).
|
||||
- **Site secrets ride the artifact deploy; the gRPC secrets hub is retired in ScadaBridge (2026-09-28, `docs/plans/2026-09-28-site-secrets-artifact-deploy-design.md`).** `Deploy Artifacts` now ships each site **only the secrets it references** — `SiteSecretsCollector` scans a site's data-connection JSON for `secret:<name>` (`SecretReferenceScanner`, protocol-agnostic, bootstrap names like `SB-GRPC-PSK-*` excluded) and resolves each against the central `ISecretStore`; a missing/tombstoned secret fails **that site's** deploy before anything is sent (fail-closed), ciphertext only ever crosses the wire, and secrets factor into `ArtifactRevisionHashService`'s staleness hash (a missing secret hashes as a distinguishable marker, so an unresolvable reference never reads *Current*; a site with no secret references hashes identically whether the field is null or empty). A pre-feature site (answers with no `SecretsApplied`) or a partial apply is also treated as a deploy failure and is never stamped; one `DeploySiteSecrets`/`SiteSecrets` audit row (`secrets` name + revision and `missing` names only, never ciphertext; no `removed` field — a removal-only deploy writes no central row) is written per site deploy that carried secrets or a missing-secret failure, on both the sweep and the per-site retry paths. Site-side: `deployed_secrets` is the 11th LocalDb-replicated table (ciphertext rows only, upsert-then-soft-remove); the per-node `DeployedSecretsMirror` (`SiteRuntime:DeployedSecretsMirrorInterval`, default 15s, also run synchronously right after an active-node apply) reconciles it into that node's local `ISecretStore`, ledgers what it mirrored in the node-local `mirrored_secrets` table so an out-of-band local secret sharing a deployed name is never silently touched (a mirror-owned name deleted or edited locally is healed back to the deployed value on the next pass, even at an unchanged revision), and trial-decrypts every pass to catch a KEK mismatch. Secrets are mirrored before the deploy's data connections reach the DCL; a rotation with unchanged connection config takes effect on the next (re)connect. **A site pair using deployed secrets must run LocalDb replication** — otherwise only the node active at deploy time holds them. Central runs one shared secret store, `Secrets:Store:Provider=SqlServer` (Central role only; a clustered central left on `Sqlite` gets a boot Warning) — the pre-host `${secret:}` expander reads the same store the running node serves. **ALL secrets replication is retired in ScadaBridge** — the pull-only gRPC hub and the SQL-Server replication mode both — `Secrets:Replication:Enabled` set to anything but empty/`false` now fails `StartupValidator` on either role with a message pointing at Deploy Artifacts / `Secrets:Store:Provider=SqlServer`.
|
||||
- **Site secrets ride the artifact deploy; the gRPC secrets hub is retired in ScadaBridge (2026-09-28, `docs/plans/2026-09-28-site-secrets-artifact-deploy-design.md`).** `Deploy Artifacts` now ships each site **only the secrets it references** — `SiteSecretsCollector` scans a site's data-connection JSON for `secret:<name>` (`SecretReferenceScanner`, protocol-agnostic, bootstrap names like `SB-GRPC-PSK-*` excluded) and resolves each against the central `ISecretStore`; a missing/tombstoned secret fails **that site's** deploy before anything is sent (fail-closed), ciphertext only ever crosses the wire, and secrets factor into `ArtifactRevisionHashService`'s staleness hash (a missing secret hashes as a distinguishable marker, so an unresolvable reference never reads *Current*; a site with no secret references hashes identically whether the field is null or empty). A pre-feature site (answers with no `SecretsApplied`) or a partial apply is also treated as a deploy failure and is never stamped; one `DeploySiteSecrets`/`SiteSecrets` audit row (`secrets` name + revision, `missing` and `removed` names, never ciphertext — `removed` comes from the site's `SecretsRemoved` reply, so a removal-only deploy is audited too) is written per site deploy that carried, lacked or retired secrets, on both the sweep and the per-site retry paths. A central secret-store read failure fails only the sites that reference a secret and leaves them *Out of date* in the pending-updates check — it no longer aborts the sweep or the fleet-wide check — and both artifact-deploy CLI commands exit 1 when any site failed. Site-side: `deployed_secrets` is the 11th LocalDb-replicated table (ciphertext rows only, upsert-then-soft-remove); the per-node `DeployedSecretsMirror` (`SiteRuntime:DeployedSecretsMirrorInterval`, default 15s, also run synchronously right after an active-node apply) reconciles it into that node's local `ISecretStore`, ledgers what it mirrored in the node-local `mirrored_secrets` table so an out-of-band local secret sharing a deployed name is never silently touched (a mirror-owned name deleted or edited locally is healed back to the deployed value on the next pass, even at an unchanged revision), and trial-decrypts every pass to catch a KEK mismatch. Secrets are mirrored before the deploy's data connections reach the DCL; a rotation with unchanged connection config takes effect on the next (re)connect. **A site pair using deployed secrets must run LocalDb replication** — otherwise only the node active at deploy time holds them. Central runs one shared secret store, `Secrets:Store:Provider=SqlServer` (Central role only; a clustered central left on `Sqlite` gets a boot Warning) — the pre-host `${secret:}` expander reads the same store the running node serves. **ALL secrets replication is retired in ScadaBridge** — the pull-only gRPC hub and the SQL-Server replication mode both — `Secrets:Replication:Enabled` set to anything but empty/`false` now fails `StartupValidator` on either role with a message pointing at Deploy Artifacts / `Secrets:Store:Provider=SqlServer`.
|
||||
- **Create Instance picks its template from the Templates folder tree** (2026-08-21): the flat `<select>` is gone. The Template field is a read-only folder-qualified path box (`TemplatePathFormatter`, "Folder / Sub / Name") + a **Choose…** button, both opening `TemplatePickerDialog` — an `IDialogService.ShowAsync` body wrapping the **same shared `TemplateFolderTree`** the Templates page renders, with its own search, expand/collapse-all, templates-only selection and double-click-to-pick. It opens on the current pick via the tree's additive **`RevealKeys`** parameter (ancestors of the named `f:`/`t:` keys start expanded when no `Filter` is active; an active filter's reveal set still wins; callers passing nothing are byte-identical). `InstanceCreate` gained `[SupplyParameterFromQuery] TemplateId`, which the Templates tree's new **Deployer-gated "New Instance…"** context-menu item navigates with; combined with `?siteId=` it populates the Connection Bindings card on first render. **The trap for anyone extending the picker:** in `TreeViewSelectionMode.Single` the inner `TreeView` reads the *singular* `SelectedKey`/`SelectedKeyChanged` pair, but `TemplateFolderTree` forwards only the plural (Checkbox-mode) `SelectedKeys` pair — so a Single-mode caller cannot get a row highlight through the shared tree and must own selection in its own `NodeContent`, as the picker does. Design: `docs/plans/2026-08-21-template-picker-design.md`.
|
||||
- **Create Instance binds module groups at creation** (2026-08-21): the create page's Connection Bindings card flattens template+site through the additive `IFlatteningPipeline.PreviewAsync` (an unsaved instance — no validation, no hash, nothing persisted, instance repo never touched) and reuses `BindingGroupBuilder`; `NodeBrowserDialog.SelectableNodeClasses` lets it pick **Object** nodes (default stays Variable-only for every existing caller). Create = `CreateInstanceAsync` → `SetConnectionBindingsAsync` (the existing upsert, no new server surface) → always navigate to Configure with `?created=1&bound=N|&bindError=…`, because the row exists whether or not the second call succeeded. Partial binding is legal: a group missing a connection or an Object is skipped and stays unbound. Design: `docs/plans/2026-08-21-create-instance-bindings-design.md`.
|
||||
- Site-side apply is all-or-nothing per instance.
|
||||
|
||||
@@ -237,11 +237,32 @@ accurate as the spec:
|
||||
next (re)connect (no forced reconnect).
|
||||
- *One `secret:` parser* (`SecretReferenceScanner.TryParseSecretReference`) shared by the scanner
|
||||
and `MxGatewayDataConnection`, so a padded/case-variant reference resolves the shipped name.
|
||||
- *Audit shape (§3.7 deviation).* The `DeploySiteSecrets` row carries `secrets` and `missing` —
|
||||
there is **no `removed` field** — and a removal-only deploy (empty list shipped) writes **no
|
||||
central row**; removals are logged on the site by `DeployedSecretsMirror`.
|
||||
- *Audit shape (§3.7).* The `DeploySiteSecrets` row carries `secrets`, `missing` and `removed`.
|
||||
(Shipped first without `removed`, so a removal-only deploy wrote no central row; closed by the
|
||||
follow-ups below.)
|
||||
- *Deployment prerequisite:* a site pair using deployed secrets must run LocalDb replication
|
||||
(topology guide), since on an unreplicated pair only the node active at deploy time gets them.
|
||||
- **Follow-ups closed after merge (2026-09-28).**
|
||||
- *Secret-store outage is per site (review M5).* `SiteSecretsCollector` returns a store read
|
||||
failure as `SiteSecretsCollection.StoreError` instead of throwing. A deploy fails only the
|
||||
sites that reference a secret (nothing is sent to them; they get a `DeploySiteSecrets` row
|
||||
with the error), and `ComputeCurrentArtifactHashesAsync` leaves those sites out of its map,
|
||||
which the pending-updates evaluator reads as *Out of date*. Sites with no secret references
|
||||
never touch the store and are unaffected. Before this, one `GetAsync` exception aborted the
|
||||
whole sweep and the fleet-wide pending-updates check.
|
||||
- *Removal-only deploys are audited.* The site's reply gained `SecretsRemoved` (proto
|
||||
`ArtifactDeploymentResponseDto.secrets_removed = 7`, names only; absent/empty reads as null):
|
||||
the `deployed_secrets` rows that deploy soft-removed. Central carries it on
|
||||
`SiteArtifactResult.SecretsRemoved` and writes the `DeploySiteSecrets` row whenever it is
|
||||
non-empty, with a `removed` list. An old site never sends it, so its removals stay unaudited
|
||||
centrally, as before.
|
||||
- *CLI exit code.* `site deploy-artifacts` and `deploy artifacts` exit `1` when the summary's
|
||||
`failureCount` is non-zero (same rule `deploy site` already had).
|
||||
- *Hub-era site-a secrets (review M8).* The retired hub had copied six `hub-gate-*`/`shared-gate-*`
|
||||
test secrets (2026-08-07) into both rig site-a nodes' local stores. The mirror deliberately
|
||||
never deletes a name it did not ledger, so they were removed once by hand on the rig (both
|
||||
nodes stopped together; see the live-gate doc). QA and vd03 never ran the hub
|
||||
(`Secrets:Replication:Enabled=false`), so nothing like this exists there.
|
||||
- **Rig posture.** `docker/docker-compose.yml`'s central nodes now carry
|
||||
`Secrets__Store__Provider=SqlServer` plus a shared KEK; site-a shares that KEK (it is the
|
||||
secrets-via-artifact-deploy site); site-b/site-c deliberately carry a **mismatched** KEK so the
|
||||
|
||||
@@ -385,16 +385,25 @@ out below.
|
||||
check 5). An old site ignores proto field 9, so the empty list costs it
|
||||
nothing, and the hash is unaffected (empty == null above).
|
||||
- **Audit.** One best-effort `DeploySiteSecrets` / `SiteSecrets` audit row is
|
||||
written per site deploy that carried secrets or a missing-secret failure
|
||||
(never for a site with no secret references at all) — after-state is `{
|
||||
deploymentId, secrets: [{name, revision}], missing: [name], success }`, which
|
||||
structurally excludes ciphertext. Written on both `DeployCoreAsync` and
|
||||
`RetryForSiteAsync`, including the fail-closed path (audited even though
|
||||
nothing was sent). The row carries `secrets` and `missing` only — there is
|
||||
**no `removed` field** (design §3.7 named one), and a deploy that only
|
||||
removes secrets (the site's last reference dropped, an empty list shipped)
|
||||
writes **no central row**; removals are logged on the site by
|
||||
`DeployedSecretsMirror`.
|
||||
written per site deploy that carried secrets, failed on a missing secret or a
|
||||
secret-store read, or retired previously-deployed secrets (never for a site
|
||||
with no secret involvement at all) — after-state is `{ deploymentId,
|
||||
secrets: [{name, revision}], missing: [name], removed: [name], success,
|
||||
error }`, which structurally excludes ciphertext. Written on both
|
||||
`DeployCoreAsync` and `RetryForSiteAsync`, including the fail-closed paths
|
||||
(audited even though nothing was sent). `removed` is the site's reply field
|
||||
`ArtifactDeploymentResponse.SecretsRemoved` — the `deployed_secrets` rows that
|
||||
deploy soft-removed — so a deploy that only drops the site's last secret
|
||||
reference is still audited centrally. A site that predates the field never
|
||||
reports it.
|
||||
- **Central secret-store outage.** `SiteSecretsCollector` returns a store read
|
||||
failure as `StoreError` rather than throwing, so it is contained per site: a
|
||||
site that references a secret fails (`Central secret store could not be read
|
||||
while resolving '<name>' (...)`, nothing sent, not stamped), every other site
|
||||
deploys, and `ComputeCurrentArtifactHashesAsync` omits only the affected sites
|
||||
from its map (they read *Out of date* on the Sites page) instead of failing the
|
||||
fleet-wide pending-updates check. A site with no secret references never
|
||||
touches the store.
|
||||
- **Secret rotation and live connections.** The site writes and mirrors the
|
||||
shipped secrets before it pushes data connections to the DCL, so a
|
||||
connection created by the same deploy resolves a new secret on first
|
||||
|
||||
@@ -166,6 +166,7 @@ flowchart TD
|
||||
- `HandleDeployArtifacts` additionally accepts the command's `Secrets` list (`SecretArtifact`, ciphertext only) and writes the full shipped set to the `deployed_secrets` table via `SiteStorageService.UpsertDeployedSecretsAsync` — upsert every shipped name, soft-remove (`is_removed = 1`) any stored name absent from the set. A `null` `Secrets` field (pre-feature central) touches nothing and answers with no `SecretsApplied`. A current central always ships a list — **empty** when the site references no secrets — so dropping a site's last `secret:` reference removes the secret from both nodes. Storage detail: *Deployed Secrets (Site SQLite / LocalDb)* below.
|
||||
- After writing the table, the active node runs `DeployedSecretsMirror.ReconcileAsync` **synchronously**, before replying — so the deploy response's `SecretsApplied` count and any apply/verify error reflect this deploy's own outcome, not a value left over from the mirror's background schedule. `SecretsApplied` counts only the names *this deploy shipped* that applied and verified cleanly; a mirror failure for an unrelated, already-broken name (a different deploy's leftover, or a stale removal) is logged at Warning and excluded — it neither fails this deploy nor reduces its `SecretsApplied`.
|
||||
- No `DeployedSecretsMirror` registered (secrets deployment not composed on this node) with a non-empty `Secrets` list fails the deploy with `Secret deployment is not enabled on this site node`; with an empty `Secrets` list it still succeeds (`SecretsApplied = 0`).
|
||||
- The reply also carries `SecretsRemoved`: the names `UpsertDeployedSecretsAsync` soft-removed on this deploy (site-wide, whichever node's mirror later deletes them), or `null` when none. Central uses it for the `removed` list of its `DeploySiteSecrets` audit row, so a deploy that only retires secrets is audited centrally.
|
||||
- **Ordering against the DCL.** The shipped secrets are written and mirrored **before** the deploy's data-connection definitions are pushed to the DCL (the definitions are still stored in SQLite at the same point, and the push still goes out if the secrets step fails), so a connection created or reconfigured by the same deploy resolves a newly shipped secret on its first connect. A rotation with **unchanged** connection config does not recreate the connection (the DCL push is hash-guarded) — the new value takes effect on that connection's next (re)connect. No forced reconnect is performed.
|
||||
- See *Deployed Secrets (Site SQLite / LocalDb)* below for the mirror itself.
|
||||
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
/// <summary>
|
||||
/// A site's reply to a <see cref="DeployArtifactsCommand"/>.
|
||||
/// </summary>
|
||||
/// <param name="SecretsApplied">
|
||||
/// How many of the shipped secrets this node applied and verified; <c>null</c> from a site that
|
||||
/// predates secret deployment or when central shipped no secret list.
|
||||
/// </param>
|
||||
/// <param name="SecretsRemoved">
|
||||
/// Names of previously-deployed secrets this deploy retired (marked removed in the site's
|
||||
/// <c>deployed_secrets</c> table because the shipped set no longer contains them). Names only —
|
||||
/// never values. <c>null</c> when none were removed or the site predates the field.
|
||||
/// </param>
|
||||
public record ArtifactDeploymentResponse(
|
||||
string DeploymentId,
|
||||
string SiteId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp,
|
||||
int? SecretsApplied = null);
|
||||
int? SecretsApplied = null,
|
||||
IReadOnlyList<string>? SecretsRemoved = null);
|
||||
|
||||
@@ -827,6 +827,11 @@ public static class SiteCommandDtoMapper
|
||||
dto.SecretsApplied = response.SecretsApplied.Value;
|
||||
}
|
||||
|
||||
if (response.SecretsRemoved is { Count: > 0 })
|
||||
{
|
||||
dto.SecretsRemoved.AddRange(response.SecretsRemoved);
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -839,7 +844,8 @@ public static class SiteCommandDtoMapper
|
||||
|
||||
return new ArtifactDeploymentResponse(
|
||||
dto.DeploymentId, dto.SiteId, dto.Success, NullIfEmpty(dto.ErrorMessage), Dto(dto.Timestamp),
|
||||
dto.SecretsApplied);
|
||||
dto.SecretsApplied,
|
||||
dto.SecretsRemoved.Count > 0 ? dto.SecretsRemoved.ToList() : null);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -340,6 +340,7 @@ message ArtifactDeploymentResponseDto {
|
||||
string error_message = 4; // empty string represents null
|
||||
google.protobuf.Timestamp timestamp = 5;
|
||||
google.protobuf.Int32Value secrets_applied = 6; // absent => null
|
||||
repeated string secrets_removed = 7; // names only; empty => null
|
||||
}
|
||||
|
||||
message LifecycleRequest {
|
||||
|
||||
@@ -134,385 +134,385 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
"cmVsYXRpb25faWQYASABKAkSHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYAiAB",
|
||||
"KAkSEwoLaXNfZGVwbG95ZWQYAyABKAgSHQoVYXBwbGllZF9kZXBsb3ltZW50",
|
||||
"X2lkGAQgASgJEh0KFWFwcGxpZWRfcmV2aXNpb25faGFzaBgFIAEoCRItCgl0",
|
||||
"aW1lc3RhbXAYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wItQB",
|
||||
"aW1lc3RhbXAYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIu0B",
|
||||
"Ch1BcnRpZmFjdERlcGxveW1lbnRSZXNwb25zZUR0bxIVCg1kZXBsb3ltZW50",
|
||||
"X2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkSDwoHc3VjY2VzcxgDIAEoCBIV",
|
||||
"Cg1lcnJvcl9tZXNzYWdlGAQgASgJEi0KCXRpbWVzdGFtcBgFIAEoCzIaLmdv",
|
||||
"b2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoPc2VjcmV0c19hcHBsaWVkGAYg",
|
||||
"ASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUimgQKEExpZmVjeWNs",
|
||||
"ZVJlcXVlc3QSVQoScmVmcmVzaF9kZXBsb3ltZW50GAEgASgLMjcuc2NhZGFi",
|
||||
"cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUmVmcmVzaERlcGxveW1lbnRDb21tYW5k",
|
||||
"RHRvSAASTwoPZW5hYmxlX2luc3RhbmNlGAIgASgLMjQuc2NhZGFicmlkZ2Uu",
|
||||
"c2l0ZWNvbW1hbmQudjEuRW5hYmxlSW5zdGFuY2VDb21tYW5kRHRvSAASUQoQ",
|
||||
"ZGlzYWJsZV9pbnN0YW5jZRgDIAEoCzI1LnNjYWRhYnJpZGdlLnNpdGVjb21t",
|
||||
"YW5kLnYxLkRpc2FibGVJbnN0YW5jZUNvbW1hbmREdG9IABJPCg9kZWxldGVf",
|
||||
"aW5zdGFuY2UYBCABKAsyNC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5E",
|
||||
"ZWxldGVJbnN0YW5jZUNvbW1hbmREdG9IABJcChZkZXBsb3ltZW50X3N0YXRl",
|
||||
"X3F1ZXJ5GAUgASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVw",
|
||||
"bG95bWVudFN0YXRlUXVlcnlSZXF1ZXN0RHRvSAASUQoQZGVwbG95X2FydGlm",
|
||||
"YWN0cxgGIAEoCzI1LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRlcGxv",
|
||||
"eUFydGlmYWN0c0NvbW1hbmREdG9IAEIJCgdjb21tYW5kIoADCg5MaWZlY3lj",
|
||||
"bGVSZXBseRJUChFkZXBsb3ltZW50X3N0YXR1cxgBIAEoCzI3LnNjYWRhYnJp",
|
||||
"ZGdlLnNpdGVjb21tYW5kLnYxLkRlcGxveW1lbnRTdGF0dXNSZXNwb25zZUR0",
|
||||
"b0gAElYKEmluc3RhbmNlX2xpZmVjeWNsZRgCIAEoCzI4LnNjYWRhYnJpZGdl",
|
||||
"LnNpdGVjb21tYW5kLnYxLkluc3RhbmNlTGlmZWN5Y2xlUmVzcG9uc2VEdG9I",
|
||||
"ABJdChZkZXBsb3ltZW50X3N0YXRlX3F1ZXJ5GAMgASgLMjsuc2NhZGFicmlk",
|
||||
"Z2Uuc2l0ZWNvbW1hbmQudjEuRGVwbG95bWVudFN0YXRlUXVlcnlSZXNwb25z",
|
||||
"ZUR0b0gAElgKE2FydGlmYWN0X2RlcGxveW1lbnQYBCABKAsyOS5zY2FkYWJy",
|
||||
"aWRnZS5zaXRlY29tbWFuZC52MS5BcnRpZmFjdERlcGxveW1lbnRSZXNwb25z",
|
||||
"ZUR0b0gAQgcKBXJlcGx5InwKFEJyb3dzZU5vZGVDb21tYW5kRHRvEhcKD2Nv",
|
||||
"bm5lY3Rpb25fbmFtZRgBIAEoCRIWCg5wYXJlbnRfbm9kZV9pZBgCIAEoCRIa",
|
||||
"ChJjb250aW51YXRpb25fdG9rZW4YAyABKAkSFwoPc2l0ZV9pZGVudGlmaWVy",
|
||||
"GAQgASgJIoICCg1Ccm93c2VOb2RlRHRvEg8KB25vZGVfaWQYASABKAkSFAoM",
|
||||
"ZGlzcGxheV9uYW1lGAIgASgJEkIKCm5vZGVfY2xhc3MYAyABKA4yLi5zY2Fk",
|
||||
"YWJyaWRnZS5zaXRlY29tbWFuZC52MS5Ccm93c2VOb2RlQ2xhc3NEdG8SFAoM",
|
||||
"aGFzX2NoaWxkcmVuGAQgASgIEhEKCWRhdGFfdHlwZRgFIAEoCRIvCgp2YWx1",
|
||||
"ZV9yYW5rGAYgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSLAoI",
|
||||
"d3JpdGFibGUYByABKAsyGi5nb29nbGUucHJvdG9idWYuQm9vbFZhbHVlImMK",
|
||||
"EEJyb3dzZUZhaWx1cmVEdG8SPgoEa2luZBgBIAEoDjIwLnNjYWRhYnJpZGdl",
|
||||
"LnNpdGVjb21tYW5kLnYxLkJyb3dzZUZhaWx1cmVLaW5kRHRvEg8KB21lc3Nh",
|
||||
"Z2UYAiABKAkiwAEKE0Jyb3dzZU5vZGVSZXN1bHREdG8SOwoIY2hpbGRyZW4Y",
|
||||
"ASADKAsyKS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Ccm93c2VOb2Rl",
|
||||
"RHRvEhEKCXRydW5jYXRlZBgCIAEoCBI9CgdmYWlsdXJlGAMgASgLMiwuc2Nh",
|
||||
"ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuQnJvd3NlRmFpbHVyZUR0bxIaChJj",
|
||||
"b250aW51YXRpb25fdG9rZW4YBCABKAkihwEKHFNlYXJjaEFkZHJlc3NTcGFj",
|
||||
"ZUNvbW1hbmREdG8SFwoPY29ubmVjdGlvbl9uYW1lGAEgASgJEg0KBXF1ZXJ5",
|
||||
"GAIgASgJEhEKCW1heF9kZXB0aBgDIAEoBRITCgttYXhfcmVzdWx0cxgEIAEo",
|
||||
"BRIXCg9zaXRlX2lkZW50aWZpZXIYBSABKAkiXQoUQWRkcmVzc1NwYWNlTWF0",
|
||||
"Y2hEdG8SNwoEbm9kZRgBIAEoCzIpLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k",
|
||||
"LnYxLkJyb3dzZU5vZGVEdG8SDAoEcGF0aBgCIAEoCSK0AQobU2VhcmNoQWRk",
|
||||
"cmVzc1NwYWNlUmVzdWx0RHRvEkEKB21hdGNoZXMYASADKAsyMC5zY2FkYWJy",
|
||||
"aWRnZS5zaXRlY29tbWFuZC52MS5BZGRyZXNzU3BhY2VNYXRjaER0bxITCgtj",
|
||||
"YXBfcmVhY2hlZBgCIAEoCBI9CgdmYWlsdXJlGAMgASgLMiwuc2NhZGFicmlk",
|
||||
"Z2Uuc2l0ZWNvbW1hbmQudjEuQnJvd3NlRmFpbHVyZUR0byJFChdSZWFkVGFn",
|
||||
"VmFsdWVzQ29tbWFuZER0bxIXCg9jb25uZWN0aW9uX25hbWUYASABKAkSEQoJ",
|
||||
"dGFnX3BhdGhzGAIgAygJIsQBChFUYWdSZWFkT3V0Y29tZUR0bxIQCgh0YWdf",
|
||||
"cGF0aBgBIAEoCRIPCgdzdWNjZXNzGAIgASgIEjUKBXZhbHVlGAMgASgLMiYu",
|
||||
"c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZRIPCgdxdWFs",
|
||||
"aXR5GAQgASgJEi0KCXRpbWVzdGFtcBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1",
|
||||
"Zi5UaW1lc3RhbXASFQoNZXJyb3JfbWVzc2FnZRgGIAEoCSJxChdSZWFkVGFn",
|
||||
"VmFsdWVzRmFpbHVyZUR0bxJFCgRraW5kGAEgASgOMjcuc2NhZGFicmlkZ2Uu",
|
||||
"c2l0ZWNvbW1hbmQudjEuUmVhZFRhZ1ZhbHVlc0ZhaWx1cmVLaW5kRHRvEg8K",
|
||||
"B21lc3NhZ2UYAiABKAkinwEKFlJlYWRUYWdWYWx1ZXNSZXN1bHREdG8SPwoI",
|
||||
"b3V0Y29tZXMYASADKAsyLS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5U",
|
||||
"YWdSZWFkT3V0Y29tZUR0bxJECgdmYWlsdXJlGAIgASgLMjMuc2NhZGFicmlk",
|
||||
"Z2Uuc2l0ZWNvbW1hbmQudjEuUmVhZFRhZ1ZhbHVlc0ZhaWx1cmVEdG8icwoY",
|
||||
"VmVyaWZ5RW5kcG9pbnRDb21tYW5kRHRvEhcKD2Nvbm5lY3Rpb25fbmFtZRgB",
|
||||
"IAEoCRIQCghwcm90b2NvbBgCIAEoCRITCgtjb25maWdfanNvbhgDIAEoCRIX",
|
||||
"Cg9zaXRlX2lkZW50aWZpZXIYBCABKAkiwwEKEVNlcnZlckNlcnRJbmZvRHRv",
|
||||
"EhIKCnRodW1icHJpbnQYASABKAkSDwoHc3ViamVjdBgCIAEoCRIOCgZpc3N1",
|
||||
"ZXIYAyABKAkSMgoObm90X2JlZm9yZV91dGMYBCABKAsyGi5nb29nbGUucHJv",
|
||||
"dG9idWYuVGltZXN0YW1wEjEKDW5vdF9hZnRlcl91dGMYBSABKAsyGi5nb29n",
|
||||
"bGUucHJvdG9idWYuVGltZXN0YW1wEhIKCmRlcl9iYXNlNjQYBiABKAkiWQoW",
|
||||
"VmVyaWZ5RmFpbHVyZUtpbmRWYWx1ZRI/CgV2YWx1ZRgBIAEoDjIwLnNjYWRh",
|
||||
"YnJpZGdlLnNpdGVjb21tYW5kLnYxLlZlcmlmeUZhaWx1cmVLaW5kRHRvIsAB",
|
||||
"ChdWZXJpZnlFbmRwb2ludFJlc3VsdER0bxIPCgdzdWNjZXNzGAEgASgIEkgK",
|
||||
"DGZhaWx1cmVfa2luZBgCIAEoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k",
|
||||
"LnYxLlZlcmlmeUZhaWx1cmVLaW5kVmFsdWUSDQoFZXJyb3IYAyABKAkSOwoE",
|
||||
"Y2VydBgEIAEoCzItLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNlcnZl",
|
||||
"ckNlcnRJbmZvRHRvInUKGVRydXN0U2VydmVyQ2VydENvbW1hbmREdG8SFwoP",
|
||||
"Y29ubmVjdGlvbl9uYW1lGAEgASgJEhIKCmRlcl9iYXNlNjQYAiABKAkSEgoK",
|
||||
"dGh1bWJwcmludBgDIAEoCRIXCg9zaXRlX2lkZW50aWZpZXIYBCABKAkiNAoZ",
|
||||
"TGlzdFNlcnZlckNlcnRzQ29tbWFuZER0bxIXCg9zaXRlX2lkZW50aWZpZXIY",
|
||||
"ASABKAkiSQoaUmVtb3ZlU2VydmVyQ2VydENvbW1hbmREdG8SEgoKdGh1bWJw",
|
||||
"cmludBgBIAEoCRIXCg9zaXRlX2lkZW50aWZpZXIYAiABKAkiwgEKElRydXN0",
|
||||
"ZWRDZXJ0SW5mb0R0bxISCgp0aHVtYnByaW50GAEgASgJEg8KB3N1YmplY3QY",
|
||||
"AiABKAkSDgoGaXNzdWVyGAMgASgJEjIKDm5vdF9iZWZvcmVfdXRjGAQgASgL",
|
||||
"MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1ub3RfYWZ0ZXJfdXRj",
|
||||
"GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIQCghyZWplY3Rl",
|
||||
"ZBgGIAEoCCJXChZUcnVzdGVkQ2VydEluZm9MaXN0RHRvEj0KBWl0ZW1zGAEg",
|
||||
"AygLMi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVHJ1c3RlZENlcnRJ",
|
||||
"bmZvRHRvIncKEkNlcnRUcnVzdFJlc3VsdER0bxIPCgdzdWNjZXNzGAEgASgI",
|
||||
"Eg0KBWVycm9yGAIgASgJEkEKBWNlcnRzGAMgASgLMjIuc2NhZGFicmlkZ2Uu",
|
||||
"c2l0ZWNvbW1hbmQudjEuVHJ1c3RlZENlcnRJbmZvTGlzdER0byK9AQoSV3Jp",
|
||||
"dGVUYWdSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhcKD2Nv",
|
||||
"bm5lY3Rpb25fbmFtZRgCIAEoCRIQCgh0YWdfcGF0aBgDIAEoCRI1CgV2YWx1",
|
||||
"ZRgEIAEoCzImLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkxvb3NlVmFs",
|
||||
"dWUSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVz",
|
||||
"dGFtcCKEAQoTV3JpdGVUYWdSZXNwb25zZUR0bxIWCg5jb3JyZWxhdGlvbl9p",
|
||||
"ZBgBIAEoCRIPCgdzdWNjZXNzGAIgASgIEhUKDWVycm9yX21lc3NhZ2UYAyAB",
|
||||
"KAkSLQoJdGltZXN0YW1wGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVz",
|
||||
"dGFtcCKgBQoMT3BjVWFSZXF1ZXN0EkcKC2Jyb3dzZV9ub2RlGAEgASgLMjAu",
|
||||
"c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuQnJvd3NlTm9kZUNvbW1hbmRE",
|
||||
"dG9IABJYChRzZWFyY2hfYWRkcmVzc19zcGFjZRgCIAEoCzI4LnNjYWRhYnJp",
|
||||
"ZGdlLnNpdGVjb21tYW5kLnYxLlNlYXJjaEFkZHJlc3NTcGFjZUNvbW1hbmRE",
|
||||
"dG9IABJOCg9yZWFkX3RhZ192YWx1ZXMYAyABKAsyMy5zY2FkYWJyaWRnZS5z",
|
||||
"aXRlY29tbWFuZC52MS5SZWFkVGFnVmFsdWVzQ29tbWFuZER0b0gAEk8KD3Zl",
|
||||
"cmlmeV9lbmRwb2ludBgEIAEoCzI0LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k",
|
||||
"LnYxLlZlcmlmeUVuZHBvaW50Q29tbWFuZER0b0gAElIKEXRydXN0X3NlcnZl",
|
||||
"cl9jZXJ0GAUgASgLMjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVHJ1",
|
||||
"c3RTZXJ2ZXJDZXJ0Q29tbWFuZER0b0gAElIKEWxpc3Rfc2VydmVyX2NlcnRz",
|
||||
"GAYgASgLMjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTGlzdFNlcnZl",
|
||||
"ckNlcnRzQ29tbWFuZER0b0gAElQKEnJlbW92ZV9zZXJ2ZXJfY2VydBgHIAEo",
|
||||
"CzI2LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJlbW92ZVNlcnZlckNl",
|
||||
"cnRDb21tYW5kRHRvSAASQwoJd3JpdGVfdGFnGAggASgLMi4uc2NhZGFicmlk",
|
||||
"Z2Uuc2l0ZWNvbW1hbmQudjEuV3JpdGVUYWdSZXF1ZXN0RHRvSABCCQoHY29t",
|
||||
"bWFuZCLhAwoKT3BjVWFSZXBseRJGCgticm93c2Vfbm9kZRgBIAEoCzIvLnNj",
|
||||
"YWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkJyb3dzZU5vZGVSZXN1bHREdG9I",
|
||||
"ABJXChRzZWFyY2hfYWRkcmVzc19zcGFjZRgCIAEoCzI3LnNjYWRhYnJpZGdl",
|
||||
"LnNpdGVjb21tYW5kLnYxLlNlYXJjaEFkZHJlc3NTcGFjZVJlc3VsdER0b0gA",
|
||||
"Ek0KD3JlYWRfdGFnX3ZhbHVlcxgDIAEoCzIyLnNjYWRhYnJpZGdlLnNpdGVj",
|
||||
"b21tYW5kLnYxLlJlYWRUYWdWYWx1ZXNSZXN1bHREdG9IABJOCg92ZXJpZnlf",
|
||||
"ZW5kcG9pbnQYBCABKAsyMy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5W",
|
||||
"ZXJpZnlFbmRwb2ludFJlc3VsdER0b0gAEkQKCmNlcnRfdHJ1c3QYBSABKAsy",
|
||||
"Li5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5DZXJ0VHJ1c3RSZXN1bHRE",
|
||||
"dG9IABJECgl3cml0ZV90YWcYBiABKAsyLy5zY2FkYWJyaWRnZS5zaXRlY29t",
|
||||
"bWFuZC52MS5Xcml0ZVRhZ1Jlc3BvbnNlRHRvSABCBwoFcmVwbHkixQIKF0V2",
|
||||
"ZW50TG9nUXVlcnlSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJ",
|
||||
"Eg8KB3NpdGVfaWQYAiABKAkSKAoEZnJvbRgDIAEoCzIaLmdvb2dsZS5wcm90",
|
||||
"b2J1Zi5UaW1lc3RhbXASJgoCdG8YBCABKAsyGi5nb29nbGUucHJvdG9idWYu",
|
||||
"VGltZXN0YW1wEhIKCmV2ZW50X3R5cGUYBSABKAkSEAoIc2V2ZXJpdHkYBiAB",
|
||||
"KAkSEwoLaW5zdGFuY2VfaWQYByABKAkSFgoOa2V5d29yZF9maWx0ZXIYCCAB",
|
||||
"KAkSGgoSY29udGludWF0aW9uX3Rva2VuGAkgASgJEhEKCXBhZ2Vfc2l6ZRgK",
|
||||
"IAEoBRItCgl0aW1lc3RhbXAYCyABKAsyGi5nb29nbGUucHJvdG9idWYuVGlt",
|
||||
"ZXN0YW1wIroBChBFdmVudExvZ0VudHJ5RHRvEgoKAmlkGAEgASgJEi0KCXRp",
|
||||
"bWVzdGFtcBgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASEgoK",
|
||||
"ZXZlbnRfdHlwZRgDIAEoCRIQCghzZXZlcml0eRgEIAEoCRITCgtpbnN0YW5j",
|
||||
"ZV9pZBgFIAEoCRIOCgZzb3VyY2UYBiABKAkSDwoHbWVzc2FnZRgHIAEoCRIP",
|
||||
"CgdkZXRhaWxzGAggASgJIocCChhFdmVudExvZ1F1ZXJ5UmVzcG9uc2VEdG8S",
|
||||
"FgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgCIAEoCRI9Cgdl",
|
||||
"bnRyaWVzGAMgAygLMiwuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXZl",
|
||||
"bnRMb2dFbnRyeUR0bxIaChJjb250aW51YXRpb25fdG9rZW4YBCABKAkSEAoI",
|
||||
"aGFzX21vcmUYBSABKAgSDwoHc3VjY2VzcxgGIAEoCBIVCg1lcnJvcl9tZXNz",
|
||||
"YWdlGAcgASgJEi0KCXRpbWVzdGFtcBgIIAEoCzIaLmdvb2dsZS5wcm90b2J1",
|
||||
"Zi5UaW1lc3RhbXAiZAoXRGVidWdTbmFwc2hvdFJlcXVlc3REdG8SHAoUaW5z",
|
||||
"dGFuY2VfdW5pcXVlX25hbWUYASABKAkSFgoOY29ycmVsYXRpb25faWQYAiAB",
|
||||
"KAkSEwoLYWxhcm1zX29ubHkYAyABKAgiVAocU3Vic2NyaWJlRGVidWdWaWV3",
|
||||
"UmVxdWVzdER0bxIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgBIAEoCRIWCg5j",
|
||||
"b3JyZWxhdGlvbl9pZBgCIAEoCSJWCh5VbnN1YnNjcmliZURlYnVnVmlld1Jl",
|
||||
"cXVlc3REdG8SHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASABKAkSFgoOY29y",
|
||||
"cmVsYXRpb25faWQYAiABKAkiHAoaVW5zdWJzY3JpYmVEZWJ1Z1ZpZXdBY2tE",
|
||||
"dG8i1AEKFkFsYXJtQ29uZGl0aW9uU3RhdGVEdG8SDgoGYWN0aXZlGAEgASgI",
|
||||
"EhQKDGFja25vd2xlZGdlZBgCIAEoCBItCgljb25maXJtZWQYAyABKAsyGi5n",
|
||||
"b29nbGUucHJvdG9idWYuQm9vbFZhbHVlEj8KBnNoZWx2ZRgEIAEoDjIvLnNj",
|
||||
"YWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkFsYXJtU2hlbHZlU3RhdGVEdG8S",
|
||||
"EgoKc3VwcHJlc3NlZBgFIAEoCBIQCghzZXZlcml0eRgGIAEoBSLdAQoWRGVi",
|
||||
"dWdBdHRyaWJ1dGVWYWx1ZUR0bxIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgB",
|
||||
"IAEoCRIWCg5hdHRyaWJ1dGVfcGF0aBgCIAEoCRIWCg5hdHRyaWJ1dGVfbmFt",
|
||||
"ZRgDIAEoCRI1CgV2YWx1ZRgEIAEoCzImLnNjYWRhYnJpZGdlLnNpdGVjb21t",
|
||||
"YW5kLnYxLkxvb3NlVmFsdWUSDwoHcXVhbGl0eRgFIAEoCRItCgl0aW1lc3Rh",
|
||||
"bXAYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIq8FChJEZWJ1",
|
||||
"Z0FsYXJtU3RhdGVEdG8SHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASABKAkS",
|
||||
"EgoKYWxhcm1fbmFtZRgCIAEoCRI4CgVzdGF0ZRgDIAEoDjIpLnNjYWRhYnJp",
|
||||
"ZGdlLnNpdGVjb21tYW5kLnYxLkFsYXJtU3RhdGVEdG8SEAoIcHJpb3JpdHkY",
|
||||
"BCABKAUSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp",
|
||||
"bWVzdGFtcBI4CgVsZXZlbBgGIAEoDjIpLnNjYWRhYnJpZGdlLnNpdGVjb21t",
|
||||
"YW5kLnYxLkFsYXJtTGV2ZWxEdG8SDwoHbWVzc2FnZRgHIAEoCRI2CgRraW5k",
|
||||
"GAggASgOMiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuQWxhcm1LaW5k",
|
||||
"RHRvEkUKCWNvbmRpdGlvbhgJIAEoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21t",
|
||||
"YW5kLnYxLkFsYXJtQ29uZGl0aW9uU3RhdGVEdG8SGAoQc291cmNlX3JlZmVy",
|
||||
"ZW5jZRgKIAEoCRIXCg9hbGFybV90eXBlX25hbWUYCyABKAkSEAoIY2F0ZWdv",
|
||||
"cnkYDCABKAkSFQoNb3BlcmF0b3JfdXNlchgNIAEoCRIYChBvcGVyYXRvcl9j",
|
||||
"b21tZW50GA4gASgJEjcKE29yaWdpbmFsX3JhaXNlX3RpbWUYDyABKAsyGi5n",
|
||||
"b29nbGUucHJvdG9idWYuVGltZXN0YW1wEhUKDWN1cnJlbnRfdmFsdWUYECAB",
|
||||
"KAkSEwoLbGltaXRfdmFsdWUYESABKAkSJAocbmF0aXZlX3NvdXJjZV9jYW5v",
|
||||
"bmljYWxfbmFtZRgSIAEoCRIhChlpc19jb25maWd1cmVkX3BsYWNlaG9sZGVy",
|
||||
"GBMgASgIIpwCChREZWJ1Z1ZpZXdTbmFwc2hvdER0bxIcChRpbnN0YW5jZV91",
|
||||
"bmlxdWVfbmFtZRgBIAEoCRJMChBhdHRyaWJ1dGVfdmFsdWVzGAIgAygLMjIu",
|
||||
"c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVidWdBdHRyaWJ1dGVWYWx1",
|
||||
"ZUR0bxJECgxhbGFybV9zdGF0ZXMYAyADKAsyLi5zY2FkYWJyaWRnZS5zaXRl",
|
||||
"Y29tbWFuZC52MS5EZWJ1Z0FsYXJtU3RhdGVEdG8SNgoSc25hcHNob3RfdGlt",
|
||||
"ZXN0YW1wGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIaChJp",
|
||||
"bnN0YW5jZV9ub3RfZm91bmQYBSABKAgi8AIKDFF1ZXJ5UmVxdWVzdBJOCg9l",
|
||||
"dmVudF9sb2dfcXVlcnkYASABKAsyMy5zY2FkYWJyaWRnZS5zaXRlY29tbWFu",
|
||||
"ZC52MS5FdmVudExvZ1F1ZXJ5UmVxdWVzdER0b0gAEk0KDmRlYnVnX3NuYXBz",
|
||||
"aG90GAIgASgLMjMuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVidWdT",
|
||||
"bmFwc2hvdFJlcXVlc3REdG9IABJYChRzdWJzY3JpYmVfZGVidWdfdmlldxgD",
|
||||
"IAEoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlN1YnNjcmliZURl",
|
||||
"YnVnVmlld1JlcXVlc3REdG9IABJcChZ1bnN1YnNjcmliZV9kZWJ1Z192aWV3",
|
||||
"GAQgASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVW5zdWJzY3Jp",
|
||||
"YmVEZWJ1Z1ZpZXdSZXF1ZXN0RHRvSABCCQoHY29tbWFuZCKRAgoKUXVlcnlS",
|
||||
"ZXBseRJPCg9ldmVudF9sb2dfcXVlcnkYASABKAsyNC5zY2FkYWJyaWRnZS5z",
|
||||
"aXRlY29tbWFuZC52MS5FdmVudExvZ1F1ZXJ5UmVzcG9uc2VEdG9IABJPChNk",
|
||||
"ZWJ1Z192aWV3X3NuYXBzaG90GAIgASgLMjAuc2NhZGFicmlkZ2Uuc2l0ZWNv",
|
||||
"bW1hbmQudjEuRGVidWdWaWV3U25hcHNob3REdG9IABJYChZ1bnN1YnNjcmli",
|
||||
"ZV9kZWJ1Z192aWV3GAMgASgLMjYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu",
|
||||
"djEuVW5zdWJzY3JpYmVEZWJ1Z1ZpZXdBY2tEdG9IAEIHCgVyZXBseSKeAQoc",
|
||||
"UGFya2VkTWVzc2FnZVF1ZXJ5UmVxdWVzdER0bxIWCg5jb3JyZWxhdGlvbl9p",
|
||||
"ZBgBIAEoCRIPCgdzaXRlX2lkGAIgASgJEhMKC3BhZ2VfbnVtYmVyGAMgASgF",
|
||||
"EhEKCXBhZ2Vfc2l6ZRgEIAEoBRItCgl0aW1lc3RhbXAYBSABKAsyGi5nb29n",
|
||||
"bGUucHJvdG9idWYuVGltZXN0YW1wIvICChVQYXJrZWRNZXNzYWdlRW50cnlE",
|
||||
"dG8SEgoKbWVzc2FnZV9pZBgBIAEoCRIVCg10YXJnZXRfc3lzdGVtGAIgASgJ",
|
||||
"EhMKC21ldGhvZF9uYW1lGAMgASgJEhUKDWVycm9yX21lc3NhZ2UYBCABKAkS",
|
||||
"FQoNYXR0ZW1wdF9jb3VudBgFIAEoBRI2ChJvcmlnaW5hbF90aW1lc3RhbXAY",
|
||||
"BiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjoKFmxhc3RfYXR0",
|
||||
"ZW1wdF90aW1lc3RhbXAYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0",
|
||||
"YW1wEhQKDG1heF9hdHRlbXB0cxgIIAEoBRJICghjYXRlZ29yeRgJIAEoDjI2",
|
||||
"LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlN0b3JlQW5kRm9yd2FyZENh",
|
||||
"dGVnb3J5RHRvEhcKD29yaWdpbl9pbnN0YW5jZRgKIAEoCSKhAgodUGFya2Vk",
|
||||
"TWVzc2FnZVF1ZXJ5UmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASAB",
|
||||
"KAkSDwoHc2l0ZV9pZBgCIAEoCRJDCghtZXNzYWdlcxgDIAMoCzIxLnNjYWRh",
|
||||
"YnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VFbnRyeUR0bxIT",
|
||||
"Cgt0b3RhbF9jb3VudBgEIAEoBRITCgtwYWdlX251bWJlchgFIAEoBRIRCglw",
|
||||
"YWdlX3NpemUYBiABKAUSDwoHc3VjY2VzcxgHIAEoCBIVCg1lcnJvcl9tZXNz",
|
||||
"YWdlGAggASgJEi0KCXRpbWVzdGFtcBgJIAEoCzIaLmdvb2dsZS5wcm90b2J1",
|
||||
"Zi5UaW1lc3RhbXAiigEKHFBhcmtlZE1lc3NhZ2VSZXRyeVJlcXVlc3REdG8S",
|
||||
"FgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgCIAEoCRISCgpt",
|
||||
"ZXNzYWdlX2lkGAMgASgJEi0KCXRpbWVzdGFtcBgEIAEoCzIaLmdvb2dsZS5w",
|
||||
"cm90b2J1Zi5UaW1lc3RhbXAiXwodUGFya2VkTWVzc2FnZVJldHJ5UmVzcG9u",
|
||||
"c2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3VjY2VzcxgCIAEo",
|
||||
"CBIVCg1lcnJvcl9tZXNzYWdlGAMgASgJIowBCh5QYXJrZWRNZXNzYWdlRGlz",
|
||||
"Y2FyZFJlcXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc2l0",
|
||||
"ZV9pZBgCIAEoCRISCgptZXNzYWdlX2lkGAMgASgJEi0KCXRpbWVzdGFtcBgE",
|
||||
"IAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiYQofUGFya2VkTWVz",
|
||||
"c2FnZURpc2NhcmRSZXNwb25zZUR0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEo",
|
||||
"CRIPCgdzdWNjZXNzGAIgASgIEhUKDWVycm9yX21lc3NhZ2UYAyABKAkiTwoX",
|
||||
"UmV0cnlQYXJrZWRPcGVyYXRpb25EdG8SFgoOY29ycmVsYXRpb25faWQYASAB",
|
||||
"KAkSHAoUdHJhY2tlZF9vcGVyYXRpb25faWQYAiABKAkiUQoZRGlzY2FyZFBh",
|
||||
"cmtlZE9wZXJhdGlvbkR0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIcChR0",
|
||||
"cmFja2VkX29wZXJhdGlvbl9pZBgCIAEoCSJdChtQYXJrZWRPcGVyYXRpb25B",
|
||||
"Y3Rpb25BY2tEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHYXBwbGll",
|
||||
"ZBgCIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMgASgJIt4DCg1QYXJrZWRSZXF1",
|
||||
"ZXN0ElgKFHBhcmtlZF9tZXNzYWdlX3F1ZXJ5GAEgASgLMjguc2NhZGFicmlk",
|
||||
"Z2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZVF1ZXJ5UmVxdWVzdER0",
|
||||
"b0gAElgKFHBhcmtlZF9tZXNzYWdlX3JldHJ5GAIgASgLMjguc2NhZGFicmlk",
|
||||
"Z2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZVJldHJ5UmVxdWVzdER0",
|
||||
"b0gAElwKFnBhcmtlZF9tZXNzYWdlX2Rpc2NhcmQYAyABKAsyOi5zY2FkYWJy",
|
||||
"aWRnZS5zaXRlY29tbWFuZC52MS5QYXJrZWRNZXNzYWdlRGlzY2FyZFJlcXVl",
|
||||
"c3REdG9IABJVChZyZXRyeV9wYXJrZWRfb3BlcmF0aW9uGAQgASgLMjMuc2Nh",
|
||||
"ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUmV0cnlQYXJrZWRPcGVyYXRpb25E",
|
||||
"dG9IABJZChhkaXNjYXJkX3BhcmtlZF9vcGVyYXRpb24YBSABKAsyNS5zY2Fk",
|
||||
"YWJyaWRnZS5zaXRlY29tbWFuZC52MS5EaXNjYXJkUGFya2VkT3BlcmF0aW9u",
|
||||
"RHRvSABCCQoHY29tbWFuZCKHAwoLUGFya2VkUmVwbHkSWQoUcGFya2VkX21l",
|
||||
"c3NhZ2VfcXVlcnkYASABKAsyOS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52",
|
||||
"MS5QYXJrZWRNZXNzYWdlUXVlcnlSZXNwb25zZUR0b0gAElkKFHBhcmtlZF9t",
|
||||
"ZXNzYWdlX3JldHJ5GAIgASgLMjkuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu",
|
||||
"djEuUGFya2VkTWVzc2FnZVJldHJ5UmVzcG9uc2VEdG9IABJdChZwYXJrZWRf",
|
||||
"bWVzc2FnZV9kaXNjYXJkGAMgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h",
|
||||
"bmQudjEuUGFya2VkTWVzc2FnZURpc2NhcmRSZXNwb25zZUR0b0gAEloKF3Bh",
|
||||
"cmtlZF9vcGVyYXRpb25fYWN0aW9uGAQgASgLMjcuc2NhZGFicmlkZ2Uuc2l0",
|
||||
"ZWNvbW1hbmQudjEuUGFya2VkT3BlcmF0aW9uQWN0aW9uQWNrRHRvSABCBwoF",
|
||||
"cmVwbHki/AEKFVJvdXRlVG9DYWxsUmVxdWVzdER0bxIWCg5jb3JyZWxhdGlv",
|
||||
"bl9pZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgCIAEoCRITCgtz",
|
||||
"Y3JpcHRfbmFtZRgDIAEoCRI9CgpwYXJhbWV0ZXJzGAQgASgLMikuc2NhZGFi",
|
||||
"cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZU1hcBItCgl0aW1lc3Rh",
|
||||
"bXAYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKE3BhcmVu",
|
||||
"dF9leGVjdXRpb25faWQYBiABKAkSDQoFdHJhY2UYByABKAgikgIKFlJvdXRl",
|
||||
"VG9DYWxsUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoH",
|
||||
"c3VjY2VzcxgCIAEoCBI8CgxyZXR1cm5fdmFsdWUYAyABKAsyJi5zY2FkYWJy",
|
||||
"aWRnZS5zaXRlY29tbWFuZC52MS5Mb29zZVZhbHVlEhUKDWVycm9yX21lc3Nh",
|
||||
"Z2UYBCABKAkSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVm",
|
||||
"LlRpbWVzdGFtcBIaChJjaGlsZF9leGVjdXRpb25faWQYBiABKAkSLwoMdHJh",
|
||||
"Y2VfZXZlbnRzGAcgAygLMhkuc2l0ZXN0cmVhbS5BdWRpdEV2ZW50RHRvIrsB",
|
||||
"Ch5Sb3V0ZVRvR2V0QXR0cmlidXRlc1JlcXVlc3REdG8SFgoOY29ycmVsYXRp",
|
||||
"b25faWQYASABKAkSHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYAiABKAkSFwoP",
|
||||
"YXR0cmlidXRlX25hbWVzGAMgAygJEi0KCXRpbWVzdGFtcBgEIAEoCzIaLmdv",
|
||||
"b2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGwoTcGFyZW50X2V4ZWN1dGlvbl9p",
|
||||
"ZBgFIAEoCSLLAQofUm91dGVUb0dldEF0dHJpYnV0ZXNSZXNwb25zZUR0bxIW",
|
||||
"Cg5jb3JyZWxhdGlvbl9pZBgBIAEoCRI5CgZ2YWx1ZXMYAiABKAsyKS5zY2Fk",
|
||||
"YWJyaWRnZS5zaXRlY29tbWFuZC52MS5Mb29zZVZhbHVlTWFwEg8KB3N1Y2Nl",
|
||||
"c3MYAyABKAgSFQoNZXJyb3JfbWVzc2FnZRgEIAEoCRItCgl0aW1lc3RhbXAY",
|
||||
"BSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wItQCCh5Sb3V0ZVRv",
|
||||
"U2V0QXR0cmlidXRlc1JlcXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQYASAB",
|
||||
"KAkSHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYAiABKAkSaQoQYXR0cmlidXRl",
|
||||
"X3ZhbHVlcxgDIAMoCzJPLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJv",
|
||||
"dXRlVG9TZXRBdHRyaWJ1dGVzUmVxdWVzdER0by5BdHRyaWJ1dGVWYWx1ZXNF",
|
||||
"bnRyeRItCgl0aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGlt",
|
||||
"ZXN0YW1wEhsKE3BhcmVudF9leGVjdXRpb25faWQYBSABKAkSDQoFdHJhY2UY",
|
||||
"BiABKAgaNgoUQXR0cmlidXRlVmFsdWVzRW50cnkSCwoDa2V5GAEgASgJEg0K",
|
||||
"BXZhbHVlGAIgASgJOgI4ASKQAQofUm91dGVUb1NldEF0dHJpYnV0ZXNSZXNw",
|
||||
"b25zZUR0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdzdWNjZXNzGAIg",
|
||||
"ASgIEhUKDWVycm9yX21lc3NhZ2UYAyABKAkSLQoJdGltZXN0YW1wGAQgASgL",
|
||||
"MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCLDAgohUm91dGVUb1dhaXRG",
|
||||
"b3JBdHRyaWJ1dGVSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJ",
|
||||
"EhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAIgASgJEhYKDmF0dHJpYnV0ZV9u",
|
||||
"YW1lGAMgASgJEjoKFHRhcmdldF92YWx1ZV9lbmNvZGVkGAQgASgLMhwuZ29v",
|
||||
"Z2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEioKB3RpbWVvdXQYBSABKAsyGS5n",
|
||||
"b29nbGUucHJvdG9idWYuRHVyYXRpb24SLQoJdGltZXN0YW1wGAYgASgLMhou",
|
||||
"Z29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhlY3V0aW9u",
|
||||
"X2lkGAcgASgJEhwKFHJlcXVpcmVfZ29vZF9xdWFsaXR5GAggASgIIv8BCiJS",
|
||||
"b3V0ZVRvV2FpdEZvckF0dHJpYnV0ZVJlc3BvbnNlRHRvEhYKDmNvcnJlbGF0",
|
||||
"aW9uX2lkGAEgASgJEg8KB21hdGNoZWQYAiABKAgSNQoFdmFsdWUYAyABKAsy",
|
||||
"Ji5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Mb29zZVZhbHVlEg8KB3F1",
|
||||
"YWxpdHkYBCABKAkSEQoJdGltZWRfb3V0GAUgASgIEg8KB3N1Y2Nlc3MYBiAB",
|
||||
"KAgSFQoNZXJyb3JfbWVzc2FnZRgHIAEoCRItCgl0aW1lc3RhbXAYCCABKAsy",
|
||||
"Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIokDCgxSb3V0ZVJlcXVlc3QS",
|
||||
"SgoNcm91dGVfdG9fY2FsbBgBIAEoCzIxLnNjYWRhYnJpZGdlLnNpdGVjb21t",
|
||||
"YW5kLnYxLlJvdXRlVG9DYWxsUmVxdWVzdER0b0gAEl0KF3JvdXRlX3RvX2dl",
|
||||
"dF9hdHRyaWJ1dGVzGAIgASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu",
|
||||
"djEuUm91dGVUb0dldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvSAASXQoXcm91dGVf",
|
||||
"dG9fc2V0X2F0dHJpYnV0ZXMYAyABKAsyOi5zY2FkYWJyaWRnZS5zaXRlY29t",
|
||||
"bWFuZC52MS5Sb3V0ZVRvU2V0QXR0cmlidXRlc1JlcXVlc3REdG9IABJkChty",
|
||||
"b3V0ZV90b193YWl0X2Zvcl9hdHRyaWJ1dGUYBCABKAsyPS5zY2FkYWJyaWRn",
|
||||
"ZS5zaXRlY29tbWFuZC52MS5Sb3V0ZVRvV2FpdEZvckF0dHJpYnV0ZVJlcXVl",
|
||||
"c3REdG9IAEIJCgdjb21tYW5kIokDCgpSb3V0ZVJlcGx5EksKDXJvdXRlX3Rv",
|
||||
"X2NhbGwYASABKAsyMi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Sb3V0",
|
||||
"ZVRvQ2FsbFJlc3BvbnNlRHRvSAASXgoXcm91dGVfdG9fZ2V0X2F0dHJpYnV0",
|
||||
"ZXMYAiABKAsyOy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Sb3V0ZVRv",
|
||||
"R2V0QXR0cmlidXRlc1Jlc3BvbnNlRHRvSAASXgoXcm91dGVfdG9fc2V0X2F0",
|
||||
"dHJpYnV0ZXMYAyABKAsyOy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5S",
|
||||
"b3V0ZVRvU2V0QXR0cmlidXRlc1Jlc3BvbnNlRHRvSAASZQobcm91dGVfdG9f",
|
||||
"d2FpdF9mb3JfYXR0cmlidXRlGAQgASgLMj4uc2NhZGFicmlkZ2Uuc2l0ZWNv",
|
||||
"bW1hbmQudjEuUm91dGVUb1dhaXRGb3JBdHRyaWJ1dGVSZXNwb25zZUR0b0gA",
|
||||
"QgcKBXJlcGx5IkEKFlRyaWdnZXJTaXRlRmFpbG92ZXJEdG8SFgoOY29ycmVs",
|
||||
"YXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgCIAEoCSJtChJTaXRlRmFpbG92",
|
||||
"ZXJBY2tEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSEAoIYWNjZXB0ZWQY",
|
||||
"AiABKAgSFgoOdGFyZ2V0X2FkZHJlc3MYAyABKAkSFQoNZXJyb3JfbWVzc2Fn",
|
||||
"ZRgEIAEoCSrLAQoTRGVwbG95bWVudFN0YXR1c0R0bxIlCiFERVBMT1lNRU5U",
|
||||
"X1NUQVRVU19EVE9fVU5TUEVDSUZJRUQQABIhCh1ERVBMT1lNRU5UX1NUQVRV",
|
||||
"U19EVE9fUEVORElORxABEiUKIURFUExPWU1FTlRfU1RBVFVTX0RUT19JTl9Q",
|
||||
"Uk9HUkVTUxACEiEKHURFUExPWU1FTlRfU1RBVFVTX0RUT19TVUNDRVNTEAMS",
|
||||
"IAocREVQTE9ZTUVOVF9TVEFUVVNfRFRPX0ZBSUxFRBAEKsQBChJCcm93c2VO",
|
||||
"b2RlQ2xhc3NEdG8SJQohQlJPV1NFX05PREVfQ0xBU1NfRFRPX1VOU1BFQ0lG",
|
||||
"SUVEEAASIAocQlJPV1NFX05PREVfQ0xBU1NfRFRPX09CSkVDVBABEiIKHkJS",
|
||||
"T1dTRV9OT0RFX0NMQVNTX0RUT19WQVJJQUJMRRACEiAKHEJST1dTRV9OT0RF",
|
||||
"X0NMQVNTX0RUT19NRVRIT0QQAxIfChtCUk9XU0VfTk9ERV9DTEFTU19EVE9f",
|
||||
"T1RIRVIQBCqhAgoUQnJvd3NlRmFpbHVyZUtpbmREdG8SJwojQlJPV1NFX0ZB",
|
||||
"SUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQABIwCixCUk9XU0VfRkFJTFVS",
|
||||
"RV9LSU5EX0RUT19DT05ORUNUSU9OX05PVF9GT1VORBABEjQKMEJST1dTRV9G",
|
||||
"QUlMVVJFX0tJTkRfRFRPX0NPTk5FQ1RJT05fTk9UX0NPTk5FQ1RFRBACEikK",
|
||||
"JUJST1dTRV9GQUlMVVJFX0tJTkRfRFRPX05PVF9CUk9XU0FCTEUQAxIjCh9C",
|
||||
"Uk9XU0VfRkFJTFVSRV9LSU5EX0RUT19USU1FT1VUEAQSKAokQlJPV1NFX0ZB",
|
||||
"SUxVUkVfS0lORF9EVE9fU0VSVkVSX0VSUk9SEAUqqgIKG1JlYWRUYWdWYWx1",
|
||||
"ZXNGYWlsdXJlS2luZER0bxIwCixSRUFEX1RBR19WQUxVRVNfRkFJTFVSRV9L",
|
||||
"SU5EX0RUT19VTlNQRUNJRklFRBAAEjkKNVJFQURfVEFHX1ZBTFVFU19GQUlM",
|
||||
"VVJFX0tJTkRfRFRPX0NPTk5FQ1RJT05fTk9UX0ZPVU5EEAESPQo5UkVBRF9U",
|
||||
"QUdfVkFMVUVTX0ZBSUxVUkVfS0lORF9EVE9fQ09OTkVDVElPTl9OT1RfQ09O",
|
||||
"TkVDVEVEEAISLAooUkVBRF9UQUdfVkFMVUVTX0ZBSUxVUkVfS0lORF9EVE9f",
|
||||
"VElNRU9VVBADEjEKLVJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJTkRfRFRP",
|
||||
"X1NFUlZFUl9FUlJPUhAEKpMCChRWZXJpZnlGYWlsdXJlS2luZER0bxInCiNW",
|
||||
"RVJJRllfRkFJTFVSRV9LSU5EX0RUT19VTlNQRUNJRklFRBAAEicKI1ZFUklG",
|
||||
"WV9GQUlMVVJFX0tJTkRfRFRPX1VOUkVBQ0hBQkxFEAESJwojVkVSSUZZX0ZB",
|
||||
"SUxVUkVfS0lORF9EVE9fQVVUSF9GQUlMRUQQAhIxCi1WRVJJRllfRkFJTFVS",
|
||||
"RV9LSU5EX0RUT19VTlRSVVNURURfQ0VSVElGSUNBVEUQAxIjCh9WRVJJRllf",
|
||||
"RkFJTFVSRV9LSU5EX0RUT19USU1FT1VUEAQSKAokVkVSSUZZX0ZBSUxVUkVf",
|
||||
"S0lORF9EVE9fU0VSVkVSX0VSUk9SEAUq5QEKGlN0b3JlQW5kRm9yd2FyZENh",
|
||||
"dGVnb3J5RHRvEi4KKlNUT1JFX0FORF9GT1JXQVJEX0NBVEVHT1JZX0RUT19V",
|
||||
"TlNQRUNJRklFRBAAEjIKLlNUT1JFX0FORF9GT1JXQVJEX0NBVEVHT1JZX0RU",
|
||||
"T19FWFRFUk5BTF9TWVNURU0QARIvCitTVE9SRV9BTkRfRk9SV0FSRF9DQVRF",
|
||||
"R09SWV9EVE9fTk9USUZJQ0FUSU9OEAISMgouU1RPUkVfQU5EX0ZPUldBUkRf",
|
||||
"Q0FURUdPUllfRFRPX0NBQ0hFRF9EQl9XUklURRADKmgKDUFsYXJtU3RhdGVE",
|
||||
"dG8SHwobQUxBUk1fU1RBVEVfRFRPX1VOU1BFQ0lGSUVEEAASGgoWQUxBUk1f",
|
||||
"U1RBVEVfRFRPX0FDVElWRRABEhoKFkFMQVJNX1NUQVRFX0RUT19OT1JNQUwQ",
|
||||
"Aiq5AQoNQWxhcm1MZXZlbER0bxIfChtBTEFSTV9MRVZFTF9EVE9fVU5TUEVD",
|
||||
"SUZJRUQQABIYChRBTEFSTV9MRVZFTF9EVE9fTk9ORRABEhcKE0FMQVJNX0xF",
|
||||
"VkVMX0RUT19MT1cQAhIbChdBTEFSTV9MRVZFTF9EVE9fTE9XX0xPVxADEhgK",
|
||||
"FEFMQVJNX0xFVkVMX0RUT19ISUdIEAQSHQoZQUxBUk1fTEVWRUxfRFRPX0hJ",
|
||||
"R0hfSElHSBAFKpIBCgxBbGFybUtpbmREdG8SHgoaQUxBUk1fS0lORF9EVE9f",
|
||||
"VU5TUEVDSUZJRUQQABIbChdBTEFSTV9LSU5EX0RUT19DT01QVVRFRBABEiAK",
|
||||
"HEFMQVJNX0tJTkRfRFRPX05BVElWRV9PUENfVUEQAhIjCh9BTEFSTV9LSU5E",
|
||||
"X0RUT19OQVRJVkVfTVhfQUNDRVNTEAMq6AEKE0FsYXJtU2hlbHZlU3RhdGVE",
|
||||
"dG8SJgoiQUxBUk1fU0hFTFZFX1NUQVRFX0RUT19VTlNQRUNJRklFRBAAEiQK",
|
||||
"IEFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVU5TSEVMVkVEEAESKwonQUxBUk1f",
|
||||
"U0hFTFZFX1NUQVRFX0RUT19PTkVfU0hPVF9TSEVMVkVEEAISKAokQUxBUk1f",
|
||||
"U0hFTFZFX1NUQVRFX0RUT19USU1FRF9TSEVMVkVEEAMSLAooQUxBUk1fU0hF",
|
||||
"TFZFX1NUQVRFX0RUT19QRVJNQU5FTlRfU0hFTFZFRBAEMoQFChJTaXRlQ29t",
|
||||
"bWFuZFNlcnZpY2USbAoQRXhlY3V0ZUxpZmVjeWNsZRIsLnNjYWRhYnJpZGdl",
|
||||
"LnNpdGVjb21tYW5kLnYxLkxpZmVjeWNsZVJlcXVlc3QaKi5zY2FkYWJyaWRn",
|
||||
"ZS5zaXRlY29tbWFuZC52MS5MaWZlY3ljbGVSZXBseRJgCgxFeGVjdXRlT3Bj",
|
||||
"VWESKC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5PcGNVYVJlcXVlc3Qa",
|
||||
"Ji5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5PcGNVYVJlcGx5EmAKDEV4",
|
||||
"ZWN1dGVRdWVyeRIoLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlF1ZXJ5",
|
||||
"UmVxdWVzdBomLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlF1ZXJ5UmVw",
|
||||
"bHkSYwoNRXhlY3V0ZVBhcmtlZBIpLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k",
|
||||
"LnYxLlBhcmtlZFJlcXVlc3QaJy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52",
|
||||
"MS5QYXJrZWRSZXBseRJgCgxFeGVjdXRlUm91dGUSKC5zY2FkYWJyaWRnZS5z",
|
||||
"aXRlY29tbWFuZC52MS5Sb3V0ZVJlcXVlc3QaJi5zY2FkYWJyaWRnZS5zaXRl",
|
||||
"Y29tbWFuZC52MS5Sb3V0ZVJlcGx5EnUKD1RyaWdnZXJGYWlsb3ZlchIyLnNj",
|
||||
"YWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlRyaWdnZXJTaXRlRmFpbG92ZXJE",
|
||||
"dG8aLi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5TaXRlRmFpbG92ZXJB",
|
||||
"Y2tEdG9CK6oCKFpCLk1PTS5XVy5TY2FkYUJyaWRnZS5Db21tdW5pY2F0aW9u",
|
||||
"LkdycGNiBnByb3RvMw=="));
|
||||
"ASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSFwoPc2VjcmV0c19y",
|
||||
"ZW1vdmVkGAcgAygJIpoEChBMaWZlY3ljbGVSZXF1ZXN0ElUKEnJlZnJlc2hf",
|
||||
"ZGVwbG95bWVudBgBIAEoCzI3LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYx",
|
||||
"LlJlZnJlc2hEZXBsb3ltZW50Q29tbWFuZER0b0gAEk8KD2VuYWJsZV9pbnN0",
|
||||
"YW5jZRgCIAEoCzI0LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkVuYWJs",
|
||||
"ZUluc3RhbmNlQ29tbWFuZER0b0gAElEKEGRpc2FibGVfaW5zdGFuY2UYAyAB",
|
||||
"KAsyNS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5EaXNhYmxlSW5zdGFu",
|
||||
"Y2VDb21tYW5kRHRvSAASTwoPZGVsZXRlX2luc3RhbmNlGAQgASgLMjQuc2Nh",
|
||||
"ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVsZXRlSW5zdGFuY2VDb21tYW5k",
|
||||
"RHRvSAASXAoWZGVwbG95bWVudF9zdGF0ZV9xdWVyeRgFIAEoCzI6LnNjYWRh",
|
||||
"YnJpZGdlLnNpdGVjb21tYW5kLnYxLkRlcGxveW1lbnRTdGF0ZVF1ZXJ5UmVx",
|
||||
"dWVzdER0b0gAElEKEGRlcGxveV9hcnRpZmFjdHMYBiABKAsyNS5zY2FkYWJy",
|
||||
"aWRnZS5zaXRlY29tbWFuZC52MS5EZXBsb3lBcnRpZmFjdHNDb21tYW5kRHRv",
|
||||
"SABCCQoHY29tbWFuZCKAAwoOTGlmZWN5Y2xlUmVwbHkSVAoRZGVwbG95bWVu",
|
||||
"dF9zdGF0dXMYASABKAsyNy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5E",
|
||||
"ZXBsb3ltZW50U3RhdHVzUmVzcG9uc2VEdG9IABJWChJpbnN0YW5jZV9saWZl",
|
||||
"Y3ljbGUYAiABKAsyOC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5JbnN0",
|
||||
"YW5jZUxpZmVjeWNsZVJlc3BvbnNlRHRvSAASXQoWZGVwbG95bWVudF9zdGF0",
|
||||
"ZV9xdWVyeRgDIAEoCzI7LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRl",
|
||||
"cGxveW1lbnRTdGF0ZVF1ZXJ5UmVzcG9uc2VEdG9IABJYChNhcnRpZmFjdF9k",
|
||||
"ZXBsb3ltZW50GAQgASgLMjkuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu",
|
||||
"QXJ0aWZhY3REZXBsb3ltZW50UmVzcG9uc2VEdG9IAEIHCgVyZXBseSJ8ChRC",
|
||||
"cm93c2VOb2RlQ29tbWFuZER0bxIXCg9jb25uZWN0aW9uX25hbWUYASABKAkS",
|
||||
"FgoOcGFyZW50X25vZGVfaWQYAiABKAkSGgoSY29udGludWF0aW9uX3Rva2Vu",
|
||||
"GAMgASgJEhcKD3NpdGVfaWRlbnRpZmllchgEIAEoCSKCAgoNQnJvd3NlTm9k",
|
||||
"ZUR0bxIPCgdub2RlX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRJC",
|
||||
"Cgpub2RlX2NsYXNzGAMgASgOMi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu",
|
||||
"djEuQnJvd3NlTm9kZUNsYXNzRHRvEhQKDGhhc19jaGlsZHJlbhgEIAEoCBIR",
|
||||
"CglkYXRhX3R5cGUYBSABKAkSLwoKdmFsdWVfcmFuaxgGIAEoCzIbLmdvb2ds",
|
||||
"ZS5wcm90b2J1Zi5JbnQzMlZhbHVlEiwKCHdyaXRhYmxlGAcgASgLMhouZ29v",
|
||||
"Z2xlLnByb3RvYnVmLkJvb2xWYWx1ZSJjChBCcm93c2VGYWlsdXJlRHRvEj4K",
|
||||
"BGtpbmQYASABKA4yMC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Ccm93",
|
||||
"c2VGYWlsdXJlS2luZER0bxIPCgdtZXNzYWdlGAIgASgJIsABChNCcm93c2VO",
|
||||
"b2RlUmVzdWx0RHRvEjsKCGNoaWxkcmVuGAEgAygLMikuc2NhZGFicmlkZ2Uu",
|
||||
"c2l0ZWNvbW1hbmQudjEuQnJvd3NlTm9kZUR0bxIRCgl0cnVuY2F0ZWQYAiAB",
|
||||
"KAgSPQoHZmFpbHVyZRgDIAEoCzIsLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k",
|
||||
"LnYxLkJyb3dzZUZhaWx1cmVEdG8SGgoSY29udGludWF0aW9uX3Rva2VuGAQg",
|
||||
"ASgJIocBChxTZWFyY2hBZGRyZXNzU3BhY2VDb21tYW5kRHRvEhcKD2Nvbm5l",
|
||||
"Y3Rpb25fbmFtZRgBIAEoCRINCgVxdWVyeRgCIAEoCRIRCgltYXhfZGVwdGgY",
|
||||
"AyABKAUSEwoLbWF4X3Jlc3VsdHMYBCABKAUSFwoPc2l0ZV9pZGVudGlmaWVy",
|
||||
"GAUgASgJIl0KFEFkZHJlc3NTcGFjZU1hdGNoRHRvEjcKBG5vZGUYASABKAsy",
|
||||
"KS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Ccm93c2VOb2RlRHRvEgwK",
|
||||
"BHBhdGgYAiABKAkitAEKG1NlYXJjaEFkZHJlc3NTcGFjZVJlc3VsdER0bxJB",
|
||||
"CgdtYXRjaGVzGAEgAygLMjAuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu",
|
||||
"QWRkcmVzc1NwYWNlTWF0Y2hEdG8SEwoLY2FwX3JlYWNoZWQYAiABKAgSPQoH",
|
||||
"ZmFpbHVyZRgDIAEoCzIsLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkJy",
|
||||
"b3dzZUZhaWx1cmVEdG8iRQoXUmVhZFRhZ1ZhbHVlc0NvbW1hbmREdG8SFwoP",
|
||||
"Y29ubmVjdGlvbl9uYW1lGAEgASgJEhEKCXRhZ19wYXRocxgCIAMoCSLEAQoR",
|
||||
"VGFnUmVhZE91dGNvbWVEdG8SEAoIdGFnX3BhdGgYASABKAkSDwoHc3VjY2Vz",
|
||||
"cxgCIAEoCBI1CgV2YWx1ZRgDIAEoCzImLnNjYWRhYnJpZGdlLnNpdGVjb21t",
|
||||
"YW5kLnYxLkxvb3NlVmFsdWUSDwoHcXVhbGl0eRgEIAEoCRItCgl0aW1lc3Rh",
|
||||
"bXAYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhUKDWVycm9y",
|
||||
"X21lc3NhZ2UYBiABKAkicQoXUmVhZFRhZ1ZhbHVlc0ZhaWx1cmVEdG8SRQoE",
|
||||
"a2luZBgBIAEoDjI3LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJlYWRU",
|
||||
"YWdWYWx1ZXNGYWlsdXJlS2luZER0bxIPCgdtZXNzYWdlGAIgASgJIp8BChZS",
|
||||
"ZWFkVGFnVmFsdWVzUmVzdWx0RHRvEj8KCG91dGNvbWVzGAEgAygLMi0uc2Nh",
|
||||
"ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVGFnUmVhZE91dGNvbWVEdG8SRAoH",
|
||||
"ZmFpbHVyZRgCIAEoCzIzLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJl",
|
||||
"YWRUYWdWYWx1ZXNGYWlsdXJlRHRvInMKGFZlcmlmeUVuZHBvaW50Q29tbWFu",
|
||||
"ZER0bxIXCg9jb25uZWN0aW9uX25hbWUYASABKAkSEAoIcHJvdG9jb2wYAiAB",
|
||||
"KAkSEwoLY29uZmlnX2pzb24YAyABKAkSFwoPc2l0ZV9pZGVudGlmaWVyGAQg",
|
||||
"ASgJIsMBChFTZXJ2ZXJDZXJ0SW5mb0R0bxISCgp0aHVtYnByaW50GAEgASgJ",
|
||||
"Eg8KB3N1YmplY3QYAiABKAkSDgoGaXNzdWVyGAMgASgJEjIKDm5vdF9iZWZv",
|
||||
"cmVfdXRjGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1u",
|
||||
"b3RfYWZ0ZXJfdXRjGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFt",
|
||||
"cBISCgpkZXJfYmFzZTY0GAYgASgJIlkKFlZlcmlmeUZhaWx1cmVLaW5kVmFs",
|
||||
"dWUSPwoFdmFsdWUYASABKA4yMC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52",
|
||||
"MS5WZXJpZnlGYWlsdXJlS2luZER0byLAAQoXVmVyaWZ5RW5kcG9pbnRSZXN1",
|
||||
"bHREdG8SDwoHc3VjY2VzcxgBIAEoCBJICgxmYWlsdXJlX2tpbmQYAiABKAsy",
|
||||
"Mi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5WZXJpZnlGYWlsdXJlS2lu",
|
||||
"ZFZhbHVlEg0KBWVycm9yGAMgASgJEjsKBGNlcnQYBCABKAsyLS5zY2FkYWJy",
|
||||
"aWRnZS5zaXRlY29tbWFuZC52MS5TZXJ2ZXJDZXJ0SW5mb0R0byJ1ChlUcnVz",
|
||||
"dFNlcnZlckNlcnRDb21tYW5kRHRvEhcKD2Nvbm5lY3Rpb25fbmFtZRgBIAEo",
|
||||
"CRISCgpkZXJfYmFzZTY0GAIgASgJEhIKCnRodW1icHJpbnQYAyABKAkSFwoP",
|
||||
"c2l0ZV9pZGVudGlmaWVyGAQgASgJIjQKGUxpc3RTZXJ2ZXJDZXJ0c0NvbW1h",
|
||||
"bmREdG8SFwoPc2l0ZV9pZGVudGlmaWVyGAEgASgJIkkKGlJlbW92ZVNlcnZl",
|
||||
"ckNlcnRDb21tYW5kRHRvEhIKCnRodW1icHJpbnQYASABKAkSFwoPc2l0ZV9p",
|
||||
"ZGVudGlmaWVyGAIgASgJIsIBChJUcnVzdGVkQ2VydEluZm9EdG8SEgoKdGh1",
|
||||
"bWJwcmludBgBIAEoCRIPCgdzdWJqZWN0GAIgASgJEg4KBmlzc3VlchgDIAEo",
|
||||
"CRIyCg5ub3RfYmVmb3JlX3V0YxgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5U",
|
||||
"aW1lc3RhbXASMQoNbm90X2FmdGVyX3V0YxgFIAEoCzIaLmdvb2dsZS5wcm90",
|
||||
"b2J1Zi5UaW1lc3RhbXASEAoIcmVqZWN0ZWQYBiABKAgiVwoWVHJ1c3RlZENl",
|
||||
"cnRJbmZvTGlzdER0bxI9CgVpdGVtcxgBIAMoCzIuLnNjYWRhYnJpZGdlLnNp",
|
||||
"dGVjb21tYW5kLnYxLlRydXN0ZWRDZXJ0SW5mb0R0byJ3ChJDZXJ0VHJ1c3RS",
|
||||
"ZXN1bHREdG8SDwoHc3VjY2VzcxgBIAEoCBINCgVlcnJvchgCIAEoCRJBCgVj",
|
||||
"ZXJ0cxgDIAEoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlRydXN0",
|
||||
"ZWRDZXJ0SW5mb0xpc3REdG8ivQEKEldyaXRlVGFnUmVxdWVzdER0bxIWCg5j",
|
||||
"b3JyZWxhdGlvbl9pZBgBIAEoCRIXCg9jb25uZWN0aW9uX25hbWUYAiABKAkS",
|
||||
"EAoIdGFnX3BhdGgYAyABKAkSNQoFdmFsdWUYBCABKAsyJi5zY2FkYWJyaWRn",
|
||||
"ZS5zaXRlY29tbWFuZC52MS5Mb29zZVZhbHVlEi0KCXRpbWVzdGFtcBgFIAEo",
|
||||
"CzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAEKE1dyaXRlVGFnUmVz",
|
||||
"cG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3VjY2VzcxgC",
|
||||
"IAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMgASgJEi0KCXRpbWVzdGFtcBgEIAEo",
|
||||
"CzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAioAUKDE9wY1VhUmVxdWVz",
|
||||
"dBJHCgticm93c2Vfbm9kZRgBIAEoCzIwLnNjYWRhYnJpZGdlLnNpdGVjb21t",
|
||||
"YW5kLnYxLkJyb3dzZU5vZGVDb21tYW5kRHRvSAASWAoUc2VhcmNoX2FkZHJl",
|
||||
"c3Nfc3BhY2UYAiABKAsyOC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5T",
|
||||
"ZWFyY2hBZGRyZXNzU3BhY2VDb21tYW5kRHRvSAASTgoPcmVhZF90YWdfdmFs",
|
||||
"dWVzGAMgASgLMjMuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUmVhZFRh",
|
||||
"Z1ZhbHVlc0NvbW1hbmREdG9IABJPCg92ZXJpZnlfZW5kcG9pbnQYBCABKAsy",
|
||||
"NC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5WZXJpZnlFbmRwb2ludENv",
|
||||
"bW1hbmREdG9IABJSChF0cnVzdF9zZXJ2ZXJfY2VydBgFIAEoCzI1LnNjYWRh",
|
||||
"YnJpZGdlLnNpdGVjb21tYW5kLnYxLlRydXN0U2VydmVyQ2VydENvbW1hbmRE",
|
||||
"dG9IABJSChFsaXN0X3NlcnZlcl9jZXJ0cxgGIAEoCzI1LnNjYWRhYnJpZGdl",
|
||||
"LnNpdGVjb21tYW5kLnYxLkxpc3RTZXJ2ZXJDZXJ0c0NvbW1hbmREdG9IABJU",
|
||||
"ChJyZW1vdmVfc2VydmVyX2NlcnQYByABKAsyNi5zY2FkYWJyaWRnZS5zaXRl",
|
||||
"Y29tbWFuZC52MS5SZW1vdmVTZXJ2ZXJDZXJ0Q29tbWFuZER0b0gAEkMKCXdy",
|
||||
"aXRlX3RhZxgIIAEoCzIuLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLldy",
|
||||
"aXRlVGFnUmVxdWVzdER0b0gAQgkKB2NvbW1hbmQi4QMKCk9wY1VhUmVwbHkS",
|
||||
"RgoLYnJvd3NlX25vZGUYASABKAsyLy5zY2FkYWJyaWRnZS5zaXRlY29tbWFu",
|
||||
"ZC52MS5Ccm93c2VOb2RlUmVzdWx0RHRvSAASVwoUc2VhcmNoX2FkZHJlc3Nf",
|
||||
"c3BhY2UYAiABKAsyNy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5TZWFy",
|
||||
"Y2hBZGRyZXNzU3BhY2VSZXN1bHREdG9IABJNCg9yZWFkX3RhZ192YWx1ZXMY",
|
||||
"AyABKAsyMi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5SZWFkVGFnVmFs",
|
||||
"dWVzUmVzdWx0RHRvSAASTgoPdmVyaWZ5X2VuZHBvaW50GAQgASgLMjMuc2Nh",
|
||||
"ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVmVyaWZ5RW5kcG9pbnRSZXN1bHRE",
|
||||
"dG9IABJECgpjZXJ0X3RydXN0GAUgASgLMi4uc2NhZGFicmlkZ2Uuc2l0ZWNv",
|
||||
"bW1hbmQudjEuQ2VydFRydXN0UmVzdWx0RHRvSAASRAoJd3JpdGVfdGFnGAYg",
|
||||
"ASgLMi8uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuV3JpdGVUYWdSZXNw",
|
||||
"b25zZUR0b0gAQgcKBXJlcGx5IsUCChdFdmVudExvZ1F1ZXJ5UmVxdWVzdER0",
|
||||
"bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdzaXRlX2lkGAIgASgJEigK",
|
||||
"BGZyb20YAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEiYKAnRv",
|
||||
"GAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBISCgpldmVudF90",
|
||||
"eXBlGAUgASgJEhAKCHNldmVyaXR5GAYgASgJEhMKC2luc3RhbmNlX2lkGAcg",
|
||||
"ASgJEhYKDmtleXdvcmRfZmlsdGVyGAggASgJEhoKEmNvbnRpbnVhdGlvbl90",
|
||||
"b2tlbhgJIAEoCRIRCglwYWdlX3NpemUYCiABKAUSLQoJdGltZXN0YW1wGAsg",
|
||||
"ASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK6AQoQRXZlbnRMb2dF",
|
||||
"bnRyeUR0bxIKCgJpZBgBIAEoCRItCgl0aW1lc3RhbXAYAiABKAsyGi5nb29n",
|
||||
"bGUucHJvdG9idWYuVGltZXN0YW1wEhIKCmV2ZW50X3R5cGUYAyABKAkSEAoI",
|
||||
"c2V2ZXJpdHkYBCABKAkSEwoLaW5zdGFuY2VfaWQYBSABKAkSDgoGc291cmNl",
|
||||
"GAYgASgJEg8KB21lc3NhZ2UYByABKAkSDwoHZGV0YWlscxgIIAEoCSKHAgoY",
|
||||
"RXZlbnRMb2dRdWVyeVJlc3BvbnNlRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEg",
|
||||
"ASgJEg8KB3NpdGVfaWQYAiABKAkSPQoHZW50cmllcxgDIAMoCzIsLnNjYWRh",
|
||||
"YnJpZGdlLnNpdGVjb21tYW5kLnYxLkV2ZW50TG9nRW50cnlEdG8SGgoSY29u",
|
||||
"dGludWF0aW9uX3Rva2VuGAQgASgJEhAKCGhhc19tb3JlGAUgASgIEg8KB3N1",
|
||||
"Y2Nlc3MYBiABKAgSFQoNZXJyb3JfbWVzc2FnZRgHIAEoCRItCgl0aW1lc3Rh",
|
||||
"bXAYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wImQKF0RlYnVn",
|
||||
"U25hcHNob3RSZXF1ZXN0RHRvEhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAEg",
|
||||
"ASgJEhYKDmNvcnJlbGF0aW9uX2lkGAIgASgJEhMKC2FsYXJtc19vbmx5GAMg",
|
||||
"ASgIIlQKHFN1YnNjcmliZURlYnVnVmlld1JlcXVlc3REdG8SHAoUaW5zdGFu",
|
||||
"Y2VfdW5pcXVlX25hbWUYASABKAkSFgoOY29ycmVsYXRpb25faWQYAiABKAki",
|
||||
"VgoeVW5zdWJzY3JpYmVEZWJ1Z1ZpZXdSZXF1ZXN0RHRvEhwKFGluc3RhbmNl",
|
||||
"X3VuaXF1ZV9uYW1lGAEgASgJEhYKDmNvcnJlbGF0aW9uX2lkGAIgASgJIhwK",
|
||||
"GlVuc3Vic2NyaWJlRGVidWdWaWV3QWNrRHRvItQBChZBbGFybUNvbmRpdGlv",
|
||||
"blN0YXRlRHRvEg4KBmFjdGl2ZRgBIAEoCBIUCgxhY2tub3dsZWRnZWQYAiAB",
|
||||
"KAgSLQoJY29uZmlybWVkGAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLkJvb2xW",
|
||||
"YWx1ZRI/CgZzaGVsdmUYBCABKA4yLy5zY2FkYWJyaWRnZS5zaXRlY29tbWFu",
|
||||
"ZC52MS5BbGFybVNoZWx2ZVN0YXRlRHRvEhIKCnN1cHByZXNzZWQYBSABKAgS",
|
||||
"EAoIc2V2ZXJpdHkYBiABKAUi3QEKFkRlYnVnQXR0cmlidXRlVmFsdWVEdG8S",
|
||||
"HAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASABKAkSFgoOYXR0cmlidXRlX3Bh",
|
||||
"dGgYAiABKAkSFgoOYXR0cmlidXRlX25hbWUYAyABKAkSNQoFdmFsdWUYBCAB",
|
||||
"KAsyJi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Mb29zZVZhbHVlEg8K",
|
||||
"B3F1YWxpdHkYBSABKAkSLQoJdGltZXN0YW1wGAYgASgLMhouZ29vZ2xlLnBy",
|
||||
"b3RvYnVmLlRpbWVzdGFtcCKvBQoSRGVidWdBbGFybVN0YXRlRHRvEhwKFGlu",
|
||||
"c3RhbmNlX3VuaXF1ZV9uYW1lGAEgASgJEhIKCmFsYXJtX25hbWUYAiABKAkS",
|
||||
"OAoFc3RhdGUYAyABKA4yKS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5B",
|
||||
"bGFybVN0YXRlRHRvEhAKCHByaW9yaXR5GAQgASgFEi0KCXRpbWVzdGFtcBgF",
|
||||
"IAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASOAoFbGV2ZWwYBiAB",
|
||||
"KA4yKS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5BbGFybUxldmVsRHRv",
|
||||
"Eg8KB21lc3NhZ2UYByABKAkSNgoEa2luZBgIIAEoDjIoLnNjYWRhYnJpZGdl",
|
||||
"LnNpdGVjb21tYW5kLnYxLkFsYXJtS2luZER0bxJFCgljb25kaXRpb24YCSAB",
|
||||
"KAsyMi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5BbGFybUNvbmRpdGlv",
|
||||
"blN0YXRlRHRvEhgKEHNvdXJjZV9yZWZlcmVuY2UYCiABKAkSFwoPYWxhcm1f",
|
||||
"dHlwZV9uYW1lGAsgASgJEhAKCGNhdGVnb3J5GAwgASgJEhUKDW9wZXJhdG9y",
|
||||
"X3VzZXIYDSABKAkSGAoQb3BlcmF0b3JfY29tbWVudBgOIAEoCRI3ChNvcmln",
|
||||
"aW5hbF9yYWlzZV90aW1lGA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVz",
|
||||
"dGFtcBIVCg1jdXJyZW50X3ZhbHVlGBAgASgJEhMKC2xpbWl0X3ZhbHVlGBEg",
|
||||
"ASgJEiQKHG5hdGl2ZV9zb3VyY2VfY2Fub25pY2FsX25hbWUYEiABKAkSIQoZ",
|
||||
"aXNfY29uZmlndXJlZF9wbGFjZWhvbGRlchgTIAEoCCKcAgoURGVidWdWaWV3",
|
||||
"U25hcHNob3REdG8SHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASABKAkSTAoQ",
|
||||
"YXR0cmlidXRlX3ZhbHVlcxgCIAMoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21t",
|
||||
"YW5kLnYxLkRlYnVnQXR0cmlidXRlVmFsdWVEdG8SRAoMYWxhcm1fc3RhdGVz",
|
||||
"GAMgAygLMi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVidWdBbGFy",
|
||||
"bVN0YXRlRHRvEjYKEnNuYXBzaG90X3RpbWVzdGFtcBgEIAEoCzIaLmdvb2ds",
|
||||
"ZS5wcm90b2J1Zi5UaW1lc3RhbXASGgoSaW5zdGFuY2Vfbm90X2ZvdW5kGAUg",
|
||||
"ASgIIvACCgxRdWVyeVJlcXVlc3QSTgoPZXZlbnRfbG9nX3F1ZXJ5GAEgASgL",
|
||||
"MjMuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXZlbnRMb2dRdWVyeVJl",
|
||||
"cXVlc3REdG9IABJNCg5kZWJ1Z19zbmFwc2hvdBgCIAEoCzIzLnNjYWRhYnJp",
|
||||
"ZGdlLnNpdGVjb21tYW5kLnYxLkRlYnVnU25hcHNob3RSZXF1ZXN0RHRvSAAS",
|
||||
"WAoUc3Vic2NyaWJlX2RlYnVnX3ZpZXcYAyABKAsyOC5zY2FkYWJyaWRnZS5z",
|
||||
"aXRlY29tbWFuZC52MS5TdWJzY3JpYmVEZWJ1Z1ZpZXdSZXF1ZXN0RHRvSAAS",
|
||||
"XAoWdW5zdWJzY3JpYmVfZGVidWdfdmlldxgEIAEoCzI6LnNjYWRhYnJpZGdl",
|
||||
"LnNpdGVjb21tYW5kLnYxLlVuc3Vic2NyaWJlRGVidWdWaWV3UmVxdWVzdER0",
|
||||
"b0gAQgkKB2NvbW1hbmQikQIKClF1ZXJ5UmVwbHkSTwoPZXZlbnRfbG9nX3F1",
|
||||
"ZXJ5GAEgASgLMjQuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXZlbnRM",
|
||||
"b2dRdWVyeVJlc3BvbnNlRHRvSAASTwoTZGVidWdfdmlld19zbmFwc2hvdBgC",
|
||||
"IAEoCzIwLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRlYnVnVmlld1Nu",
|
||||
"YXBzaG90RHRvSAASWAoWdW5zdWJzY3JpYmVfZGVidWdfdmlldxgDIAEoCzI2",
|
||||
"LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlVuc3Vic2NyaWJlRGVidWdW",
|
||||
"aWV3QWNrRHRvSABCBwoFcmVwbHkingEKHFBhcmtlZE1lc3NhZ2VRdWVyeVJl",
|
||||
"cXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgC",
|
||||
"IAEoCRITCgtwYWdlX251bWJlchgDIAEoBRIRCglwYWdlX3NpemUYBCABKAUS",
|
||||
"LQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFt",
|
||||
"cCLyAgoVUGFya2VkTWVzc2FnZUVudHJ5RHRvEhIKCm1lc3NhZ2VfaWQYASAB",
|
||||
"KAkSFQoNdGFyZ2V0X3N5c3RlbRgCIAEoCRITCgttZXRob2RfbmFtZRgDIAEo",
|
||||
"CRIVCg1lcnJvcl9tZXNzYWdlGAQgASgJEhUKDWF0dGVtcHRfY291bnQYBSAB",
|
||||
"KAUSNgoSb3JpZ2luYWxfdGltZXN0YW1wGAYgASgLMhouZ29vZ2xlLnByb3Rv",
|
||||
"YnVmLlRpbWVzdGFtcBI6ChZsYXN0X2F0dGVtcHRfdGltZXN0YW1wGAcgASgL",
|
||||
"MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIUCgxtYXhfYXR0ZW1wdHMY",
|
||||
"CCABKAUSSAoIY2F0ZWdvcnkYCSABKA4yNi5zY2FkYWJyaWRnZS5zaXRlY29t",
|
||||
"bWFuZC52MS5TdG9yZUFuZEZvcndhcmRDYXRlZ29yeUR0bxIXCg9vcmlnaW5f",
|
||||
"aW5zdGFuY2UYCiABKAkioQIKHVBhcmtlZE1lc3NhZ2VRdWVyeVJlc3BvbnNl",
|
||||
"RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkS",
|
||||
"QwoIbWVzc2FnZXMYAyADKAsyMS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52",
|
||||
"MS5QYXJrZWRNZXNzYWdlRW50cnlEdG8SEwoLdG90YWxfY291bnQYBCABKAUS",
|
||||
"EwoLcGFnZV9udW1iZXIYBSABKAUSEQoJcGFnZV9zaXplGAYgASgFEg8KB3N1",
|
||||
"Y2Nlc3MYByABKAgSFQoNZXJyb3JfbWVzc2FnZRgIIAEoCRItCgl0aW1lc3Rh",
|
||||
"bXAYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIooBChxQYXJr",
|
||||
"ZWRNZXNzYWdlUmV0cnlSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEg",
|
||||
"ASgJEg8KB3NpdGVfaWQYAiABKAkSEgoKbWVzc2FnZV9pZBgDIAEoCRItCgl0",
|
||||
"aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIl8K",
|
||||
"HVBhcmtlZE1lc3NhZ2VSZXRyeVJlc3BvbnNlRHRvEhYKDmNvcnJlbGF0aW9u",
|
||||
"X2lkGAEgASgJEg8KB3N1Y2Nlc3MYAiABKAgSFQoNZXJyb3JfbWVzc2FnZRgD",
|
||||
"IAEoCSKMAQoeUGFya2VkTWVzc2FnZURpc2NhcmRSZXF1ZXN0RHRvEhYKDmNv",
|
||||
"cnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkSEgoKbWVzc2Fn",
|
||||
"ZV9pZBgDIAEoCRItCgl0aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9i",
|
||||
"dWYuVGltZXN0YW1wImEKH1BhcmtlZE1lc3NhZ2VEaXNjYXJkUmVzcG9uc2VE",
|
||||
"dG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3VjY2VzcxgCIAEoCBIV",
|
||||
"Cg1lcnJvcl9tZXNzYWdlGAMgASgJIk8KF1JldHJ5UGFya2VkT3BlcmF0aW9u",
|
||||
"RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhwKFHRyYWNrZWRfb3BlcmF0",
|
||||
"aW9uX2lkGAIgASgJIlEKGURpc2NhcmRQYXJrZWRPcGVyYXRpb25EdG8SFgoO",
|
||||
"Y29ycmVsYXRpb25faWQYASABKAkSHAoUdHJhY2tlZF9vcGVyYXRpb25faWQY",
|
||||
"AiABKAkiXQobUGFya2VkT3BlcmF0aW9uQWN0aW9uQWNrRHRvEhYKDmNvcnJl",
|
||||
"bGF0aW9uX2lkGAEgASgJEg8KB2FwcGxpZWQYAiABKAgSFQoNZXJyb3JfbWVz",
|
||||
"c2FnZRgDIAEoCSLeAwoNUGFya2VkUmVxdWVzdBJYChRwYXJrZWRfbWVzc2Fn",
|
||||
"ZV9xdWVyeRgBIAEoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBh",
|
||||
"cmtlZE1lc3NhZ2VRdWVyeVJlcXVlc3REdG9IABJYChRwYXJrZWRfbWVzc2Fn",
|
||||
"ZV9yZXRyeRgCIAEoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBh",
|
||||
"cmtlZE1lc3NhZ2VSZXRyeVJlcXVlc3REdG9IABJcChZwYXJrZWRfbWVzc2Fn",
|
||||
"ZV9kaXNjYXJkGAMgASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu",
|
||||
"UGFya2VkTWVzc2FnZURpc2NhcmRSZXF1ZXN0RHRvSAASVQoWcmV0cnlfcGFy",
|
||||
"a2VkX29wZXJhdGlvbhgEIAEoCzIzLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k",
|
||||
"LnYxLlJldHJ5UGFya2VkT3BlcmF0aW9uRHRvSAASWQoYZGlzY2FyZF9wYXJr",
|
||||
"ZWRfb3BlcmF0aW9uGAUgASgLMjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu",
|
||||
"djEuRGlzY2FyZFBhcmtlZE9wZXJhdGlvbkR0b0gAQgkKB2NvbW1hbmQihwMK",
|
||||
"C1BhcmtlZFJlcGx5ElkKFHBhcmtlZF9tZXNzYWdlX3F1ZXJ5GAEgASgLMjku",
|
||||
"c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZVF1ZXJ5",
|
||||
"UmVzcG9uc2VEdG9IABJZChRwYXJrZWRfbWVzc2FnZV9yZXRyeRgCIAEoCzI5",
|
||||
"LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VSZXRy",
|
||||
"eVJlc3BvbnNlRHRvSAASXQoWcGFya2VkX21lc3NhZ2VfZGlzY2FyZBgDIAEo",
|
||||
"CzI7LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VE",
|
||||
"aXNjYXJkUmVzcG9uc2VEdG9IABJaChdwYXJrZWRfb3BlcmF0aW9uX2FjdGlv",
|
||||
"bhgEIAEoCzI3LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE9w",
|
||||
"ZXJhdGlvbkFjdGlvbkFja0R0b0gAQgcKBXJlcGx5IvwBChVSb3V0ZVRvQ2Fs",
|
||||
"bFJlcXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSHAoUaW5zdGFu",
|
||||
"Y2VfdW5pcXVlX25hbWUYAiABKAkSEwoLc2NyaXB0X25hbWUYAyABKAkSPQoK",
|
||||
"cGFyYW1ldGVycxgEIAEoCzIpLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYx",
|
||||
"Lkxvb3NlVmFsdWVNYXASLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnBy",
|
||||
"b3RvYnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhlY3V0aW9uX2lkGAYgASgJ",
|
||||
"Eg0KBXRyYWNlGAcgASgIIpICChZSb3V0ZVRvQ2FsbFJlc3BvbnNlRHRvEhYK",
|
||||
"DmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3N1Y2Nlc3MYAiABKAgSPAoMcmV0",
|
||||
"dXJuX3ZhbHVlGAMgASgLMiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu",
|
||||
"TG9vc2VWYWx1ZRIVCg1lcnJvcl9tZXNzYWdlGAQgASgJEi0KCXRpbWVzdGFt",
|
||||
"cBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGgoSY2hpbGRf",
|
||||
"ZXhlY3V0aW9uX2lkGAYgASgJEi8KDHRyYWNlX2V2ZW50cxgHIAMoCzIZLnNp",
|
||||
"dGVzdHJlYW0uQXVkaXRFdmVudER0byK7AQoeUm91dGVUb0dldEF0dHJpYnV0",
|
||||
"ZXNSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhwKFGluc3Rh",
|
||||
"bmNlX3VuaXF1ZV9uYW1lGAIgASgJEhcKD2F0dHJpYnV0ZV9uYW1lcxgDIAMo",
|
||||
"CRItCgl0aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0",
|
||||
"YW1wEhsKE3BhcmVudF9leGVjdXRpb25faWQYBSABKAkiywEKH1JvdXRlVG9H",
|
||||
"ZXRBdHRyaWJ1dGVzUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASAB",
|
||||
"KAkSOQoGdmFsdWVzGAIgASgLMikuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu",
|
||||
"djEuTG9vc2VWYWx1ZU1hcBIPCgdzdWNjZXNzGAMgASgIEhUKDWVycm9yX21l",
|
||||
"c3NhZ2UYBCABKAkSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3Rv",
|
||||
"YnVmLlRpbWVzdGFtcCLUAgoeUm91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0",
|
||||
"RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1",
|
||||
"ZV9uYW1lGAIgASgJEmkKEGF0dHJpYnV0ZV92YWx1ZXMYAyADKAsyTy5zY2Fk",
|
||||
"YWJyaWRnZS5zaXRlY29tbWFuZC52MS5Sb3V0ZVRvU2V0QXR0cmlidXRlc1Jl",
|
||||
"cXVlc3REdG8uQXR0cmlidXRlVmFsdWVzRW50cnkSLQoJdGltZXN0YW1wGAQg",
|
||||
"ASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhl",
|
||||
"Y3V0aW9uX2lkGAUgASgJEg0KBXRyYWNlGAYgASgIGjYKFEF0dHJpYnV0ZVZh",
|
||||
"bHVlc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEikAEK",
|
||||
"H1JvdXRlVG9TZXRBdHRyaWJ1dGVzUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRp",
|
||||
"b25faWQYASABKAkSDwoHc3VjY2VzcxgCIAEoCBIVCg1lcnJvcl9tZXNzYWdl",
|
||||
"GAMgASgJEi0KCXRpbWVzdGFtcBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5U",
|
||||
"aW1lc3RhbXAiwwIKIVJvdXRlVG9XYWl0Rm9yQXR0cmlidXRlUmVxdWVzdER0",
|
||||
"bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVf",
|
||||
"bmFtZRgCIAEoCRIWCg5hdHRyaWJ1dGVfbmFtZRgDIAEoCRI6ChR0YXJnZXRf",
|
||||
"dmFsdWVfZW5jb2RlZBgEIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdW",
|
||||
"YWx1ZRIqCgd0aW1lb3V0GAUgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0",
|
||||
"aW9uEi0KCXRpbWVzdGFtcBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l",
|
||||
"c3RhbXASGwoTcGFyZW50X2V4ZWN1dGlvbl9pZBgHIAEoCRIcChRyZXF1aXJl",
|
||||
"X2dvb2RfcXVhbGl0eRgIIAEoCCL/AQoiUm91dGVUb1dhaXRGb3JBdHRyaWJ1",
|
||||
"dGVSZXNwb25zZUR0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdtYXRj",
|
||||
"aGVkGAIgASgIEjUKBXZhbHVlGAMgASgLMiYuc2NhZGFicmlkZ2Uuc2l0ZWNv",
|
||||
"bW1hbmQudjEuTG9vc2VWYWx1ZRIPCgdxdWFsaXR5GAQgASgJEhEKCXRpbWVk",
|
||||
"X291dBgFIAEoCBIPCgdzdWNjZXNzGAYgASgIEhUKDWVycm9yX21lc3NhZ2UY",
|
||||
"ByABKAkSLQoJdGltZXN0YW1wGAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp",
|
||||
"bWVzdGFtcCKJAwoMUm91dGVSZXF1ZXN0EkoKDXJvdXRlX3RvX2NhbGwYASAB",
|
||||
"KAsyMS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Sb3V0ZVRvQ2FsbFJl",
|
||||
"cXVlc3REdG9IABJdChdyb3V0ZV90b19nZXRfYXR0cmlidXRlcxgCIAEoCzI6",
|
||||
"LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJvdXRlVG9HZXRBdHRyaWJ1",
|
||||
"dGVzUmVxdWVzdER0b0gAEl0KF3JvdXRlX3RvX3NldF9hdHRyaWJ1dGVzGAMg",
|
||||
"ASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb1NldEF0",
|
||||
"dHJpYnV0ZXNSZXF1ZXN0RHRvSAASZAobcm91dGVfdG9fd2FpdF9mb3JfYXR0",
|
||||
"cmlidXRlGAQgASgLMj0uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91",
|
||||
"dGVUb1dhaXRGb3JBdHRyaWJ1dGVSZXF1ZXN0RHRvSABCCQoHY29tbWFuZCKJ",
|
||||
"AwoKUm91dGVSZXBseRJLCg1yb3V0ZV90b19jYWxsGAEgASgLMjIuc2NhZGFi",
|
||||
"cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb0NhbGxSZXNwb25zZUR0b0gA",
|
||||
"El4KF3JvdXRlX3RvX2dldF9hdHRyaWJ1dGVzGAIgASgLMjsuc2NhZGFicmlk",
|
||||
"Z2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb0dldEF0dHJpYnV0ZXNSZXNwb25z",
|
||||
"ZUR0b0gAEl4KF3JvdXRlX3RvX3NldF9hdHRyaWJ1dGVzGAMgASgLMjsuc2Nh",
|
||||
"ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb1NldEF0dHJpYnV0ZXNS",
|
||||
"ZXNwb25zZUR0b0gAEmUKG3JvdXRlX3RvX3dhaXRfZm9yX2F0dHJpYnV0ZRgE",
|
||||
"IAEoCzI+LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJvdXRlVG9XYWl0",
|
||||
"Rm9yQXR0cmlidXRlUmVzcG9uc2VEdG9IAEIHCgVyZXBseSJBChZUcmlnZ2Vy",
|
||||
"U2l0ZUZhaWxvdmVyRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3Np",
|
||||
"dGVfaWQYAiABKAkibQoSU2l0ZUZhaWxvdmVyQWNrRHRvEhYKDmNvcnJlbGF0",
|
||||
"aW9uX2lkGAEgASgJEhAKCGFjY2VwdGVkGAIgASgIEhYKDnRhcmdldF9hZGRy",
|
||||
"ZXNzGAMgASgJEhUKDWVycm9yX21lc3NhZ2UYBCABKAkqywEKE0RlcGxveW1l",
|
||||
"bnRTdGF0dXNEdG8SJQohREVQTE9ZTUVOVF9TVEFUVVNfRFRPX1VOU1BFQ0lG",
|
||||
"SUVEEAASIQodREVQTE9ZTUVOVF9TVEFUVVNfRFRPX1BFTkRJTkcQARIlCiFE",
|
||||
"RVBMT1lNRU5UX1NUQVRVU19EVE9fSU5fUFJPR1JFU1MQAhIhCh1ERVBMT1lN",
|
||||
"RU5UX1NUQVRVU19EVE9fU1VDQ0VTUxADEiAKHERFUExPWU1FTlRfU1RBVFVT",
|
||||
"X0RUT19GQUlMRUQQBCrEAQoSQnJvd3NlTm9kZUNsYXNzRHRvEiUKIUJST1dT",
|
||||
"RV9OT0RFX0NMQVNTX0RUT19VTlNQRUNJRklFRBAAEiAKHEJST1dTRV9OT0RF",
|
||||
"X0NMQVNTX0RUT19PQkpFQ1QQARIiCh5CUk9XU0VfTk9ERV9DTEFTU19EVE9f",
|
||||
"VkFSSUFCTEUQAhIgChxCUk9XU0VfTk9ERV9DTEFTU19EVE9fTUVUSE9EEAMS",
|
||||
"HwobQlJPV1NFX05PREVfQ0xBU1NfRFRPX09USEVSEAQqoQIKFEJyb3dzZUZh",
|
||||
"aWx1cmVLaW5kRHRvEicKI0JST1dTRV9GQUlMVVJFX0tJTkRfRFRPX1VOU1BF",
|
||||
"Q0lGSUVEEAASMAosQlJPV1NFX0ZBSUxVUkVfS0lORF9EVE9fQ09OTkVDVElP",
|
||||
"Tl9OT1RfRk9VTkQQARI0CjBCUk9XU0VfRkFJTFVSRV9LSU5EX0RUT19DT05O",
|
||||
"RUNUSU9OX05PVF9DT05ORUNURUQQAhIpCiVCUk9XU0VfRkFJTFVSRV9LSU5E",
|
||||
"X0RUT19OT1RfQlJPV1NBQkxFEAMSIwofQlJPV1NFX0ZBSUxVUkVfS0lORF9E",
|
||||
"VE9fVElNRU9VVBAEEigKJEJST1dTRV9GQUlMVVJFX0tJTkRfRFRPX1NFUlZF",
|
||||
"Ul9FUlJPUhAFKqoCChtSZWFkVGFnVmFsdWVzRmFpbHVyZUtpbmREdG8SMAos",
|
||||
"UkVBRF9UQUdfVkFMVUVTX0ZBSUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQ",
|
||||
"ABI5CjVSRUFEX1RBR19WQUxVRVNfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNU",
|
||||
"SU9OX05PVF9GT1VORBABEj0KOVJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJ",
|
||||
"TkRfRFRPX0NPTk5FQ1RJT05fTk9UX0NPTk5FQ1RFRBACEiwKKFJFQURfVEFH",
|
||||
"X1ZBTFVFU19GQUlMVVJFX0tJTkRfRFRPX1RJTUVPVVQQAxIxCi1SRUFEX1RB",
|
||||
"R19WQUxVRVNfRkFJTFVSRV9LSU5EX0RUT19TRVJWRVJfRVJST1IQBCqTAgoU",
|
||||
"VmVyaWZ5RmFpbHVyZUtpbmREdG8SJwojVkVSSUZZX0ZBSUxVUkVfS0lORF9E",
|
||||
"VE9fVU5TUEVDSUZJRUQQABInCiNWRVJJRllfRkFJTFVSRV9LSU5EX0RUT19V",
|
||||
"TlJFQUNIQUJMRRABEicKI1ZFUklGWV9GQUlMVVJFX0tJTkRfRFRPX0FVVEhf",
|
||||
"RkFJTEVEEAISMQotVkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVU5UUlVTVEVE",
|
||||
"X0NFUlRJRklDQVRFEAMSIwofVkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVElN",
|
||||
"RU9VVBAEEigKJFZFUklGWV9GQUlMVVJFX0tJTkRfRFRPX1NFUlZFUl9FUlJP",
|
||||
"UhAFKuUBChpTdG9yZUFuZEZvcndhcmRDYXRlZ29yeUR0bxIuCipTVE9SRV9B",
|
||||
"TkRfRk9SV0FSRF9DQVRFR09SWV9EVE9fVU5TUEVDSUZJRUQQABIyCi5TVE9S",
|
||||
"RV9BTkRfRk9SV0FSRF9DQVRFR09SWV9EVE9fRVhURVJOQUxfU1lTVEVNEAES",
|
||||
"LworU1RPUkVfQU5EX0ZPUldBUkRfQ0FURUdPUllfRFRPX05PVElGSUNBVElP",
|
||||
"ThACEjIKLlNUT1JFX0FORF9GT1JXQVJEX0NBVEVHT1JZX0RUT19DQUNIRURf",
|
||||
"REJfV1JJVEUQAypoCg1BbGFybVN0YXRlRHRvEh8KG0FMQVJNX1NUQVRFX0RU",
|
||||
"T19VTlNQRUNJRklFRBAAEhoKFkFMQVJNX1NUQVRFX0RUT19BQ1RJVkUQARIa",
|
||||
"ChZBTEFSTV9TVEFURV9EVE9fTk9STUFMEAIquQEKDUFsYXJtTGV2ZWxEdG8S",
|
||||
"HwobQUxBUk1fTEVWRUxfRFRPX1VOU1BFQ0lGSUVEEAASGAoUQUxBUk1fTEVW",
|
||||
"RUxfRFRPX05PTkUQARIXChNBTEFSTV9MRVZFTF9EVE9fTE9XEAISGwoXQUxB",
|
||||
"Uk1fTEVWRUxfRFRPX0xPV19MT1cQAxIYChRBTEFSTV9MRVZFTF9EVE9fSElH",
|
||||
"SBAEEh0KGUFMQVJNX0xFVkVMX0RUT19ISUdIX0hJR0gQBSqSAQoMQWxhcm1L",
|
||||
"aW5kRHRvEh4KGkFMQVJNX0tJTkRfRFRPX1VOU1BFQ0lGSUVEEAASGwoXQUxB",
|
||||
"Uk1fS0lORF9EVE9fQ09NUFVURUQQARIgChxBTEFSTV9LSU5EX0RUT19OQVRJ",
|
||||
"VkVfT1BDX1VBEAISIwofQUxBUk1fS0lORF9EVE9fTkFUSVZFX01YX0FDQ0VT",
|
||||
"UxADKugBChNBbGFybVNoZWx2ZVN0YXRlRHRvEiYKIkFMQVJNX1NIRUxWRV9T",
|
||||
"VEFURV9EVE9fVU5TUEVDSUZJRUQQABIkCiBBTEFSTV9TSEVMVkVfU1RBVEVf",
|
||||
"RFRPX1VOU0hFTFZFRBABEisKJ0FMQVJNX1NIRUxWRV9TVEFURV9EVE9fT05F",
|
||||
"X1NIT1RfU0hFTFZFRBACEigKJEFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVElN",
|
||||
"RURfU0hFTFZFRBADEiwKKEFMQVJNX1NIRUxWRV9TVEFURV9EVE9fUEVSTUFO",
|
||||
"RU5UX1NIRUxWRUQQBDKEBQoSU2l0ZUNvbW1hbmRTZXJ2aWNlEmwKEEV4ZWN1",
|
||||
"dGVMaWZlY3ljbGUSLC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5MaWZl",
|
||||
"Y3ljbGVSZXF1ZXN0Giouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTGlm",
|
||||
"ZWN5Y2xlUmVwbHkSYAoMRXhlY3V0ZU9wY1VhEiguc2NhZGFicmlkZ2Uuc2l0",
|
||||
"ZWNvbW1hbmQudjEuT3BjVWFSZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNv",
|
||||
"bW1hbmQudjEuT3BjVWFSZXBseRJgCgxFeGVjdXRlUXVlcnkSKC5zY2FkYWJy",
|
||||
"aWRnZS5zaXRlY29tbWFuZC52MS5RdWVyeVJlcXVlc3QaJi5zY2FkYWJyaWRn",
|
||||
"ZS5zaXRlY29tbWFuZC52MS5RdWVyeVJlcGx5EmMKDUV4ZWN1dGVQYXJrZWQS",
|
||||
"KS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5QYXJrZWRSZXF1ZXN0Gicu",
|
||||
"c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkUmVwbHkSYAoMRXhl",
|
||||
"Y3V0ZVJvdXRlEiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVS",
|
||||
"ZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVSZXBs",
|
||||
"eRJ1Cg9UcmlnZ2VyRmFpbG92ZXISMi5zY2FkYWJyaWRnZS5zaXRlY29tbWFu",
|
||||
"ZC52MS5UcmlnZ2VyU2l0ZUZhaWxvdmVyRHRvGi4uc2NhZGFicmlkZ2Uuc2l0",
|
||||
"ZWNvbW1hbmQudjEuU2l0ZUZhaWxvdmVyQWNrRHRvQiuqAihaQi5NT00uV1cu",
|
||||
"U2NhZGFCcmlkZ2UuQ29tbXVuaWNhdGlvbi5HcnBjYgZwcm90bzM="));
|
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
|
||||
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SitestreamReflection.Descriptor, },
|
||||
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStatusDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseNodeClassDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ReadTagValuesFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.VerifyFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.StoreAndForwardCategoryDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmLevelDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmShelveStateDto), }, null, new pbr::GeneratedClrTypeInfo[] {
|
||||
@@ -543,7 +543,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStatusResponseDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStatusResponseDto.Parser, new[]{ "DeploymentId", "InstanceUniqueName", "Status", "ErrorMessage", "Timestamp" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.InstanceLifecycleResponseDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.InstanceLifecycleResponseDto.Parser, new[]{ "CommandId", "InstanceUniqueName", "Success", "ErrorMessage", "Timestamp" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStateQueryResponseDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStateQueryResponseDto.Parser, new[]{ "CorrelationId", "InstanceUniqueName", "IsDeployed", "AppliedDeploymentId", "AppliedRevisionHash", "Timestamp" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ArtifactDeploymentResponseDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ArtifactDeploymentResponseDto.Parser, new[]{ "DeploymentId", "SiteId", "Success", "ErrorMessage", "Timestamp", "SecretsApplied" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ArtifactDeploymentResponseDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ArtifactDeploymentResponseDto.Parser, new[]{ "DeploymentId", "SiteId", "Success", "ErrorMessage", "Timestamp", "SecretsApplied", "SecretsRemoved" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.LifecycleRequest), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.LifecycleRequest.Parser, new[]{ "RefreshDeployment", "EnableInstance", "DisableInstance", "DeleteInstance", "DeploymentStateQuery", "DeployArtifacts" }, new[]{ "Command" }, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.LifecycleReply), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.LifecycleReply.Parser, new[]{ "DeploymentStatus", "InstanceLifecycle", "DeploymentStateQuery", "ArtifactDeployment" }, new[]{ "Reply" }, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseNodeCommandDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseNodeCommandDto.Parser, new[]{ "ConnectionName", "ParentNodeId", "ContinuationToken", "SiteIdentifier" }, null, null, null, null),
|
||||
@@ -9751,6 +9751,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
errorMessage_ = other.errorMessage_;
|
||||
timestamp_ = other.timestamp_ != null ? other.timestamp_.Clone() : null;
|
||||
SecretsApplied = other.SecretsApplied;
|
||||
secretsRemoved_ = other.secretsRemoved_.Clone();
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -9840,6 +9841,20 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Field number for the "secrets_removed" field.</summary>
|
||||
public const int SecretsRemovedFieldNumber = 7;
|
||||
private static readonly pb::FieldCodec<string> _repeated_secretsRemoved_codec
|
||||
= pb::FieldCodec.ForString(58);
|
||||
private readonly pbc::RepeatedField<string> secretsRemoved_ = new pbc::RepeatedField<string>();
|
||||
/// <summary>
|
||||
/// names only; empty => null
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public pbc::RepeatedField<string> SecretsRemoved {
|
||||
get { return secretsRemoved_; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
@@ -9861,6 +9876,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
if (ErrorMessage != other.ErrorMessage) return false;
|
||||
if (!object.Equals(Timestamp, other.Timestamp)) return false;
|
||||
if (SecretsApplied != other.SecretsApplied) return false;
|
||||
if(!secretsRemoved_.Equals(other.secretsRemoved_)) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -9874,6 +9890,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
|
||||
if (timestamp_ != null) hash ^= Timestamp.GetHashCode();
|
||||
if (secretsApplied_ != null) hash ^= SecretsApplied.GetHashCode();
|
||||
hash ^= secretsRemoved_.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
@@ -9915,6 +9932,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
if (secretsApplied_ != null) {
|
||||
_single_secretsApplied_codec.WriteTagAndValue(output, SecretsApplied);
|
||||
}
|
||||
secretsRemoved_.WriteTo(output, _repeated_secretsRemoved_codec);
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
@@ -9948,6 +9966,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
if (secretsApplied_ != null) {
|
||||
_single_secretsApplied_codec.WriteTagAndValue(ref output, SecretsApplied);
|
||||
}
|
||||
secretsRemoved_.WriteTo(ref output, _repeated_secretsRemoved_codec);
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
@@ -9976,6 +9995,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
if (secretsApplied_ != null) {
|
||||
size += _single_secretsApplied_codec.CalculateSizeWithTag(SecretsApplied);
|
||||
}
|
||||
size += secretsRemoved_.CalculateSize(_repeated_secretsRemoved_codec);
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
@@ -10011,6 +10031,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
SecretsApplied = other.SecretsApplied;
|
||||
}
|
||||
}
|
||||
secretsRemoved_.Add(other.secretsRemoved_);
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -10060,6 +10081,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 58: {
|
||||
secretsRemoved_.AddEntriesFrom(input, _repeated_secretsRemoved_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -10109,6 +10134,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 58: {
|
||||
secretsRemoved_.AddEntriesFrom(ref input, _repeated_secretsRemoved_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,10 +111,11 @@ public class ArtifactDeploymentService
|
||||
/// single-site retries).
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The deployment artifacts command for the site, and any secret references its data
|
||||
/// connections make that could not be resolved at central (absent or tombstoned). A
|
||||
/// non-empty <c>Missing</c> list means the command must NOT be sent to the site —
|
||||
/// see <see cref="DeployCoreAsync"/>/<see cref="RetryForSiteAsync"/>.
|
||||
/// The deployment artifacts command for the site, any secret references its data
|
||||
/// connections make that could not be resolved at central (absent or tombstoned), and the
|
||||
/// central secret store's read error if resolution could not complete. A non-empty
|
||||
/// <c>Missing</c> list or a non-null <c>SecretStoreError</c> means the command must NOT be
|
||||
/// sent to the site — see <see cref="DeployCoreAsync"/>/<see cref="RetryForSiteAsync"/>.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This convenience overload runs the global artifact queries
|
||||
@@ -123,7 +124,7 @@ public class ArtifactDeploymentService
|
||||
/// per-site loop and calls the prefetched-globals overload to avoid the N+1
|
||||
/// re-query of every system-wide artifact set per site.
|
||||
/// </remarks>
|
||||
public async Task<(DeployArtifactsCommand Command, IReadOnlyList<SecretReference> Missing)> BuildDeployArtifactsCommandAsync(
|
||||
public async Task<(DeployArtifactsCommand Command, IReadOnlyList<SecretReference> Missing, string? SecretStoreError)> BuildDeployArtifactsCommandAsync(
|
||||
int siteId,
|
||||
CancellationToken cancellationToken = default,
|
||||
string? deploymentId = null)
|
||||
@@ -157,7 +158,7 @@ public class ArtifactDeploymentService
|
||||
/// distinguishable marker into the hash even for a command the caller ultimately refuses
|
||||
/// to send (see the returned <c>Missing</c> tuple element).
|
||||
/// </remarks>
|
||||
private async Task<(DeployArtifactsCommand Command, IReadOnlyList<SecretReference> Missing)> BuildDeployArtifactsCommandAsync(
|
||||
private async Task<(DeployArtifactsCommand Command, IReadOnlyList<SecretReference> Missing, string? SecretStoreError)> BuildDeployArtifactsCommandAsync(
|
||||
int siteId,
|
||||
GlobalArtifactSnapshot globals,
|
||||
CancellationToken cancellationToken,
|
||||
@@ -193,7 +194,7 @@ public class ArtifactDeploymentService
|
||||
Secrets: collected.Secrets,
|
||||
MissingSecrets: collected.Missing.Count > 0 ? collected.Missing.Select(m => m.Name).ToList() : null);
|
||||
|
||||
return (command, collected.Missing);
|
||||
return (command, collected.Missing, collected.StoreError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -221,19 +222,24 @@ public class ArtifactDeploymentService
|
||||
var shipped = cmd.Secrets?.Count ?? 0;
|
||||
if (r.Success && shipped > 0 && r.SecretsApplied is null)
|
||||
return new(siteIdentifier, siteName, false,
|
||||
"Site build predates secret deployment — upgrade the site before deploying secrets", null);
|
||||
"Site build predates secret deployment — upgrade the site before deploying secrets", null,
|
||||
r.SecretsRemoved);
|
||||
if (r.Success && shipped > 0 && r.SecretsApplied != shipped)
|
||||
return new(siteIdentifier, siteName, false,
|
||||
$"Site applied {r.SecretsApplied} of {shipped} secrets", r.SecretsApplied);
|
||||
return new(siteIdentifier, siteName, r.Success, r.ErrorMessage, shipped > 0 ? r.SecretsApplied : null);
|
||||
$"Site applied {r.SecretsApplied} of {shipped} secrets", r.SecretsApplied, r.SecretsRemoved);
|
||||
return new(siteIdentifier, siteName, r.Success, r.ErrorMessage, shipped > 0 ? r.SecretsApplied : null,
|
||||
r.SecretsRemoved);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Best-effort <c>DeploySiteSecrets</c> audit row (task 7): one row per site whose command
|
||||
/// carried, or would have carried, at least one secret — a resolved
|
||||
/// <see cref="DeployArtifactsCommand.Secrets"/> entry, an unresolved reference in
|
||||
/// <paramref name="missing"/> (the fail-closed case, where nothing was sent), or both. A
|
||||
/// site with no secret references at all gets no row.
|
||||
/// <paramref name="missing"/> (the fail-closed case, where nothing was sent), a central
|
||||
/// secret-store read failure (<paramref name="secretStoreError"/>, also fail-closed), or a
|
||||
/// site-reported removal of previously-deployed secrets (<paramref name="removed"/>, the
|
||||
/// site's <see cref="ArtifactDeploymentResponse.SecretsRemoved"/>). A site with none of
|
||||
/// these gets no row.
|
||||
///
|
||||
/// Per the audit-is-best-effort rule (an audit failure never changes the deploy outcome)
|
||||
/// this is fire-and-forget-shaped only in intent, not mechanism — like every other audit
|
||||
@@ -251,13 +257,22 @@ public class ArtifactDeploymentService
|
||||
string user,
|
||||
DeployArtifactsCommand command,
|
||||
IReadOnlyList<SecretReference> missing,
|
||||
string? secretStoreError,
|
||||
IReadOnlyList<string>? removed,
|
||||
string siteIdentifier,
|
||||
string siteName,
|
||||
bool success,
|
||||
string? error,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var hasSecretRefs = (command.Secrets?.Count ?? 0) > 0 || missing.Count > 0;
|
||||
// A removal-only deploy (the site's last secret reference was dropped, so nothing
|
||||
// ships but the site retires previously-deployed rows) and a secret-store outage both
|
||||
// count as "secrets involved" — the former used to write no row at all (final review
|
||||
// M6 follow-up), leaving the removal visible only in the site's own logs.
|
||||
var hasSecretRefs = (command.Secrets?.Count ?? 0) > 0
|
||||
|| missing.Count > 0
|
||||
|| secretStoreError is not null
|
||||
|| removed is { Count: > 0 };
|
||||
if (!hasSecretRefs)
|
||||
return Task.CompletedTask;
|
||||
|
||||
@@ -270,6 +285,7 @@ public class ArtifactDeploymentService
|
||||
.Select(s => new { name = s.Name, revision = s.Revision })
|
||||
.ToList(),
|
||||
missing = missing.Select(m => m.Name).ToList(),
|
||||
removed = (removed ?? []).ToList(),
|
||||
success,
|
||||
error,
|
||||
},
|
||||
@@ -427,7 +443,7 @@ public class ArtifactDeploymentService
|
||||
// Each entry also carries the site's unresolved secret references (design §3.3):
|
||||
// a non-empty Missing list means this site's command must never reach
|
||||
// _communicationService — see the fan-out loop below.
|
||||
var siteCommands = new Dictionary<int, (DeployArtifactsCommand Command, IReadOnlyList<SecretReference> Missing)>();
|
||||
var siteCommands = new Dictionary<int, (DeployArtifactsCommand Command, IReadOnlyList<SecretReference> Missing, string? SecretStoreError)>();
|
||||
foreach (var site in sites)
|
||||
{
|
||||
siteCommands[site.Id] = await BuildDeployArtifactsCommandAsync(
|
||||
@@ -457,7 +473,19 @@ public class ArtifactDeploymentService
|
||||
using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
cts.CancelAfter(_options.ArtifactDeploymentTimeoutPerSite);
|
||||
|
||||
var (command, missing) = siteCommands[site.Id];
|
||||
var (command, missing, secretStoreError) = siteCommands[site.Id];
|
||||
|
||||
// A central secret-store read failure (final review M5) fails only the sites
|
||||
// that reference a secret — resolution is incomplete, so shipping would either
|
||||
// drop a secret the site still needs or retire one it still uses. Sites with no
|
||||
// secret references never touch the store and deploy normally.
|
||||
if (secretStoreError is not null)
|
||||
{
|
||||
_logger.LogError(
|
||||
"Cannot deploy artifacts to site {SiteId} ({SiteName}): {Error}",
|
||||
site.SiteIdentifier, site.Name, secretStoreError);
|
||||
return new SiteArtifactResult(site.SiteIdentifier, site.Name, false, secretStoreError);
|
||||
}
|
||||
|
||||
// Fail this site closed BEFORE anything is sent (design §3.3): a referenced
|
||||
// secret that is absent or tombstoned at central must not let the rest of the
|
||||
@@ -528,11 +556,11 @@ public class ArtifactDeploymentService
|
||||
// rule — BEFORE the best-effort stamp below.
|
||||
foreach (var site in sites)
|
||||
{
|
||||
var (command, missing) = siteCommands[site.Id];
|
||||
var (command, missing, secretStoreError) = siteCommands[site.Id];
|
||||
var result = perSiteResults[site.SiteIdentifier];
|
||||
await LogSecretsAuditAsync(
|
||||
user, command, missing, site.SiteIdentifier, site.Name,
|
||||
result.Success, result.ErrorMessage, cancellationToken);
|
||||
user, command, missing, secretStoreError, result.SecretsRemoved,
|
||||
site.SiteIdentifier, site.Name, result.Success, result.ErrorMessage, cancellationToken);
|
||||
}
|
||||
|
||||
// Persist the system artifact deployment record.
|
||||
@@ -611,7 +639,18 @@ public class ArtifactDeploymentService
|
||||
using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
cts.CancelAfter(_options.ArtifactDeploymentTimeoutPerSite);
|
||||
|
||||
var (command, missing) = await BuildDeployArtifactsCommandAsync(siteDbId, cts.Token);
|
||||
var (command, missing, secretStoreError) = await BuildDeployArtifactsCommandAsync(siteDbId, cts.Token);
|
||||
|
||||
// Same store-outage rule as the sweep path (final review M5).
|
||||
if (secretStoreError is not null)
|
||||
{
|
||||
_logger.LogError(
|
||||
"Cannot deploy artifacts to site {SiteId}: {Error}", siteIdentifier, secretStoreError);
|
||||
await LogSecretsAuditAsync(
|
||||
user, command, missing, secretStoreError, null, siteIdentifier, siteIdentifier,
|
||||
false, secretStoreError, cancellationToken);
|
||||
return Result<SiteArtifactResult>.Failure(secretStoreError);
|
||||
}
|
||||
|
||||
// Same fail-closed rule as the sweep path (design §3.3): a retry must not ship a
|
||||
// site an artifact set whose secret references still don't resolve.
|
||||
@@ -623,7 +662,7 @@ public class ArtifactDeploymentService
|
||||
// Task 7: the fail-closed case still gets its DeploySiteSecrets row — nothing
|
||||
// was sent, but the command carried (or would have carried) secrets.
|
||||
await LogSecretsAuditAsync(
|
||||
user, command, missing, siteIdentifier, siteIdentifier, false, missingMessage,
|
||||
user, command, missing, null, null, siteIdentifier, siteIdentifier, false, missingMessage,
|
||||
cancellationToken);
|
||||
return Result<SiteArtifactResult>.Failure(missingMessage);
|
||||
}
|
||||
@@ -648,7 +687,7 @@ public class ArtifactDeploymentService
|
||||
|
||||
// Ordering rule: audit before the best-effort stamp.
|
||||
await LogSecretsAuditAsync(
|
||||
user, command, missing, siteIdentifier, siteIdentifier,
|
||||
user, command, missing, null, result.SecretsRemoved, siteIdentifier, siteIdentifier,
|
||||
result.Success, result.ErrorMessage, cancellationToken);
|
||||
|
||||
// Same stamp-on-success rule as the sweep path: a retry that lands is a
|
||||
@@ -699,6 +738,12 @@ public class ArtifactDeploymentService
|
||||
/// would silently report unqueried sites as up to date. The pending-updates cache discards a
|
||||
/// faulted flight and the UI shows the aggregate as unavailable instead.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// A central secret-store read failure is the one per-site exception (final review M5): the
|
||||
/// affected site is left OUT of the map, which the evaluator reads as <i>Out of date</i> (a
|
||||
/// missing entry never matches a stamp), so a store outage degrades only the sites that
|
||||
/// reference secrets instead of failing the fleet-wide check.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public async Task<IReadOnlyDictionary<int, string>> ComputeCurrentArtifactHashesAsync(
|
||||
IReadOnlyList<Site> sites,
|
||||
@@ -717,8 +762,22 @@ public class ArtifactDeploymentService
|
||||
// MissingSecrets straight off the command (design §3.4), so an unresolved
|
||||
// reference still folds a distinguishable marker into the hash — the site reads
|
||||
// *Out of date* instead of this call failing the whole batch.
|
||||
var (command, _) = await BuildDeployArtifactsCommandAsync(
|
||||
var (command, _, secretStoreError) = await BuildDeployArtifactsCommandAsync(
|
||||
site.Id, globals, cancellationToken, deploymentId: "current");
|
||||
|
||||
// A central secret-store outage (final review M5) leaves this site's current hash
|
||||
// unknowable. Omitting it from the map makes the site read *Out of date* — the
|
||||
// conservative answer, never a false *Current* — while every other site, including
|
||||
// every site with no secret references, still evaluates normally instead of the
|
||||
// whole fleet check failing.
|
||||
if (secretStoreError is not null)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Could not compute the current artifact hash for site {SiteId}: {Error}",
|
||||
site.SiteIdentifier, secretStoreError);
|
||||
continue;
|
||||
}
|
||||
|
||||
hashes[site.Id] = _hashService.ComputeHash(command);
|
||||
}
|
||||
|
||||
@@ -800,12 +859,19 @@ public class ArtifactDeploymentService
|
||||
/// doesn't know about the field) are indistinguishable, which is correct: neither one is a
|
||||
/// secrets-gating concern.
|
||||
/// </param>
|
||||
/// <param name="SecretsRemoved">
|
||||
/// The previously-deployed secret names the site retired on this deploy because no data
|
||||
/// connection references them any more (the site's
|
||||
/// <see cref="ArtifactDeploymentResponse.SecretsRemoved"/>); <c>null</c> when the site reported
|
||||
/// none or predates the field. Feeds the <c>DeploySiteSecrets</c> audit row's <c>removed</c> list.
|
||||
/// </param>
|
||||
public record SiteArtifactResult(
|
||||
string SiteId,
|
||||
string SiteName,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
int? SecretsDeployed = null);
|
||||
int? SecretsDeployed = null,
|
||||
IReadOnlyList<string>? SecretsRemoved = null);
|
||||
|
||||
/// <summary>
|
||||
/// Summary of system-wide artifact deployment with per-site results.
|
||||
|
||||
@@ -6,12 +6,23 @@ namespace ZB.MOM.WW.ScadaBridge.DeploymentManager;
|
||||
|
||||
/// <summary>
|
||||
/// Result of <see cref="SiteSecretsCollector.CollectAsync"/>: the resolved ciphertext rows for a
|
||||
/// site's referenced secrets, and the references that could not be resolved (absent or
|
||||
/// tombstoned) at central.
|
||||
/// site's referenced secrets, the references that could not be resolved (absent or
|
||||
/// tombstoned) at central, and — when the central secret store itself could not be read — the
|
||||
/// error that stopped resolution.
|
||||
/// </summary>
|
||||
/// <param name="Secrets">The resolved rows.</param>
|
||||
/// <param name="Missing">References that are absent or tombstoned in the store.</param>
|
||||
/// <param name="StoreError">
|
||||
/// <see langword="null"/> when every reference was looked up. Otherwise the store read failed
|
||||
/// (final review M5: e.g. the shared SQL Server secret store is unreachable), resolution stopped
|
||||
/// at the first failure, and <see cref="Secrets"/>/<see cref="Missing"/> are INCOMPLETE — the
|
||||
/// caller must treat this site as undeployable and its current hash as unknown. The message is
|
||||
/// the exception type and message only; it never contains secret material.
|
||||
/// </param>
|
||||
public sealed record SiteSecretsCollection(
|
||||
IReadOnlyList<SecretArtifact> Secrets,
|
||||
IReadOnlyList<SecretReference> Missing);
|
||||
IReadOnlyList<SecretReference> Missing,
|
||||
string? StoreError = null);
|
||||
|
||||
/// <summary>
|
||||
/// Central half of design §3.1/§3.3: derives which secrets a site's data connections reference
|
||||
@@ -30,7 +41,11 @@ public sealed class SiteSecretsCollector(ISecretStore store)
|
||||
/// <param name="ct">A token to cancel the operation.</param>
|
||||
/// <returns>
|
||||
/// The resolved rows (mapped field-for-field from <see cref="StoredSecret"/>) and the
|
||||
/// references that were absent or tombstoned in the store.
|
||||
/// references that were absent or tombstoned in the store. A store read failure is
|
||||
/// returned as <see cref="SiteSecretsCollection.StoreError"/> rather than thrown, so one
|
||||
/// site's lookup failing never aborts a whole multi-site sweep (final review M5); only
|
||||
/// cancellation of <paramref name="ct"/> propagates. A site whose connections reference no
|
||||
/// secret never touches the store at all.
|
||||
/// </returns>
|
||||
public async Task<SiteSecretsCollection> CollectAsync(
|
||||
IEnumerable<DataConnectionArtifact> connections, CancellationToken ct)
|
||||
@@ -40,7 +55,19 @@ public sealed class SiteSecretsCollector(ISecretStore store)
|
||||
|
||||
foreach (var reference in SecretReferenceScanner.Scan(connections))
|
||||
{
|
||||
var row = await store.GetAsync(new SecretName(reference.Name), ct);
|
||||
StoredSecret? row;
|
||||
try
|
||||
{
|
||||
row = await store.GetAsync(new SecretName(reference.Name), ct);
|
||||
}
|
||||
catch (Exception ex) when (!ct.IsCancellationRequested)
|
||||
{
|
||||
return new SiteSecretsCollection(
|
||||
secrets, missing,
|
||||
$"Central secret store could not be read while resolving '{reference.Name}' " +
|
||||
$"({ex.GetType().Name}: {ex.Message})");
|
||||
}
|
||||
|
||||
if (row is null || row.IsDeleted)
|
||||
{
|
||||
missing.Add(reference);
|
||||
|
||||
@@ -3352,6 +3352,7 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
|
||||
// registered on this node fails the deploy rather than silently applying
|
||||
// nothing.
|
||||
int? secretsApplied = null;
|
||||
IReadOnlyList<string>? secretsRemoved = null;
|
||||
string? secretError = null;
|
||||
if (command.Secrets != null)
|
||||
{
|
||||
@@ -3371,7 +3372,20 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
|
||||
_logger.LogInformation(
|
||||
"Applying {Count} deployed secret(s), deploymentId={DeploymentId}",
|
||||
command.Secrets.Count, command.DeploymentId);
|
||||
await _storage.UpsertDeployedSecretsAsync(command.Secrets, command.DeploymentId);
|
||||
var (_, removedNames) =
|
||||
await _storage.UpsertDeployedSecretsAsync(command.Secrets, command.DeploymentId);
|
||||
// Reported to central for its DeploySiteSecrets audit row, so a deploy
|
||||
// that only retires secrets is still audited there. These are the
|
||||
// deployed_secrets rows this deploy marked removed (site-wide, the
|
||||
// authoritative "no longer deployed" set) — not whichever of them this
|
||||
// node's mirror happened to own and delete.
|
||||
if (removedNames.Count > 0)
|
||||
{
|
||||
secretsRemoved = removedNames;
|
||||
_logger.LogInformation(
|
||||
"Retired {Count} deployed secret(s) no longer referenced, deploymentId={DeploymentId}: {Names}",
|
||||
removedNames.Count, command.DeploymentId, string.Join(", ", removedNames));
|
||||
}
|
||||
var mirror = await _secretsMirror.ReconcileAsync(CancellationToken.None);
|
||||
|
||||
// The mirror reconciles the WHOLE site-wide deployed_secrets table
|
||||
@@ -3418,7 +3432,7 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
|
||||
|
||||
return new ArtifactDeploymentResponse(
|
||||
command.DeploymentId, "", secretError is null, secretError, DateTimeOffset.UtcNow,
|
||||
secretsApplied);
|
||||
secretsApplied, secretsRemoved);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
+19
@@ -82,4 +82,23 @@ public class SiteCommandDtoMapperSecretsTests
|
||||
var r = new ArtifactDeploymentResponse("dep", "site-a", true, null, DateTimeOffset.UtcNow, applied);
|
||||
Assert.Equal(applied, SiteCommandDtoMapper.FromProto(SiteCommandDtoMapper.ToProto(r)).SecretsApplied);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ArtifactResponse_SecretsRemoved_RoundTrips()
|
||||
{
|
||||
var r = new ArtifactDeploymentResponse(
|
||||
"dep", "site-a", true, null, DateTimeOffset.UtcNow, 0, ["old-1", "old-2"]);
|
||||
Assert.Equal(["old-1", "old-2"], SiteCommandDtoMapper.FromProto(SiteCommandDtoMapper.ToProto(r)).SecretsRemoved!);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ArtifactResponse_NoSecretsRemoved_IsNullOnBothSides()
|
||||
{
|
||||
// Absent on the wire (an old site, or nothing removed) must read back as null.
|
||||
var none = new ArtifactDeploymentResponse("dep", "site-a", true, null, DateTimeOffset.UtcNow, 1);
|
||||
Assert.Null(SiteCommandDtoMapper.FromProto(SiteCommandDtoMapper.ToProto(none)).SecretsRemoved);
|
||||
|
||||
var empty = none with { SecretsRemoved = [] };
|
||||
Assert.Null(SiteCommandDtoMapper.FromProto(SiteCommandDtoMapper.ToProto(empty)).SecretsRemoved);
|
||||
}
|
||||
}
|
||||
|
||||
+178
@@ -1157,6 +1157,184 @@ public class ArtifactDeploymentServiceTests : TestKit
|
||||
/// reconciliation gate can be exercised independently of the wire-level success/failure
|
||||
/// the shared <see cref="ArtifactProbeActor"/> models.
|
||||
/// </summary>
|
||||
// ── Final review M5: a central secret-store outage is contained to the sites that need it ──
|
||||
|
||||
[Fact]
|
||||
public async Task StoreOutage_FailsOnlyTheSecretReferencingSite_AndAuditsIt()
|
||||
{
|
||||
var secretSite = new Site("Secret Site", "sec-site") { Id = 1 };
|
||||
var plainSite = new Site("Plain Site", "plain-site") { Id = 2 };
|
||||
_siteRepo.GetAllSitesAsync(Arg.Any<CancellationToken>()).Returns(new List<Site> { secretSite, plainSite });
|
||||
_siteRepo.GetDataConnectionsBySiteIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<DataConnection>
|
||||
{
|
||||
new("GW1", "MxGateway", 1) { PrimaryConfiguration = """{"ApiKey":"secret:the-key"}""" }
|
||||
});
|
||||
_siteRepo.GetDataConnectionsBySiteIdAsync(2, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<DataConnection>());
|
||||
_secretStore.GetAsync(Arg.Any<SecretName>(), Arg.Any<CancellationToken>())
|
||||
.Returns<Task<StoredSecret?>>(_ => throw new InvalidOperationException("SQL Server unreachable"));
|
||||
|
||||
var recorder = new ArtifactProbeRecorder();
|
||||
var probe = Sys.ActorOf(Props.Create(() =>
|
||||
new SecretsAckProbeActor(recorder, cmd => cmd.Secrets == null ? (int?)null : cmd.Secrets.Count)));
|
||||
var service = CreateServiceWithCommActor(probe);
|
||||
|
||||
object? audited = null;
|
||||
_audit.When(x => x.LogAsync(
|
||||
Arg.Any<string>(), "DeploySiteSecrets", Arg.Any<string>(), "sec-site", Arg.Any<string>(),
|
||||
Arg.Any<object>(), Arg.Any<CancellationToken>()))
|
||||
.Do(ci => audited = ci[5]);
|
||||
|
||||
// Before M5 the store exception escaped the build loop and the whole sweep threw.
|
||||
var result = await service.DeployToAllSitesAsync("admin");
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(1, result.Value.SuccessCount);
|
||||
Assert.Equal(1, result.Value.FailureCount);
|
||||
var failed = Assert.Single(result.Value.SiteResults, r => r.SiteId == "sec-site");
|
||||
Assert.False(failed.Success);
|
||||
Assert.Contains("Central secret store could not be read", failed.ErrorMessage);
|
||||
Assert.Contains("SQL Server unreachable", failed.ErrorMessage);
|
||||
Assert.Contains(result.Value.SiteResults, r => r.SiteId == "plain-site" && r.Success);
|
||||
|
||||
// Nothing was sent to the failing site, and it keeps no stamp.
|
||||
var sent = Assert.Single(recorder.Received);
|
||||
Assert.Empty(sent.DataConnections ?? []);
|
||||
Assert.Null(secretSite.ArtifactRevisionHash);
|
||||
Assert.NotNull(plainSite.ArtifactRevisionHash);
|
||||
|
||||
Assert.NotNull(audited);
|
||||
var json = JsonSerializer.Serialize(audited);
|
||||
Assert.Contains("\"success\":false", json);
|
||||
Assert.Contains("Central secret store could not be read", json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ComputeCurrentHashes_StoreOutage_OmitsOnlyTheSecretReferencingSite()
|
||||
{
|
||||
var secretSite = new Site("Secret Site", "sec-site") { Id = 1 };
|
||||
var plainSite = new Site("Plain Site", "plain-site") { Id = 2 };
|
||||
_siteRepo.GetDataConnectionsBySiteIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<DataConnection>
|
||||
{
|
||||
new("GW1", "MxGateway", 1) { PrimaryConfiguration = """{"ApiKey":"secret:the-key"}""" }
|
||||
});
|
||||
_siteRepo.GetDataConnectionsBySiteIdAsync(2, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<DataConnection>());
|
||||
_secretStore.GetAsync(Arg.Any<SecretName>(), Arg.Any<CancellationToken>())
|
||||
.Returns<Task<StoredSecret?>>(_ => throw new InvalidOperationException("SQL Server unreachable"));
|
||||
var service = CreateService();
|
||||
|
||||
var hashes = await service.ComputeCurrentArtifactHashesAsync([secretSite, plainSite]);
|
||||
|
||||
// The secret-referencing site is left out (the evaluator reads that as Out of date);
|
||||
// the plain site still gets its hash instead of the whole fleet check failing.
|
||||
Assert.False(hashes.ContainsKey(1));
|
||||
Assert.True(hashes.ContainsKey(2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RetryForSite_StoreOutage_FailsWithoutSending()
|
||||
{
|
||||
_siteRepo.GetDataConnectionsBySiteIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<DataConnection>
|
||||
{
|
||||
new("GW1", "MxGateway", 1) { PrimaryConfiguration = """{"ApiKey":"secret:the-key"}""" }
|
||||
});
|
||||
_secretStore.GetAsync(Arg.Any<SecretName>(), Arg.Any<CancellationToken>())
|
||||
.Returns<Task<StoredSecret?>>(_ => throw new InvalidOperationException("SQL Server unreachable"));
|
||||
|
||||
var recorder = new ArtifactProbeRecorder();
|
||||
var probe = Sys.ActorOf(Props.Create(() => new SecretsAckProbeActor(recorder, _ => 1)));
|
||||
var service = CreateServiceWithCommActor(probe);
|
||||
|
||||
var result = await service.RetryForSiteAsync(1, "sec-site", "admin");
|
||||
|
||||
Assert.True(result.IsFailure);
|
||||
Assert.Contains("Central secret store could not be read", result.Error);
|
||||
Assert.Empty(recorder.Received);
|
||||
await _audit.Received(1).LogAsync(
|
||||
"admin", "DeploySiteSecrets", "SiteSecrets", "sec-site", Arg.Any<string>(),
|
||||
Arg.Any<object>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
// ── Removal-only deploys are audited (the site reports the names it retired) ──
|
||||
|
||||
[Fact]
|
||||
public async Task RemovalOnlyDeploy_WritesAuditRowNamingTheRemovedSecrets()
|
||||
{
|
||||
var site = new Site("Site One", "site-1") { Id = 1 };
|
||||
_siteRepo.GetAllSitesAsync(Arg.Any<CancellationToken>()).Returns(new List<Site> { site });
|
||||
// The site's last secret reference is gone: nothing ships, the site retires "old-key".
|
||||
_siteRepo.GetDataConnectionsBySiteIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<DataConnection>());
|
||||
|
||||
var recorder = new ArtifactProbeRecorder();
|
||||
var probe = Sys.ActorOf(Props.Create(() => new RemovingProbeActor(recorder, new[] { "old-key" })));
|
||||
var service = CreateServiceWithCommActor(probe);
|
||||
|
||||
object? audited = null;
|
||||
_audit.When(x => x.LogAsync(
|
||||
Arg.Any<string>(), "DeploySiteSecrets", Arg.Any<string>(), "site-1", Arg.Any<string>(),
|
||||
Arg.Any<object>(), Arg.Any<CancellationToken>()))
|
||||
.Do(ci => audited = ci[5]);
|
||||
|
||||
var result = await service.DeployToAllSitesAsync("admin");
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
var siteResult = Assert.Single(result.Value.SiteResults);
|
||||
Assert.True(siteResult.Success);
|
||||
Assert.Equal(["old-key"], siteResult.SecretsRemoved!);
|
||||
|
||||
Assert.NotNull(audited);
|
||||
var json = JsonSerializer.Serialize(audited);
|
||||
Assert.Contains("\"removed\":[\"old-key\"]", json);
|
||||
Assert.Contains("\"secrets\":[]", json);
|
||||
Assert.Contains("\"success\":true", json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RetryForSite_RemovalOnly_WritesAuditRowNamingTheRemovedSecrets()
|
||||
{
|
||||
_siteRepo.GetDataConnectionsBySiteIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<DataConnection>());
|
||||
|
||||
var recorder = new ArtifactProbeRecorder();
|
||||
var probe = Sys.ActorOf(Props.Create(() => new RemovingProbeActor(recorder, new[] { "old-key" })));
|
||||
var service = CreateServiceWithCommActor(probe);
|
||||
|
||||
object? audited = null;
|
||||
_audit.When(x => x.LogAsync(
|
||||
Arg.Any<string>(), "DeploySiteSecrets", Arg.Any<string>(), "site-1", Arg.Any<string>(),
|
||||
Arg.Any<object>(), Arg.Any<CancellationToken>()))
|
||||
.Do(ci => audited = ci[5]);
|
||||
|
||||
var result = await service.RetryForSiteAsync(1, "site-1", "admin");
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.NotNull(audited);
|
||||
Assert.Contains("\"removed\":[\"old-key\"]", JsonSerializer.Serialize(audited));
|
||||
}
|
||||
|
||||
/// <summary>Acks every command as applied (0 shipped secrets) and reports the given names as retired.</summary>
|
||||
private class RemovingProbeActor : ReceiveActor
|
||||
{
|
||||
public RemovingProbeActor(ArtifactProbeRecorder recorder, IReadOnlyList<string> removed)
|
||||
{
|
||||
Receive<SiteEnvelope>(env =>
|
||||
{
|
||||
if (env.Message is DeployArtifactsCommand cmd)
|
||||
{
|
||||
recorder.Received.Add(cmd);
|
||||
Sender.Tell(new ArtifactDeploymentResponse(
|
||||
cmd.DeploymentId, env.SiteId, true, null, DateTimeOffset.UtcNow,
|
||||
cmd.Secrets?.Count, removed));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class SecretsAckProbeActor : ReceiveActor
|
||||
{
|
||||
public SecretsAckProbeActor(ArtifactProbeRecorder recorder, Func<DeployArtifactsCommand, int?> secretsApplied)
|
||||
|
||||
@@ -100,6 +100,40 @@ public class SiteSecretsCollectorTests
|
||||
Assert.Empty(result.Missing);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Collect_StoreThrows_ReturnsStoreError_InsteadOfThrowing()
|
||||
{
|
||||
// Final review M5: one site's store read failing must not abort a whole sweep.
|
||||
var store = new FakeSecretStore(Row("a", 1)) { Fault = new InvalidOperationException("db down") };
|
||||
|
||||
var result = await new SiteSecretsCollector(store).CollectAsync(
|
||||
[Dc("GW1", """{"ApiKey":"secret:a"}""")], default);
|
||||
|
||||
Assert.NotNull(result.StoreError);
|
||||
Assert.Contains("'a'", result.StoreError);
|
||||
Assert.Contains("InvalidOperationException: db down", result.StoreError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Collect_CallerCancellation_StillPropagates()
|
||||
{
|
||||
using var cts = new CancellationTokenSource();
|
||||
cts.Cancel();
|
||||
var store = new FakeSecretStore(Row("a", 1)) { Fault = new OperationCanceledException(cts.Token) };
|
||||
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(() => new SiteSecretsCollector(store).CollectAsync(
|
||||
[Dc("GW1", """{"ApiKey":"secret:a"}""")], cts.Token));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Collect_Success_HasNoStoreError()
|
||||
{
|
||||
var result = await new SiteSecretsCollector(new FakeSecretStore(Row("a", 1))).CollectAsync(
|
||||
[Dc("GW1", """{"ApiKey":"secret:a"}""")], default);
|
||||
|
||||
Assert.Null(result.StoreError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In-memory <see cref="ISecretStore"/> stand-in. Implements only <see cref="GetAsync"/> —
|
||||
/// the sole member <see cref="SiteSecretsCollector"/> calls; every other member throws so an
|
||||
@@ -112,8 +146,13 @@ public class SiteSecretsCollectorTests
|
||||
|
||||
public FakeSecretStore(params StoredSecret[] rows) => _rows = rows.ToDictionary(r => r.Name);
|
||||
|
||||
/// <summary>When set, <see cref="GetAsync"/> throws this instead of reading.</summary>
|
||||
public Exception? Fault { get; init; }
|
||||
|
||||
public Task<StoredSecret?> GetAsync(SecretName name, CancellationToken ct) =>
|
||||
Task.FromResult(_rows.TryGetValue(name, out var row) ? row : null);
|
||||
Fault is not null
|
||||
? Task.FromException<StoredSecret?>(Fault)
|
||||
: Task.FromResult(_rows.TryGetValue(name, out var row) ? row : null);
|
||||
|
||||
public Task UpsertAsync(StoredSecret row, CancellationToken ct) => throw new NotSupportedException();
|
||||
|
||||
|
||||
+29
@@ -173,6 +173,35 @@ public class DeploymentManagerActorArtifactSecretsTests : TestKit, IDisposable
|
||||
Assert.Equal(0, response.SecretsApplied);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Secrets_Dropped_ReplyNamesTheRetiredSecrets()
|
||||
{
|
||||
var store = new FakeSecretStore();
|
||||
var resolver = new FakeSecretResolver();
|
||||
var mirror = CreateMirror(store, resolver);
|
||||
var manager = CreateDeploymentManager(mirror);
|
||||
|
||||
manager.Tell(ArtifactsCommand("dep-1", secrets: [Art("a", 1), Art("b", 1)]));
|
||||
var first = ExpectMsg<ArtifactDeploymentResponse>(TimeSpan.FromSeconds(10));
|
||||
Assert.True(first.Success);
|
||||
Assert.Null(first.SecretsRemoved);
|
||||
|
||||
// The next deploy no longer references "b" (a removal-only change for that name):
|
||||
// the reply names it so central can audit the removal.
|
||||
manager.Tell(ArtifactsCommand("dep-2", secrets: [Art("a", 1)]));
|
||||
var second = ExpectMsg<ArtifactDeploymentResponse>(TimeSpan.FromSeconds(10));
|
||||
Assert.True(second.Success);
|
||||
Assert.Equal(["b"], second.SecretsRemoved!);
|
||||
|
||||
// Dropping the last reference retires "a" the same way.
|
||||
manager.Tell(ArtifactsCommand("dep-3", secrets: []));
|
||||
var third = ExpectMsg<ArtifactDeploymentResponse>(TimeSpan.FromSeconds(10));
|
||||
Assert.True(third.Success);
|
||||
Assert.Equal(0, third.SecretsApplied);
|
||||
Assert.Equal(["a"], third.SecretsRemoved!);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Secrets_MirrorFailsOne_SuccessFalse_KekIdInMessage_SecretsAppliedExcludesFailure()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user