From d0e81c5bf4eb68368bf5aa62092eb2599a462ce3 Mon Sep 17 00:00:00 2001 From: Gael <338191059+gael-obin@users.noreply.github.com> Date: Mon, 2 Nov 2026 18:55:05 -0500 Subject: [PATCH 1/3] feat(accounts): verify retained source receipts against original invocation Publish the previously exercised owner implementation for draft review. --- module/CALLABLE_SOURCES.md | 60 ++++ module/REST_SURFACE.md | 15 +- .../api/accounts/authority/contract.binpb | Bin 1311879 -> 1313006 bytes .../proto/saas/accounts/v1/datasource.proto | 31 ++ .../api/accounts/connect/contract.binpb | Bin 1311879 -> 1313006 bytes .../proto/saas/accounts/v1/datasource.proto | 31 ++ module/contracts/api/catalog.codefly.json | 7 +- module/module.package.codefly.yaml | 4 +- module/services/accounts/AUTHZ_MATRIX.md | 5 +- .../adapters/rest_registration_catalog_gen.go | 201 +++++------ .../adapters/source_operation_authority.go | 1 + .../pkg/adapters/source_operation_invoke.go | 54 ++- .../source_operation_refusal_audit_test.go | 6 +- ...ource_operation_verify_integration_test.go | 325 ++++++++++++++++++ .../adapters/source_operation_verify_test.go | 287 ++++++++++++++++ .../code/pkg/business/introspection.go | 1 + .../pkg/business/owned_resource_resolver.go | 1 + .../business/source_operation_integration.go | 12 + .../cataloggen/api_contract_surfaces_test.go | 2 +- .../accountsv1connect/datasource.connect.go | 42 +++ .../pkg/gen/saas/accounts/v1/datasource.pb.go | 140 ++++---- .../gen/saas/accounts/v1/datasource.pb.gw.go | 82 ++++- .../saas/accounts/v1/datasource_grpc.pb.go | 50 +++ .../generated/api-contract-surfaces.json | 3 +- .../accounts/generated/authz-methods.json | 47 +++ .../accounts/generated/gateway-routes.json | 48 +++ .../generated/openapi-raw/api.swagger.json | 59 ++++ .../accounts/generated/rest-surface.json | 16 + .../accounts/generated/service-catalog.json | 64 +++- .../accounts/openapi/api.swagger.json | 59 ++++ .../proto/saas/accounts/v1/datasource.proto | 31 ++ .../auth-gateway/code/authz_catalog_gen.go | 2 + .../auth-gateway/code/routing_catalog_gen.go | 2 + .../code/routing_rest_catalog_gen.go | 1 + .../services/frontend/code/package-lock.json | 4 +- module/services/frontend/code/package.json | 2 +- .../generated/contract/catalog.codefly.json | 5 +- .../generated/contract/contract.binpb | Bin 612094 -> 613221 bytes .../saas-sdk/generated/library.codefly.yaml | 2 +- .../src/gen/saas/accounts/v1/datasource_pb.ts | 17 +- .../code/packages/saas-sdk/package.json | 2 +- .../saas-sdk/test/source-declaration.test.ts | 49 ++- .../src/gen/saas/accounts/v1/datasource_pb.ts | 17 +- 43 files changed, 1579 insertions(+), 208 deletions(-) create mode 100644 module/services/accounts/code/pkg/adapters/source_operation_verify_integration_test.go create mode 100644 module/services/accounts/code/pkg/adapters/source_operation_verify_test.go create mode 100644 module/services/accounts/code/pkg/business/source_operation_integration.go diff --git a/module/CALLABLE_SOURCES.md b/module/CALLABLE_SOURCES.md index 2a5f4623b..bb1d905a1 100644 --- a/module/CALLABLE_SOURCES.md +++ b/module/CALLABLE_SOURCES.md @@ -78,6 +78,51 @@ binding are recovered from verified identity and durable attempt metadata. ## Receipts and uncertain outcomes +### Conditional receipt verification (local owner candidate) + +`VerifySourceOperationReceipt` is a proposed additional read, not an accepted +release contract. It takes the complete original `InvokeSourceOperationRequest` +through Connect/gRPC/gRPC-Web or POST +`/v1/datasource-operation-receipts/verify` with the whole request in the body. +It has no input-bearing GET or query binding. Its request and response are secret. + +The caller must preserve exact `input_json` text and supply the original nonempty +`expected_declaration_digest`. The host normalizes the effect header/field exactly +as Invoke does and applies the same 65,536-byte complete normalized protojson +request bound. Matching headers are allowed; conflicting or empty carriers refuse. +Under the verified tenant, the original actor must still hold read authority to +the **stored** source, including current delegation, membership, boundary and +personal-source checks. Supplied source metadata never grants authority. + +Only after those checks, the host compares the admitted declaration digest and +the complete normalized request with the permanent attempt's SDK request digest. +This reuses `receipts.RequestDigest` and its `codefly.effect-receipt.request.digest/v1` +format; optional-field presence and exact JSON text participate. There is no second +consumer-side fingerprint. A future digest-format change needs an owner migration +that preserves verification of retained attempts; silently rehashing old markers +would not be compatible. No supplied input is newly persisted or logged. + +A committed result means that invocation and admitted declaration match the +stored attempt, and contains the retained response under its existing 1 MiB wire +bound. It says nothing about output correctness, currentness or indefinite retention. +Mismatch returns a generic FailedPrecondition with no output; omitted or empty +declaration preconditions are InvalidArgument. An absent attempt is NotFound; +a matching attempt without retained output is `unknown` with `{}` output and +never authorizes redispatch. Removed/replaced declarations do not prevent the read; +removed sources or revoked authority can refuse it. Legacy invocations that never +pinned a declaration remain recoverable only through the original Lookup. + +Old servers answer Unimplemented. Consumers must refuse unsupported, missing, +malformed, unknown or failed verification; ordinary Lookup success is not a +substitute. Legacy Lookup's request/response and paired Runnable recovery remain +unchanged. This method neither reads a replacement declaration nor contacts a +provider, and introduces no Runnable, ledger, queue or retry mechanism. Its +actor-bound, bounded retention does not provide permanent cross-reviewer evidence. +Owner acceptance, composition qualification and any durable sharing/retention +contract remain separate prerequisites for adoption. + +### Existing receipt lifecycle + The SDK receipts guard serializes `(tenant, effect_id, method)` and verifies the request digest. Its Postgres reads use the request pool under tenant RLS. `receipts.Record` writes the full response using the exact org transaction that @@ -402,3 +447,18 @@ is not release qualification. The CLI preserves scope slots in operation documents and resolves composition selections during preparation, checking that the called endpoint serves both Invoke and Lookup. A passing generation drift check alone does not qualify the delivery path. + +The conditional receipt candidate additionally has an isolated ingress test. +With the documented CLI on `PATH`, run from accounts/code: + +```sh +GOWORK=off go test -race -tags integration ./pkg/adapters -run '^TestSourceOperationVerifyPostgresIngress$' -count=1 -timeout=15m +``` + +It uses the owner's Codefly dependency harness, Postgres/Vault, real signed +sessions, generated Connect client and HTTP POST gateway. It qualifies real +Invoke persistence, caller response loss, binding refusals, legacy Lookup, +current read access, pruning and receipt-pool reopening. Only outbound provider +transport and the retention clock use test seams. It does not qualify a complete +process restart, module-delegation composition, external gateway/proxy deployment, +TypeScript consumer adoption, or production raw body limits. diff --git a/module/REST_SURFACE.md b/module/REST_SURFACE.md index 3f024258b..45de78a08 100644 --- a/module/REST_SURFACE.md +++ b/module/REST_SURFACE.md @@ -17,11 +17,11 @@ module ceiling. The complete regeneration includes these additions and the calla ## Current surface -The accounts projection contains 175 descriptor routes across 30 services, +The accounts projection contains 176 descriptor routes across 30 services, counted from `generated/rest-surface.json`: -- 18 public routes and 157 authenticated routes; -- 148 OpenAPI paths and 175 operations; +- 18 public routes and 158 authenticated routes; +- 149 OpenAPI paths and 176 operations; - zero internal RPCs; - fifteen explicit non-protobuf extensions loaded by auth-gateway: magic-link request/verification, the billing and Resend email webhooks, the two GitHub @@ -29,7 +29,7 @@ counted from `generated/rest-surface.json`: checkout, free-plan, portal, and the four OAuth 2 authorization-server routes (metadata, authorize validation, authorize grant, token). -The generated runtime therefore authorizes 190 REST routes in total. Descriptor +The generated runtime therefore authorizes 191 REST routes in total. Descriptor routes and extensions remain separate so an extension can never be mistaken for a protobuf procedure or inherit policy by path similarity. @@ -119,6 +119,13 @@ from 327 to 324. ## Regeneration +The local candidate `VerifySourceOperationReceipt` is POST-only at +`/v1/datasource-operation-receipts/verify`, with the complete original Invoke +request in its body. It has no query binding, classifies both directions as secret, +and reuses current stored-source read authority and bounded receipt recovery. +See [conditional verification](./CALLABLE_SOURCES.md#conditional-receipt-verification-local-owner-candidate) +for strict declaration, committed/unknown/refusal semantics and adoption limits. + Run from `module/services/accounts`, with Docker running and a Codefly CLI at or above 0.1.160: diff --git a/module/contracts/api/accounts/authority/contract.binpb b/module/contracts/api/accounts/authority/contract.binpb index 257438d435624ec885abbb37d9bf4a00b58aba6b..b142c4957625704a1ab653026d96cab1eb670ae0 100644 GIT binary patch delta 10645 zcmZ9Sd304pp2x|{O(neh?p6s~*j}RD$K$@WGh;j5XIy%;d&Y6>cBZ?JJ$58fqwqp! zadgg%FK7S}0oi{LDN6SHkGjVCJMPc5U+wnH9UbRa+P#-es9V5PCBAn!jWQxmw3u6uH0Ch?$m>9dQd~Aw!XQ(AyYGW@crq= zx|-T1{B5qO&(zhX8(Nx&wlt?(n(8xmrkn4oOQ!4Ys~OasZfLB(vmPzdH)QT@xTg*c z{?t;})O>!rJ~L==ORYM)CY@=>)D0Qhe1E#OZqVSG#u{~z^w7pSbHxjj>2t4X7&4^3 zxf$0QQdg5{QWrtP#vwI>>;DHZ4xFyZ)aJ6oQ$4cjAvMi|?$Ui}YHn!6IW=gG>s*+= zC38=v;lDFzGz8smO1ESh>zWz{-&L3(n)z&u+Rnh92(35Lg z8XM~}&1np;q4E55b6uuJ9c60M`Z5Sv|2G?vsq{ey-u4d>^c)Pvs4)g^w zhYYQ0tZ!<_AmVS-CF`4VQHiX`4y~zIeZ9FQlc~9Va9#Re8XE3t8LI3zH!7nww>R8d zcVRN=B}>$F6-j4=C#nmF33YhZ&kKje>hPC$CIfvkCU>OgJmQIDd9u4|?JVB3qFO=s z5w9dElSz>+P)9lsd*TYh0xOlyC{F~P!j1NvX$U8iWem4$Y_SxhJ$D+SMe!xT(8)(V z@#D@29UbF|^GtZ0RoqQFV=Fvyc4z1Sj>`=jkt)wV=7~vOY3Cq9I+Hyyu=Dw)2>iI` zpV#@cGU?w87v5Yy7`{nH-`hfv+&Id{ZYF42<$ z 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 T@d@w=@rm$}`C%K&#XtT(r7gNu delta 9805 zcmZA7dyo~?odTxFN@Ra?>P%Khh~ zPRI9(qlbFiGQ|fU^17AOw`}YUI zzvW!f%W;($8937l>&N>~e`RtY@9e%`R=LfAxVL*$soW`n_*VBQr`)N5xTkyMDfh)52l~o=DcS28o`8%J zGXkeQD6e^}tf3GM@%k1zCip+iXE6O4fv8WlGZ@s2V8DH)O`MAv!Glkwsu`%x4BRW3p=(B;)n*&vSK6HrFHY*T6{eM}7a%Tr3>{cz`8n`RWNy;QHO0)*v3UiK_VUTm} zIbwu?&I`mhQhP>;{mX$^WbB#3esN-7mGiI;7*&+v%q?!&X^IX-n3MVK(!+fccpraK(({S zfuP!zP+ihg*$O502To^D_-(U)HeZ2R?N8Q`zJDZx*&jp=rA=7v5AM7#wW@&Cfxta& ztSYqCfxtU$teBzdL2JbbmEX2jj559QN*oHrd&Y_}td7`K#)zxzsFl+pN*=Rv%pmtC z3&03+$E_SA$ep0vy}b08f$n6FBSCj6p&M1sRhCuaeBgW@6dR}d|6P{PVv^?rp;D_X zMsq%>x}&rSy7R%12U5B$=q?2AEkl>pbQc2emZ4*YsuwLCBUHX*=@^mj<3L<7bc{jQ zW$74^?pl!jR=VhPh?3VW9W&6~v;d4i_nD<*1iC*5;_h6059yeJ?k_!#1l|88bX^YV zD$%o~GpRVF#sBxRd?n^MQkte!iNTDNrfF3|Zlpxh((R`ba-*a>QI^_IrIs5dy@|5a zeVC!@Xlc3+BUEmb;%n(8!bqsRJ4Tioh{G&d_G6{#AI!kfBu)Qd1degi^bbbh7%vkJ zYA}Mv3qAIN#smqChlx>M#2n6a}%RsH1d>KAe~i(%nUSE50hCS%}vU~P!>pY zlkz~cK$@GB2cm`2U1^9sO|(#YD-97dR9$3=7@_iFOT>sb^d(ZfYKRzvXjx%o!LQ1{ zW>xqbs4TZCjG)qHRTx2Kg;ik$mG&M70;MBCS*~y1K6;gO_R8{_Ib{vQpa1O>!+-Z& z;rW^V?7WZ3td$~4myM5!td;TL(k6)3%DaA)t|A{qMd|J_M7|~}N^g%LVuq^gEDt? zVl17~G&c#OPHCE(gwYx4-Y`Z|8=aBf4P(R%RX?;wj8OTkHDW}gb5dM1MvP%}DKXMd zpN!btE=$wgbcm9l*u}*Ra91oGBfxdp#l;A4R|%(^8#BmVv%ZV~cRhidubW$_#4YJe zF7BD@*Olc%%<+~K{nO1C-ylpGtH%aR%7#)YO2GJ@Rr z&|H>`AooIO9}Ad4ZbB%&nf69Tkee7nZo8I?lxPW^SBlm1{U4U)Bh0ZS6m=<8gu%3g z_1`aTLarrz;E7Z&g50#wU25baEjKOnmKr%`s5(6~j|GfSxe%Ir7$eHf2*n&D#~5<0 zR*n(n=7rh&QaK%>V=&{_f#kO=0K~e@b3qwmU*m zdI?e(){bz{(9}@Da7XyF-=&5MhC4&|s4+yxOkTWqhTc(Q$P86?SwlvsygM{cWQ=II zClvdQA!8UGu!f9i_;#56c50|Ylsse&nZfWKE5Qhc?^;7fFnq6@Au|{ru~#r77`~qv z7PVoO630WQ3x-Qz_(-i+U%2BHzd2up*&YwYZ7Et6hIKr={U@bO7#T+dBGYogW)A> z$OwiXTSG=Lyv%F)2V95DVE9RoBVqVyV)!&0Z*L{8h0f@xyyjO8|Mc{K{QhUp7Y@~V zeF~XZ{rmI1G2?5YC_Tva#?Y>XxBX-4*c*=5!bhG<9ecy^dgzXdO5LQlcDx>XqoPtb zVTP(VtRo{-zG)p9(eblT+%k@g;rMyts4rbc$+OBAp?QH~2C^^h#2JC?uc3K?Vg$0U zxa=s#2x225-EnTivkEhijf_AxK`*;LN{o%1Sup!UL*Z(jS6djf%zrB12lE;mi9sn( zAB<{jH2D6~CbY&zKYupW>I1E&$en4l`e?1D$eU@jn4#*p$aD}!s60M0S1u!Jy%34X zQK|PbhE{WAdM_icx~Wn2Z&N}YqU4K_>AlQA*pf;Bf)NO(MW**M0^#(?_FiT%Ec7@M zgfkMtd77{q9}Y%NTcK{bKPz92DYizY^;Tmnt&wTH)qrb_OzW)%+}y}rZs4jl+}y}p zZs3@q>O2d_2$f%sOzUMtxcQM-Y~UCJZb<^Cml>mEnJtaXGGhj#SL{p~!RU{XS!Rr2 z^eT1lw=H!04&j&qZflPt;kGSt`)9i06VRQJ^8v2TpEnc^ z{Sx=GXWRY1&-cSzcSfQ%y&U^tP&=c#@0K^FF zkh^T<7(wonZud22ko&a9k&wHR$c@%=HA>uwoNwDx)@Zn!k=GQL+9xwq{mjBKLghbOI7Wo~OC-K9aEt->rG;ZexUZt@ zko2O}Axe&jO+#P?xKXir8Dj*v(XnX=i~!ddCk;Vgw9EiErpJ+h8yf@eIbO82N=%5I zd2xBolMRI-gT3m)lWY86 zn9Z_gj9@mKX1vca0@<7%2ZF3MA=|CjT16c`YmA-Mg^$J$pjs5Ws|;10rdkwxs|*!0R9$ST7@_hKOT~zbZD}l)87ju0dM!3hlu=@| zJT^^~8I0QOR2ji&MQoZVBN(+?BStXlNDsUnO_UjsRwhVY8mS)NhsDl*EUZ&_MVR_E ztgMgL`3Lj$nAm!|vg$Fc^>$^|gKNEAS@q!B5W8;~u6oV2A@<%fT+C2)qvc|R%9|_~ zBXYeSi>-!>F}SuRT>2v>M!YuPjLoa64pDN4U1!W-xXT(cg5hqv&KSXP4-NIJDl;JN z?QtXw_a%ncv%EM5;KRAt`3#0fXR0c%nc+4( z_~h^L8TzxurCa>I&O-w+pb^TvKMcg2M=10DFc6v}lzD#`2+fiBj{;R{7X!8CNaal_ zv~KnvO}`LloLqD-D09&vGmr=};|2bHy#4=U7*)vV< zV9H#QjJTTGlzBqaA^!9VW!fb(2zNjwpMC_%48$vy>6eT^yvhqO+u`{ zmQ0k2_)w;s(#GU-pQ7>(K&doUWMyTT|2oz0w(g+=yY;Giuo)S4#A(=&oTP5YCjZ{E zQAIU|3A-gso0QnnjR`53ws!YKB(dW*CHAP_SWv_O*sH{_?td8o`xF|N{uZ;r#a;k- zOQG#|ivX}c`4jW?eSMG;hm~_q6>9e43#dUD>EWb?{zrmAI2(tRX?}w+x5MhkrH{P_ z0q-5$PYm85y~N&8-dVH6n4#*sc8M`U<@f9oW5gwPM45jnVwfzk_mh>Qml(6e?kGO8 zGImU1cOuzQ!!t^**OT^oWro#s%3gMiV0oI${zzmq3b~P~q<{7)17y YkDmZP5Bce4^Y6^Hvj+t diff --git a/module/contracts/api/accounts/authority/proto/saas/accounts/v1/datasource.proto b/module/contracts/api/accounts/authority/proto/saas/accounts/v1/datasource.proto index c95696bd1..1df8959d4 100644 --- a/module/contracts/api/accounts/authority/proto/saas/accounts/v1/datasource.proto +++ b/module/contracts/api/accounts/authority/proto/saas/accounts/v1/datasource.proto @@ -1662,6 +1662,37 @@ service DatasourceService { }; } + // VerifySourceOperationReceipt conditionally reads retained output using the + // exact original Invoke request, including a nonempty declaration precondition. + // Committed means the normalized request and admitted declaration match the + // stored attempt. Unknown remains unresolved; this method never redispatches. + // Current actor, tenant and stored-source read authority apply before comparison. + // This is independent of the paired Runnable Lookup contract above. + rpc VerifySourceOperationReceipt(InvokeSourceOperationRequest) returns (InvokeSourceOperationResponse) { + option (google.api.http) = { + post: "/v1/datasource-operation-receipts/verify" + body: "*" + }; + option (saas.policy.v1.method_policy) = { + exposure: EXPOSURE_AUTHENTICATED + tenant: TENANT_REQUIREMENT_ORG_MEMBER + permissions: "datasource:read" + scopes: "datasource:read" + resource_bindings: { + request_field: "effect_id" + target: RESOURCE_TARGET_OWNED_RESOURCE + lookup: RESOURCE_LOOKUP_RESOURCE_TO_ORGANIZATION + } + mfa: MFA_REQUIREMENT_NONE + audit: {emission: AUDIT_EMISSION_NONE} + idempotency: IDEMPOTENCY_REQUIREMENT_FORBIDDEN + rate_limit: RATE_LIMIT_CLASS_STANDARD_READ + request_sensitivity: SENSITIVITY_SECRET + response_sensitivity: SENSITIVITY_SECRET + platform_role: PLATFORM_ROLE_REQUIREMENT_NONE + }; + } + // ListSourceOperations reads the currently admitted declarations under source authority. rpc ListSourceOperations(ListSourceOperationsRequest) returns (ListSourceOperationsResponse) { option (google.api.http) = {get: "/v1/organizations/{org_id}/datasources/{source_id}/operations"}; diff --git a/module/contracts/api/accounts/connect/contract.binpb b/module/contracts/api/accounts/connect/contract.binpb index 257438d435624ec885abbb37d9bf4a00b58aba6b..b142c4957625704a1ab653026d96cab1eb670ae0 100644 GIT binary patch delta 10645 zcmZ9Sd304pp2x|{O(neh?p6s~*j}RD$K$@WGh;j5XIy%;d&Y6>cBZ?JJ$58fqwqp! zadgg%FK7S}0oi{LDN6SHkGjVCJMPc5U+wnH9UbRa+P#-es9V5PCBAn!jWQxmw3u6uH0Ch?$m>9dQd~Aw!XQ(AyYGW@crq= zx|-T1{B5qO&(zhX8(Nx&wlt?(n(8xmrkn4oOQ!4Ys~OasZfLB(vmPzdH)QT@xTg*c z{?t;})O>!rJ~L==ORYM)CY@=>)D0Qhe1E#OZqVSG#u{~z^w7pSbHxjj>2t4X7&4^3 zxf$0QQdg5{QWrtP#vwI>>;DHZ4xFyZ)aJ6oQ$4cjAvMi|?$Ui}YHn!6IW=gG>s*+= zC38=v;lDFzGz8smO1ESh>zWz{-&L3(n)z&u+Rnh92(35Lg z8XM~}&1np;q4E55b6uuJ9c60M`Z5Sv|2G?vsq{ey-u4d>^c)Pvs4)g^w zhYYQ0tZ!<_AmVS-CF`4VQHiX`4y~zIeZ9FQlc~9Va9#Re8XE3t8LI3zH!7nww>R8d zcVRN=B}>$F6-j4=C#nmF33YhZ&kKje>hPC$CIfvkCU>OgJmQIDd9u4|?JVB3qFO=s z5w9dElSz>+P)9lsd*TYh0xOlyC{F~P!j1NvX$U8iWem4$Y_SxhJ$D+SMe!xT(8)(V z@#D@29UbF|^GtZ0RoqQFV=Fvyc4z1Sj>`=jkt)wV=7~vOY3Cq9I+Hyyu=Dw)2>iI` zpV#@cGU?w87v5Yy7`{nH-`hfv+&Id{ZYF42<$ z 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 T@d@w=@rm$}`C%K&#XtT(r7gNu delta 9805 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 YkDmZP5Bce4^Y6^Hvj+t diff --git a/module/contracts/api/accounts/connect/proto/saas/accounts/v1/datasource.proto b/module/contracts/api/accounts/connect/proto/saas/accounts/v1/datasource.proto index c95696bd1..1df8959d4 100644 --- a/module/contracts/api/accounts/connect/proto/saas/accounts/v1/datasource.proto +++ b/module/contracts/api/accounts/connect/proto/saas/accounts/v1/datasource.proto @@ -1662,6 +1662,37 @@ service DatasourceService { }; } + // VerifySourceOperationReceipt conditionally reads retained output using the + // exact original Invoke request, including a nonempty declaration precondition. + // Committed means the normalized request and admitted declaration match the + // stored attempt. Unknown remains unresolved; this method never redispatches. + // Current actor, tenant and stored-source read authority apply before comparison. + // This is independent of the paired Runnable Lookup contract above. + rpc VerifySourceOperationReceipt(InvokeSourceOperationRequest) returns (InvokeSourceOperationResponse) { + option (google.api.http) = { + post: "/v1/datasource-operation-receipts/verify" + body: "*" + }; + option (saas.policy.v1.method_policy) = { + exposure: EXPOSURE_AUTHENTICATED + tenant: TENANT_REQUIREMENT_ORG_MEMBER + permissions: "datasource:read" + scopes: "datasource:read" + resource_bindings: { + request_field: "effect_id" + target: RESOURCE_TARGET_OWNED_RESOURCE + lookup: RESOURCE_LOOKUP_RESOURCE_TO_ORGANIZATION + } + mfa: MFA_REQUIREMENT_NONE + audit: {emission: AUDIT_EMISSION_NONE} + idempotency: IDEMPOTENCY_REQUIREMENT_FORBIDDEN + rate_limit: RATE_LIMIT_CLASS_STANDARD_READ + request_sensitivity: SENSITIVITY_SECRET + response_sensitivity: SENSITIVITY_SECRET + platform_role: PLATFORM_ROLE_REQUIREMENT_NONE + }; + } + // ListSourceOperations reads the currently admitted declarations under source authority. rpc ListSourceOperations(ListSourceOperationsRequest) returns (ListSourceOperationsResponse) { option (google.api.http) = {get: "/v1/organizations/{org_id}/datasources/{source_id}/operations"}; diff --git a/module/contracts/api/catalog.codefly.json b/module/contracts/api/catalog.codefly.json index e65f99eec..4624f4ebc 100644 --- a/module/contracts/api/catalog.codefly.json +++ b/module/contracts/api/catalog.codefly.json @@ -10,7 +10,7 @@ "kind": "protobuf", "package": "saas.accounts.v1", "path": "contracts/api/accounts/authority/contract.binpb", - "digest": "sha256:606e52170c2e55688ce163eb1d54c347f0d19ac40915d7fb6252f2034b787c0e", + "digest": "sha256:7e1acbb32e08f5a5a41c5da10fb73b4436c4cb53c991af657d7d80a2648e862e", "services": [ { "name": "ModuleCapabilitiesService", @@ -66,7 +66,7 @@ "kind": "protobuf", "package": "", "path": "contracts/api/accounts/connect/contract.binpb", - "digest": "sha256:606e52170c2e55688ce163eb1d54c347f0d19ac40915d7fb6252f2034b787c0e", + "digest": "sha256:7e1acbb32e08f5a5a41c5da10fb73b4436c4cb53c991af657d7d80a2648e862e", "services": [ { "name": "ArtifactService", @@ -259,7 +259,8 @@ "/saas.accounts.v1.DatasourceService/SyncSource", "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup", "/saas.accounts.v1.DatasourceService/UpdateSource", - "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain" + "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain", + "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt" ] }, { diff --git a/module/module.package.codefly.yaml b/module/module.package.codefly.yaml index 75742ac6a..29652c2fa 100644 --- a/module/module.package.codefly.yaml +++ b/module/module.package.codefly.yaml @@ -18,12 +18,12 @@ services: kind: protobuf package: saas.accounts.v1 path: contracts/api/accounts/authority/contract.binpb - digest: sha256:606e52170c2e55688ce163eb1d54c347f0d19ac40915d7fb6252f2034b787c0e + digest: sha256:7e1acbb32e08f5a5a41c5da10fb73b4436c4cb53c991af657d7d80a2648e862e - endpoint: connect kind: protobuf package: "" path: contracts/api/accounts/connect/contract.binpb - digest: sha256:606e52170c2e55688ce163eb1d54c347f0d19ac40915d7fb6252f2034b787c0e + digest: sha256:7e1acbb32e08f5a5a41c5da10fb73b4436c4cb53c991af657d7d80a2648e862e - name: auth-gateway endpoints: [grpc, rest] api-contracts: diff --git a/module/services/accounts/AUTHZ_MATRIX.md b/module/services/accounts/AUTHZ_MATRIX.md index b508aa4ed..9149444e5 100644 --- a/module/services/accounts/AUTHZ_MATRIX.md +++ b/module/services/accounts/AUTHZ_MATRIX.md @@ -2,7 +2,7 @@ > Generated from protobuf service descriptors and `saas.policy.v1.method_policy`; only the prose description is joined from `pkg/business/introspection.go`. Do not edit by hand. Run `go generate ./pkg/business` from `module/services/accounts/code`. -Inventory: **301 RPCs** across **42 services**. Missing, invalid, or unclassified procedures are denied by both Connect and gRPC interceptors. +Inventory: **302 RPCs** across **42 services**. Missing, invalid, or unclassified procedures are denied by both Connect and gRPC interceptors. The compact tier is retained for compatibility. Guards, resource bindings, audit events, limiter class, and data sensitivity are descriptor-authoritative. Domain handlers may enforce stronger state-dependent rules but may not weaken this floor. @@ -106,6 +106,7 @@ The compact tier is retained for compatibility. Guards, resource bindings, audit | `/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup` | unary | `—` | `org_admin` | exposure=AUTHENTICATED; tenant=ORG_ADMIN | — | org_id → ORGANIZATION/DIRECT_ID | SUCCESS: saas.datasource.group_unbound | FORBIDDEN / STANDARD_WRITE | INTERNAL → CONFIDENTIAL | Remove a provider group binding. | | `/saas.accounts.v1.DatasourceService/UpdateSource` | unary | `—` | `org_admin` | exposure=AUTHENTICATED; tenant=ORG_ADMIN | — | org_id → ORGANIZATION/DIRECT_ID | SUCCESS: saas.datasource.source.updated | FORBIDDEN / STANDARD_WRITE | INTERNAL → CONFIDENTIAL | Change what a connected source fetches — its branch and path and file-type filters — keeping its credential, history and collection. | | `/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain` | unary | `—` | `org_admin` | exposure=AUTHENTICATED; tenant=ORG_ADMIN | — | org_id → ORGANIZATION/DIRECT_ID | SUCCESS: saas.datasource.domain_verified | FORBIDDEN / STANDARD_WRITE | INTERNAL → CONFIDENTIAL | Verify a claimed domain by its DNS TXT record. | +| `/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt` | unary | `POST /v1/datasource-operation-receipts/verify` | `org_member` | exposure=AUTHENTICATED; tenant=ORG_MEMBER | perm=datasource:read; scope=datasource:read | effect_id → OWNED_RESOURCE/RESOURCE_TO_ORGANIZATION | — | FORBIDDEN / STANDARD_READ | SECRET → SECRET | Read a source receipt only when the original invocation and admitted declaration match. | | `/saas.accounts.v1.DelegationService/DecideDelegation` | unary | `POST /v1/delegations/{id}:decide` | `org_admin` | exposure=AUTHENTICATED; tenant=ORG_ADMIN | — | org_id → ORGANIZATION/DIRECT_ID | SUCCESS: saas.delegation.approved, saas.delegation.denied | FORBIDDEN / STANDARD_READ | CONFIDENTIAL → CONFIDENTIAL | Approve or deny a delegation request. | | `/saas.accounts.v1.DelegationService/ListPendingDelegations` | unary | `GET /v1/delegations:pending` | `org_member` | exposure=AUTHENTICATED; tenant=ORG_MEMBER | — | org_id → ORGANIZATION/DIRECT_ID | — | FORBIDDEN / STANDARD_READ | CONFIDENTIAL → CONFIDENTIAL | List pending organization delegations. | | `/saas.accounts.v1.DelegationService/RequestDelegation` | unary | `POST /v1/delegations` | `org_member` | exposure=AUTHENTICATED; tenant=ORG_MEMBER | — | org_id → ORGANIZATION/DIRECT_ID | SUCCESS: saas.delegation.requested, saas.delegation.auto_approved | FORBIDDEN / STANDARD_WRITE | CONFIDENTIAL → CONFIDENTIAL | Request a scoped authority delegation. | @@ -316,7 +317,7 @@ The compact tier is retained for compatibility. Guards, resource bindings, audit - `internal`: 55 - `mfa`: 5 - `org_admin`: 71 -- `org_member`: 57 +- `org_member`: 58 - `platform_admin`: 29 - `public`: 32 diff --git a/module/services/accounts/code/pkg/adapters/rest_registration_catalog_gen.go b/module/services/accounts/code/pkg/adapters/rest_registration_catalog_gen.go index 20f82c23a..abf5a832f 100644 --- a/module/services/accounts/code/pkg/adapters/rest_registration_catalog_gen.go +++ b/module/services/accounts/code/pkg/adapters/rest_registration_catalog_gen.go @@ -114,106 +114,107 @@ func registerCatalogRESTHandlers(ctx context.Context, mux *runtime.ServeMux, end } var catalogRESTExactRoutes = map[string]struct{}{ - "DELETE /v1/record-shares": {}, - "DELETE /v1/role-assignments": {}, - "DELETE /v1/scope-grants": {}, - "GET /v1/.well-known/service-info": {}, - "GET /v1/accessible-scopes": {}, - "GET /v1/acquisition": {}, - "GET /v1/api-keys": {}, - "GET /v1/audit-event-types": {}, - "GET /v1/audit-log": {}, - "GET /v1/audit-log:aggregate": {}, - "GET /v1/auth/.well-known/jwks.json": {}, - "GET /v1/collection-access": {}, - "GET /v1/consent/status": {}, - "GET /v1/delegations:pending": {}, - "GET /v1/installations": {}, - "GET /v1/installations:listAvailable": {}, - "GET /v1/invitations": {}, - "GET /v1/mfa/devices": {}, - "GET /v1/notifications": {}, - "GET /v1/notifications/unread-count": {}, - "GET /v1/organizations": {}, - "GET /v1/platform/admins": {}, - "GET /v1/platform/catalogue": {}, - "GET /v1/platform/events/operations": {}, - "GET /v1/platform/events/subscriptions": {}, - "GET /v1/platform/feature-flags": {}, - "GET /v1/platform/jobs": {}, - "GET /v1/platform/jobs/operations": {}, - "GET /v1/platform/module-envelope": {}, - "GET /v1/platform/sessions": {}, - "GET /v1/platform/users": {}, - "GET /v1/platform/waitlist": {}, - "GET /v1/principals": {}, - "GET /v1/public/plans": {}, - "GET /v1/record-shares": {}, - "GET /v1/role-assignments": {}, - "GET /v1/roles": {}, - "GET /v1/user/settings": {}, - "GET /v1/users": {}, - "GET /v1/users/self": {}, - "GET /v1/users:byEmail": {}, - "GET /v1/users:findByIdentity": {}, - "GET /v1/version": {}, - "GET /v1/webhooks": {}, - "POST /v1/api-keys": {}, - "POST /v1/audit-log:export": {}, - "POST /v1/auth/authenticate": {}, - "POST /v1/auth/clients/authorize": {}, - "POST /v1/auth/clients/validate": {}, - "POST /v1/auth/logout": {}, - "POST /v1/auth/mfa/complete": {}, - "POST /v1/auth/mfa/webauthn/begin": {}, - "POST /v1/auth/mfa/webauthn/complete": {}, - "POST /v1/auth/oauth/begin": {}, - "POST /v1/auth/refresh": {}, - "POST /v1/auth/switch-organization": {}, - "POST /v1/auth/token": {}, - "POST /v1/billing/connect/portal": {}, - "POST /v1/consent/terms": {}, - "POST /v1/delegations": {}, - "POST /v1/gdpr/delete": {}, - "POST /v1/gdpr/export": {}, - "POST /v1/installations": {}, - "POST /v1/invitations": {}, - "POST /v1/invitations:accept": {}, - "POST /v1/invitations:inspect": {}, - "POST /v1/invitations:inspect-id": {}, - "POST /v1/mfa/backup-codes": {}, - "POST /v1/mfa/totp/setup": {}, - "POST /v1/mfa/totp/verify": {}, - "POST /v1/mfa/webauthn/register/begin": {}, - "POST /v1/mfa/webauthn/register/finish": {}, - "POST /v1/notifications:read-all": {}, - "POST /v1/organizations": {}, - "POST /v1/platform/admins": {}, - "POST /v1/platform/impersonation:stop": {}, - "POST /v1/principals:agent": {}, - "POST /v1/record-shares": {}, - "POST /v1/resource-follows": {}, - "POST /v1/resource-follows:unfollow": {}, - "POST /v1/role-assignments": {}, - "POST /v1/roles": {}, - "POST /v1/scope-grants": {}, - "POST /v1/scope-nodes": {}, - "POST /v1/solution-installations": {}, - "POST /v1/solution-installations/review": {}, - "POST /v1/sso/disable": {}, - "POST /v1/sso/setup": {}, - "POST /v1/user/settings": {}, - "POST /v1/users": {}, - "POST /v1/waitlist": {}, - "POST /v1/waitlist:verify": {}, - "POST /v1/webhooks": {}, - "POST /v1/work-contexts:child-session": {}, - "POST /v1/work-contexts:exchange-audience": {}, - "POST /v1/work-contexts:renew": {}, - "POST /v1/work-contexts:root-session": {}, - "POST /v1/work-contexts:task": {}, - "PUT /v1/consent/preferences": {}, - "PUT /v1/platform/module-envelope": {}, + "DELETE /v1/record-shares": {}, + "DELETE /v1/role-assignments": {}, + "DELETE /v1/scope-grants": {}, + "GET /v1/.well-known/service-info": {}, + "GET /v1/accessible-scopes": {}, + "GET /v1/acquisition": {}, + "GET /v1/api-keys": {}, + "GET /v1/audit-event-types": {}, + "GET /v1/audit-log": {}, + "GET /v1/audit-log:aggregate": {}, + "GET /v1/auth/.well-known/jwks.json": {}, + "GET /v1/collection-access": {}, + "GET /v1/consent/status": {}, + "GET /v1/delegations:pending": {}, + "GET /v1/installations": {}, + "GET /v1/installations:listAvailable": {}, + "GET /v1/invitations": {}, + "GET /v1/mfa/devices": {}, + "GET /v1/notifications": {}, + "GET /v1/notifications/unread-count": {}, + "GET /v1/organizations": {}, + "GET /v1/platform/admins": {}, + "GET /v1/platform/catalogue": {}, + "GET /v1/platform/events/operations": {}, + "GET /v1/platform/events/subscriptions": {}, + "GET /v1/platform/feature-flags": {}, + "GET /v1/platform/jobs": {}, + "GET /v1/platform/jobs/operations": {}, + "GET /v1/platform/module-envelope": {}, + "GET /v1/platform/sessions": {}, + "GET /v1/platform/users": {}, + "GET /v1/platform/waitlist": {}, + "GET /v1/principals": {}, + "GET /v1/public/plans": {}, + "GET /v1/record-shares": {}, + "GET /v1/role-assignments": {}, + "GET /v1/roles": {}, + "GET /v1/user/settings": {}, + "GET /v1/users": {}, + "GET /v1/users/self": {}, + "GET /v1/users:byEmail": {}, + "GET /v1/users:findByIdentity": {}, + "GET /v1/version": {}, + "GET /v1/webhooks": {}, + "POST /v1/api-keys": {}, + "POST /v1/audit-log:export": {}, + "POST /v1/auth/authenticate": {}, + "POST /v1/auth/clients/authorize": {}, + "POST /v1/auth/clients/validate": {}, + "POST /v1/auth/logout": {}, + "POST /v1/auth/mfa/complete": {}, + "POST /v1/auth/mfa/webauthn/begin": {}, + "POST /v1/auth/mfa/webauthn/complete": {}, + "POST /v1/auth/oauth/begin": {}, + "POST /v1/auth/refresh": {}, + "POST /v1/auth/switch-organization": {}, + "POST /v1/auth/token": {}, + "POST /v1/billing/connect/portal": {}, + "POST /v1/consent/terms": {}, + "POST /v1/datasource-operation-receipts/verify": {}, + "POST /v1/delegations": {}, + "POST /v1/gdpr/delete": {}, + "POST /v1/gdpr/export": {}, + "POST /v1/installations": {}, + "POST /v1/invitations": {}, + "POST /v1/invitations:accept": {}, + "POST /v1/invitations:inspect": {}, + "POST /v1/invitations:inspect-id": {}, + "POST /v1/mfa/backup-codes": {}, + "POST /v1/mfa/totp/setup": {}, + "POST /v1/mfa/totp/verify": {}, + "POST /v1/mfa/webauthn/register/begin": {}, + "POST /v1/mfa/webauthn/register/finish": {}, + "POST /v1/notifications:read-all": {}, + "POST /v1/organizations": {}, + "POST /v1/platform/admins": {}, + "POST /v1/platform/impersonation:stop": {}, + "POST /v1/principals:agent": {}, + "POST /v1/record-shares": {}, + "POST /v1/resource-follows": {}, + "POST /v1/resource-follows:unfollow": {}, + "POST /v1/role-assignments": {}, + "POST /v1/roles": {}, + "POST /v1/scope-grants": {}, + "POST /v1/scope-nodes": {}, + "POST /v1/solution-installations": {}, + "POST /v1/solution-installations/review": {}, + "POST /v1/sso/disable": {}, + "POST /v1/sso/setup": {}, + "POST /v1/user/settings": {}, + "POST /v1/users": {}, + "POST /v1/waitlist": {}, + "POST /v1/waitlist:verify": {}, + "POST /v1/webhooks": {}, + "POST /v1/work-contexts:child-session": {}, + "POST /v1/work-contexts:exchange-audience": {}, + "POST /v1/work-contexts:renew": {}, + "POST /v1/work-contexts:root-session": {}, + "POST /v1/work-contexts:task": {}, + "PUT /v1/consent/preferences": {}, + "PUT /v1/platform/module-envelope": {}, } type catalogRESTTemplateRoute struct { diff --git a/module/services/accounts/code/pkg/adapters/source_operation_authority.go b/module/services/accounts/code/pkg/adapters/source_operation_authority.go index 970c7a58c..379f67421 100644 --- a/module/services/accounts/code/pkg/adapters/source_operation_authority.go +++ b/module/services/accounts/code/pkg/adapters/source_operation_authority.go @@ -38,6 +38,7 @@ func sourceOperationProcedure(method string) bool { case business.SourceOperationMethod, "/saas.accounts.v1.DatasourceService/ListSourceOperations", "/saas.accounts.v1.DatasourceService/LookupInvokeSourceOperation", + "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", business.SourceReceiptRetentionMethod, "/saas.accounts.v1.DatasourceService/LookupPruneSourceOperationReceipts", business.ReconcileSourceMethod, diff --git a/module/services/accounts/code/pkg/adapters/source_operation_invoke.go b/module/services/accounts/code/pkg/adapters/source_operation_invoke.go index 0759009c4..79d4c0c5a 100644 --- a/module/services/accounts/code/pkg/adapters/source_operation_invoke.go +++ b/module/services/accounts/code/pkg/adapters/source_operation_invoke.go @@ -1,6 +1,7 @@ package adapters import ( + "bytes" "context" "errors" "net/http" @@ -144,6 +145,48 @@ func (h *datasourceConnectHandler) LookupInvokeSourceOperation(ctx context.Conte if err := Validate(req.Msg); err != nil { return nil, translateGRPCError(err) } + attempt, err := h.authorizedSourceOperationAttempt(ctx, req.Header(), req.Msg.EffectId) + if err != nil { + return nil, err + } + return h.retainedSourceOperationResponse(ctx, attempt) +} + +// VerifySourceOperationReceipt is a conditional read, not an invocation or a +// paired Runnable lookup. Only the stored source can supply its authority. +func (h *datasourceConnectHandler) VerifySourceOperationReceipt(ctx context.Context, req *connect.Request[gen.InvokeSourceOperationRequest]) (*connect.Response[gen.InvokeSourceOperationResponse], error) { + ctx = connectCtx(ctx, req.Header()) + if err := Validate(req.Msg); err != nil { + return nil, translateGRPCError(err) + } + if req.Msg.GetExpectedDeclarationDigest() == "" { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("source declaration precondition required")) + } + effect, err := sourceEffectID(req.Header(), req.Msg.EffectId) + if err != nil { + return nil, err + } + normalized := proto.CloneOf(req.Msg) + normalized.EffectId = effect + if !sourceWireFits(normalized, sourceInputEnvelopeBytes) { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("source input exceeds wire bound")) + } + attempt, err := h.authorizedSourceOperationAttempt(ctx, req.Header(), effect) + if err != nil { + return nil, err + } + digest, err := receipts.RequestDigest(normalized) + if err != nil { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("source request invalid")) + } + org, _, _ := auth.VerifiedDatabaseIdentity(ctx) // Established by the shared authorization above. + if normalized.OrgId != org || normalized.OrgId != attempt.OrgID || normalized.SourceId != attempt.SourceID || normalized.Operation != attempt.Operation || normalized.GetExpectedDeclarationDigest() != attempt.DeclarationDigest || !bytes.Equal(digest, attempt.RequestDigest) { + return nil, connect.NewError(connect.CodeFailedPrecondition, errors.New("source receipt verification refused")) + } + return h.retainedSourceOperationResponse(ctx, attempt) +} + +func (h *datasourceConnectHandler) authorizedSourceOperationAttempt(ctx context.Context, header http.Header, field string) (*business.SourceOperationAttempt, error) { actor, err := callerID(ctx) if err != nil { return nil, err @@ -155,7 +198,7 @@ func (h *datasourceConnectHandler) LookupInvokeSourceOperation(ctx context.Conte if err = requireOrgMember(ctx, actor, org); err != nil { return nil, translateGRPCError(err) } - effect, err := sourceEffectID(req.Header(), req.Msg.EffectId) + effect, err := sourceEffectID(header, field) if err != nil { return nil, err } @@ -172,16 +215,21 @@ func (h *datasourceConnectHandler) LookupInvokeSourceOperation(ctx context.Conte if _, _, err = h.svc.SourceOperationAuthority(ctx, actor, org, attempt.SourceID, attempt.Operation, effect, "", true); err != nil { return nil, translateGRPCError(err) } + return attempt, nil +} + +func (h *datasourceConnectHandler) retainedSourceOperationResponse(ctx context.Context, attempt *business.SourceOperationAttempt) (*connect.Response[gen.InvokeSourceOperationResponse], error) { + org, _, _ := auth.VerifiedDatabaseIdentity(ctx) // Keep receipt reads under verified identity. store, _ := h.svc.SourceOperationReceipts() if store == nil { return nil, connect.NewError(connect.CodeUnavailable, errors.New("source receipts unavailable")) } - saved, found, err := store.Lookup(ctx, org, effect, business.SourceOperationMethod) + saved, found, err := store.Lookup(ctx, org, attempt.EffectID, business.SourceOperationMethod) if err != nil { return nil, connect.NewError(connect.CodeUnavailable, errors.New("source receipt unavailable")) } if !found { - return connect.NewResponse(sourceUnknownResponse(effect)), nil + return connect.NewResponse(sourceUnknownResponse(attempt.EffectID)), nil } out := &gen.InvokeSourceOperationResponse{} if proto.Unmarshal(saved.Response, out) != nil || !sourceWireFits(out, sourceOutputEnvelopeBytes) { diff --git a/module/services/accounts/code/pkg/adapters/source_operation_refusal_audit_test.go b/module/services/accounts/code/pkg/adapters/source_operation_refusal_audit_test.go index c562a21bd..6d8ea6641 100644 --- a/module/services/accounts/code/pkg/adapters/source_operation_refusal_audit_test.go +++ b/module/services/accounts/code/pkg/adapters/source_operation_refusal_audit_test.go @@ -3,6 +3,7 @@ package adapters import ( "context" "net/http" + "strings" "testing" "accounts/pkg/auth" @@ -12,6 +13,7 @@ import ( "connectrpc.com/connect" basev0 "github.com/codefly-dev/core/generated/go/codefly/base/v0" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" ) // Use the real mint and verifier: a hand-stamped delegation key cannot prove @@ -35,7 +37,7 @@ func TestSourceOperationDelegatedRefusalAudited(t *testing.T) { require.NoError(t, err) require.NoError(t, requireSourceOperationScope(ctx, delegationOrg, borrowed, "invoke")) - for _, method := range []string{"invoke", "lookup", "prune", "lookup-prune"} { + for _, method := range []string{"invoke", "lookup", "verify", "prune", "lookup-prune"} { t.Run(method, func(t *testing.T) { store := &sourceRefusalStore{sourceWireStore: &sourceWireStore{role: gen.OrgRole_ORG_ROLE_ADMIN, attempt: &business.SourceOperationAttempt{OrgID: delegationOrg, ActorID: delegationPerson, SourceID: other, Operation: "read_item", EffectID: "refused-effect"}}} @@ -52,6 +54,8 @@ func TestSourceOperationDelegatedRefusalAudited(t *testing.T) { _, err = h.InvokeSourceOperation(ctx, connect.NewRequest(&gen.InvokeSourceOperationRequest{OrgId: delegationOrg, SourceId: other, Operation: "read_item", InputJson: `{"private":"must not enter audit"}`, EffectId: "refused-effect"})) case "lookup": _, err = h.LookupInvokeSourceOperation(ctx, connect.NewRequest(&gen.LookupInvokeSourceOperationRequest{EffectId: "refused-effect"})) + case "verify": + _, err = h.VerifySourceOperationReceipt(ctx, connect.NewRequest(&gen.InvokeSourceOperationRequest{OrgId: delegationOrg, SourceId: borrowed, Operation: "read_item", InputJson: `{"private":"must not enter audit"}`, EffectId: "refused-effect", ExpectedDeclarationDigest: proto.String("sha256:" + strings.Repeat("a", 64))})) case "prune": _, err = h.PruneSourceOperationReceipts(ctx, connect.NewRequest(&gen.PruneSourceOperationReceiptsRequest{OrgId: delegationOrg, SourceId: other, EffectId: "refused-effect"})) case "lookup-prune": diff --git a/module/services/accounts/code/pkg/adapters/source_operation_verify_integration_test.go b/module/services/accounts/code/pkg/adapters/source_operation_verify_integration_test.go new file mode 100644 index 000000000..72a00db0a --- /dev/null +++ b/module/services/accounts/code/pkg/adapters/source_operation_verify_integration_test.go @@ -0,0 +1,325 @@ +//go:build integration + +package adapters + +import ( + "bytes" + "context" + "crypto/rand" + "io" + "net/http" + "net/http/httptest" + "strings" + "sync/atomic" + "testing" + "time" + + "accounts/internal/testdb" + "accounts/pkg/auth" + ed25519minter "accounts/pkg/auth/ed25519" + pgauth "accounts/pkg/auth/pg" + "accounts/pkg/business" + "accounts/pkg/datasource/apisource" + "accounts/pkg/datasource/connector/connectortest" + "accounts/pkg/datasource/operations" + gen "accounts/pkg/gen/saas/accounts/v1" + "accounts/pkg/gen/saas/accounts/v1/accountsv1connect" + "accounts/pkg/infra" + "accounts/pkg/keyservice" + + "connectrpc.com/connect" + "github.com/codefly-dev/core/sdk" + codefly "github.com/codefly-dev/sdk-go" + "github.com/codefly-dev/sdk-go/receipts" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +// Uses the same package lock and isolated Codefly dependency lifecycle as the +// business integration suite. No identity-stamping interceptor or seeded +// attempt/digest is involved: signed requests enter the production interceptor. +func TestSourceOperationVerifyPostgresIngress(t *testing.T) { + _, err := testdb.RunWithPackageLock(func() int { + t.Run("isolated owner dependencies", testSourceReceiptIngress) + return 0 + }) + require.NoError(t, err) +} + +func testSourceReceiptIngress(t *testing.T) { + ctx := context.Background() + deps, err := sdk.WithDependencies(ctx, sdk.WithExcludedDependencies("object-storage", "cache"), + sdk.WithNamingScope("receipt-ingress-test"), sdk.WithTimeout(10*time.Minute), sdk.WithSilence("store")) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, deps.Destroy(context.Background())) }) + _, err = codefly.Init(ctx) + require.NoError(t, err) + store, err := infra.NewPostgresStore(ctx) + require.NoError(t, err) + t.Cleanup(store.Close) + svc, err := business.NewService(store) + require.NoError(t, err) + keys, err := keyservice.Load(ctx) + require.NoError(t, err) + svc.SetDatasourceConnector(keys.Cipher, nil, "") + ticket, link := make([]byte, 32), make([]byte, 32) + _, err = rand.Read(ticket) + require.NoError(t, err) + _, err = rand.Read(link) + require.NoError(t, err) + svc.SetDatasourceKeys(ticket, link) + emitter, err := business.NewDurableAuditEmitter(store, store) + require.NoError(t, err) + t.Cleanup(emitter.Close) + svc.SetAuditEmitter(emitter) + require.NoError(t, store.WithControlPlane(ctx, func(ctx context.Context) error { + return store.SyncAuditEventTypes(ctx, business.AuditEventCatalog()) + })) + _, privateKey, err := ed25519minter.GenerateKey() + require.NoError(t, err) + minter := ed25519minter.New(ed25519minter.Config{Issuer: "receipt-test", Audience: "receipt-test"}, privateKey, pgauth.NewSessionStore(store)) + svc.SetJWTMinter(minter) + resolver := pgauth.NewResolver(store) + resolver.SetBootstrapAdminEmail("") + svc.SetIdentityResolver(resolver) + identity := func(name string) *auth.Identity { + id, err := resolver.Resolve(ctx, &auth.Claims{Provider: "email", Subject: name, + Email: name + "@test.invalid", EmailVerified: true}, auth.SignupIntent{OrganizationName: name}) + require.NoError(t, err) + return id + } + owner, other := identity("receipt-owner"), identity("receipt-other") + token := func(id *auth.Identity) string { + pair, err := minter.Mint(ctx, id) + require.NoError(t, err) + return pair.AccessToken + } + ownerToken, otherToken := token(owner), token(other) + org, actor := owner.OrgID.String(), owner.UserID.String() + // The maintained fixture membership path supplies a second real member; + // its signed session is then independently verified by ingress. + require.NoError(t, svc.ConvergeFixtureOrgMember(ctx, &gen.AddOrgMemberRequest{ + OrgId: org, UserId: other.UserID.String(), Role: gen.OrgRole_ORG_ROLE_MEMBER})) + member := *other + member.OrgID, member.OrgRole = owner.OrgID, "member" + member.SessionID = business.NewID() + memberToken := token(&member) + receiptStore, closeReceipts, err := store.NewEffectReceipts() + require.NoError(t, err) + t.Cleanup(func() { closeReceipts() }) + clock := &ingressReceiptClock{Store: receiptStore} + require.NoError(t, svc.ConfigureSourceOperationReceipts(clock)) + previous := service + WithService(svc) + t.Cleanup(func() { WithService(previous) }) + servers, err := NewGrpServer(&Configuration{}) + require.NoError(t, err) + endpoint := serveContractConnectTier(t, servers, "") + client := accountsv1connect.NewDatasourceServiceClient(http.DefaultClient, "http://"+endpoint) + var calls atomic.Int64 + provider := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + calls.Add(1) + require.Equal(t, "Bearer synthetic-provider-credential", r.Header.Get("Authorization")) + _, _ = w.Write([]byte(`{}`)) + })) + t.Cleanup(provider.Close) + // The existing owner test transport seam allows a loopback provider; the + // production egress IP guard is qualified separately by apisource tests. + svc.SetSourceOperationIntegrationClient(func(_ apisource.Config, credential string) business.APIOperationClient { + return ingressProvider{credential: credential} + }) + added, err := client.AddSource(ctx, signedReceiptRequest(&gen.AddSourceRequest{OrgId: org, + Provider: gen.DatasourceProvider_DATASOURCE_PROVIDER_API, + Boundary: &gen.AddSourceRequest_CollectionLabel{CollectionLabel: "Receipt ingress"}, + Credential: "synthetic-provider-credential", + Config: &gen.AddSourceRequest_Api{Api: &gen.ApiDatasourceConfig{BaseUrl: provider.URL, ResourcePath: "/items", + CredentialKind: gen.ApiCredentialKind_API_CREDENTIAL_KIND_BEARER}}}, ownerToken)) + require.NoError(t, err) + source := added.Msg.Datasource + var grant *gen.ScopeGrant + require.NoError(t, store.WithOrgTx(ctx, org, func(ctx context.Context) error { + collections, err := store.ListCollectionAccess(ctx, org, "", 100, []string{"datasource"}) + if err != nil { + return err + } + var path string + for _, collection := range collections { + if collection.GetNode().GetId() == source.BoundaryNodeId { + path = collection.GetNode().GetScopePath() + } + } + require.NotEmpty(t, path) + role := business.NewIDString() + if err := store.CreateRole(ctx, &gen.Role{Id: role, Name: "Receipt operations", OrgId: org, + Permissions: []*gen.Permission{{Resource: "datasource", Action: "invoke"}, {Resource: "datasource", Action: "read"}}}); err != nil { + return err + } + grant = &gen.ScopeGrant{Id: business.NewIDString(), OrgId: org, SubjectId: actor, + SubjectKind: gen.SubjectKind_SUBJECT_KIND_PRINCIPAL, ScopePath: path, RoleId: role, GrantedBy: actor} + return store.GrantScope(ctx, grant) + })) + d := connectortest.OperationDeclaration() + d.Effect, d.Method = operations.Mutation, "POST" + declaration, err := declarationToProto(d) + require.NoError(t, err) + declared, err := client.DeclareSourceOperations(ctx, signedReceiptRequest(&gen.DeclareSourceOperationsRequest{ + OrgId: org, SourceId: source.Id, Operations: []*gen.SourceOperation{declaration}}, ownerToken)) + require.NoError(t, err) + original := &gen.InvokeSourceOperationRequest{OrgId: org, SourceId: source.Id, Operation: d.Name, + EffectId: "ingress-effect", InputJson: `{"id":"one"}`, ExpectedDeclarationDigest: proto.String(declared.Msg.Operations[0].Digest)} + // Consume and discard a successful HTTP response at the caller boundary. + // The caller sees a lost response, while the real Invoke transaction commits. + lostClient := accountsv1connect.NewDatasourceServiceClient(&http.Client{Transport: discardInvokeResponse{}}, "http://"+endpoint) + _, err = lostClient.InvokeSourceOperation(ctx, signedReceiptRequest(original, ownerToken)) + require.Error(t, err) + require.EqualValues(t, 1, calls.Load()) + verified, err := client.VerifySourceOperationReceipt(ctx, signedReceiptRequest(original, ownerToken)) + require.NoError(t, err) + require.Equal(t, "committed", verified.Msg.Receipt.Status) + require.Equal(t, `{}`, verified.Msg.OutputJson) + replayed, err := client.InvokeSourceOperation(ctx, signedReceiptRequest(original, ownerToken)) + require.NoError(t, err) + require.True(t, proto.Equal(verified.Msg, replayed.Msg)) + require.EqualValues(t, 1, calls.Load(), "Invoke replay must not redispatch") + + // Actual generated REST -> gRPC -> Connect path, including production + // Authorization forwarding, uses the same signed session and retained row. + conn, err := grpc.NewClient(endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + t.Cleanup(func() { _ = conn.Close() }) + mux := runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(restIdentityHeaderMatcher)) + require.NoError(t, gen.RegisterDatasourceServiceHandlerClient(ctx, mux, gen.NewDatasourceServiceClient(conn))) + postEndpoint := httptest.NewServer(mux) + t.Cleanup(postEndpoint.Close) + postVerify := func(request *gen.InvokeSourceOperationRequest, bearer string) *httptest.ResponseRecorder { + wire, err := protojson.Marshal(request) + require.NoError(t, err) + r, err := http.NewRequestWithContext(ctx, http.MethodPost, postEndpoint.URL+"/v1/datasource-operation-receipts/verify", bytes.NewReader(wire)) + require.NoError(t, err) + r.Header.Set("Content-Type", "application/json") + r.Header.Set("Authorization", "Bearer "+bearer) + response, err := postEndpoint.Client().Do(r) + require.NoError(t, err) + defer response.Body.Close() + w := httptest.NewRecorder() + w.WriteHeader(response.StatusCode) + _, err = io.Copy(w, response.Body) + require.NoError(t, err) + return w + } + w := postVerify(original, ownerToken) + require.Equal(t, http.StatusOK, w.Code, w.Body.String()) + for _, change := range []func(*gen.InvokeSourceOperationRequest){ + func(r *gen.InvokeSourceOperationRequest) { r.InputJson = `{"id":"two"}` }, + func(r *gen.InvokeSourceOperationRequest) { + r.ExpectedDeclarationDigest = proto.String("sha256:" + strings.Repeat("a", 64)) + }, + func(r *gen.InvokeSourceOperationRequest) { r.SourceId = business.NewIDString() }, + func(r *gen.InvokeSourceOperationRequest) { r.OrgId = other.OrgID.String() }, + func(r *gen.InvokeSourceOperationRequest) { r.ExpectedDeclarationDigest = nil }, + func(r *gen.InvokeSourceOperationRequest) { + r.InputJson = strings.Repeat(" ", sourceInputEnvelopeBytes+1) + }, + } { + modified := proto.CloneOf(original) + change(modified) + require.Equal(t, http.StatusBadRequest, postVerify(modified, ownerToken).Code) + } + require.Equal(t, http.StatusNotFound, postVerify(original, otherToken).Code) + require.Equal(t, http.StatusBadRequest, postVerify(original, memberToken).Code, "another actor cannot reuse this effect") + require.Equal(t, http.StatusUnauthorized, postVerify(original, "invalid-token").Code) + missing := proto.CloneOf(original) + missing.EffectId = "never-invoked" + require.Equal(t, http.StatusNotFound, postVerify(missing, ownerToken).Code) + legacy, err := client.LookupInvokeSourceOperation(ctx, signedReceiptRequest(&gen.LookupInvokeSourceOperationRequest{EffectId: original.EffectId}, ownerToken)) + require.NoError(t, err) + require.True(t, proto.Equal(verified.Msg, legacy.Msg)) + // Reopen the receipt pool over the same database, then rebuild its guard. + // This is pool/guard restart coverage, not a full process restart claim. + closeReceipts() + reopened, closeReopened, err := store.NewEffectReceipts() + require.NoError(t, err) + t.Cleanup(func() { closeReopened() }) + clock.Store = reopened + require.NoError(t, svc.ConfigureSourceOperationReceipts(clock)) + require.Equal(t, http.StatusOK, postVerify(original, ownerToken).Code) + // Real Invoke persists an old receipt through the existing storage-clock + // seam; public retention removes it while the permanent attempt survives. + clock.before = time.Now().Add(-48 * time.Hour) + expired := proto.CloneOf(original) + expired.EffectId = "expired-effect" + _, err = client.InvokeSourceOperation(ctx, signedReceiptRequest(expired, ownerToken)) + require.NoError(t, err) + clock.before = time.Time{} + _, err = client.PruneSourceOperationReceipts(ctx, signedReceiptRequest(&gen.PruneSourceOperationReceiptsRequest{OrgId: org, SourceId: source.Id, EffectId: "prune-effect"}, ownerToken)) + require.NoError(t, err) + expiredResponse := postVerify(expired, ownerToken) + require.Equal(t, http.StatusOK, expiredResponse.Code) + require.Contains(t, expiredResponse.Body.String(), `"unknown"`) + // Removing the declaration does not erase already committed evidence. + _, err = client.DeclareSourceOperations(ctx, signedReceiptRequest(&gen.DeclareSourceOperationsRequest{OrgId: org, SourceId: source.Id}, ownerToken)) + require.NoError(t, err) + require.Equal(t, http.StatusOK, postVerify(original, ownerToken).Code) + require.NoError(t, store.WithOrgTx(ctx, org, func(ctx context.Context) error { + _, err := store.UpdateRole(ctx, grant.RoleId, org, "Read-only receipt access", []*gen.Permission{{Resource: "datasource", Action: "read"}}) + return err + })) + require.Equal(t, http.StatusOK, postVerify(original, ownerToken).Code, "verification requires read, not invoke") + require.NoError(t, store.WithOrgTx(ctx, org, func(ctx context.Context) error { + return store.RevokeScope(ctx, org, actor, grant.SubjectKind, grant.ScopePath, grant.RoleId) + })) + require.Equal(t, http.StatusForbidden, postVerify(original, ownerToken).Code) + require.EqualValues(t, 2, calls.Load(), "only the two distinct Invoke effects may dispatch") +} + +func signedReceiptRequest[T any](message *T, token string) *connect.Request[T] { + r := connect.NewRequest(message) + r.Header().Set("Authorization", "Bearer "+token) + return r +} + +type ingressReceiptClock struct { + receipts.Store + before time.Time +} + +func (c *ingressReceiptClock) Record(ctx context.Context, tx receipts.Tx, receipt receipts.Receipt) error { + if !c.before.IsZero() { + receipt.CommittedAt = c.before + } + return c.Store.Record(ctx, tx, receipt) +} + +type discardInvokeResponse struct{} + +func (discardInvokeResponse) RoundTrip(r *http.Request) (*http.Response, error) { + response, err := http.DefaultTransport.RoundTrip(r) + if err != nil { + return nil, err + } + _, _ = io.Copy(io.Discard, response.Body) + _ = response.Body.Close() + return nil, io.ErrUnexpectedEOF +} + +type ingressProvider struct{ credential string } + +func (p ingressProvider) Do(ctx context.Context, method, target string, body []byte) (*apisource.Result, error) { + r, err := http.NewRequestWithContext(ctx, method, target, bytes.NewReader(body)) + if err != nil { + return nil, err + } + r.Header.Set("Authorization", "Bearer "+p.credential) + client := &http.Client{Transport: &http.Transport{DisableKeepAlives: true}, Timeout: 30 * time.Second} + response, err := client.Do(r) + if err != nil { + return nil, err + } + defer response.Body.Close() + data, err := io.ReadAll(response.Body) + return &apisource.Result{Body: data, StatusCode: response.StatusCode}, err +} diff --git a/module/services/accounts/code/pkg/adapters/source_operation_verify_test.go b/module/services/accounts/code/pkg/adapters/source_operation_verify_test.go new file mode 100644 index 000000000..8813307e9 --- /dev/null +++ b/module/services/accounts/code/pkg/adapters/source_operation_verify_test.go @@ -0,0 +1,287 @@ +package adapters + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "os" + "strings" + "testing" + "time" + + "accounts/pkg/auth" + "accounts/pkg/business" + "accounts/pkg/datasource/connector/connectortest" + "accounts/pkg/datasource/operations" + gen "accounts/pkg/gen/saas/accounts/v1" + "accounts/pkg/gen/saas/accounts/v1/accountsv1connect" + policyv1 "accounts/pkg/gen/saas/policy/v1" + + "connectrpc.com/connect" + basev0 "github.com/codefly-dev/core/generated/go/codefly/base/v0" + "github.com/codefly-dev/sdk-go/receipts" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/stretchr/testify/require" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/proto" +) + +func sourceVerificationFixture(t *testing.T) (*datasourceConnectHandler, context.Context, *gen.InvokeSourceOperationRequest, *sourceWireStore) { + t.Helper() + org, actor, source := "11111111-1111-4111-8111-111111111111", "22222222-2222-4222-8222-222222222222", "33333333-3333-4333-8333-333333333333" + declaration, err := operations.Admit(connectortest.OperationDeclaration()) + require.NoError(t, err) + request := &gen.InvokeSourceOperationRequest{OrgId: org, SourceId: source, Operation: declaration.Name, InputJson: `{"id":"one"}`, EffectId: "effect-one", ExpectedDeclarationDigest: proto.String(declaration.Digest)} + digest, err := receipts.RequestDigest(request) + require.NoError(t, err) + store := &sourceWireStore{allowed: true, declaration: declaration, source: &business.DatasourceSource{ID: source, OrgID: org, Provider: business.DatasourceProviderAPI, API: &business.APIDatasourceConfig{}}, attempt: &business.SourceOperationAttempt{OrgID: org, ActorID: actor, SourceID: source, Operation: declaration.Name, DeclarationDigest: declaration.Digest, EffectID: request.EffectId, RequestDigest: digest}} + svc, err := business.NewService(store) + require.NoError(t, err) + previous, cache := service, orgMembershipCache + service, orgMembershipCache = svc, nil + t.Cleanup(func() { service, orgMembershipCache = previous, cache }) + receiptStore := receipts.NewMemoryStore() + require.NoError(t, svc.ConfigureSourceOperationReceipts(receiptStore)) + svc.SetAuditEmitter(&sourceWireAudit{}) + ctx := stampVerifiedIdentity(t.Context(), actor, org, auth.Assurance{}) + out, err := sourceOperationResponse(&business.SourceOperationResult{Output: []byte(`{"value":"retained"}`), EffectID: request.EffectId, CommittedAt: time.Now(), ProviderStatus: 200}) + require.NoError(t, err) + effectCtx := receipts.WithEffect(ctx, receipts.Effect{ID: request.EffectId, Tenant: org, Method: business.SourceOperationMethod, RequestDigest: digest}) + require.NoError(t, receipts.Record(effectCtx, receiptStore, sourceWireTx{}, out)) + return &datasourceConnectHandler{svc: svc}, ctx, request, store +} + +func TestSourceOperationVerifyExactRequest(t *testing.T) { + h, ctx, original, store := sourceVerificationFixture(t) + for _, tc := range []struct { + name string + change func(*gen.InvokeSourceOperationRequest) + code connect.Code + }{ + {"input", func(r *gen.InvokeSourceOperationRequest) { r.InputJson = `{"id":"two"}` }, connect.CodeFailedPrecondition}, + {"exact text", func(r *gen.InvokeSourceOperationRequest) { r.InputJson = `{ "id":"one"}` }, connect.CodeFailedPrecondition}, + {"source", func(r *gen.InvokeSourceOperationRequest) { r.SourceId = "44444444-4444-4444-8444-444444444444" }, connect.CodeFailedPrecondition}, + {"organization", func(r *gen.InvokeSourceOperationRequest) { r.OrgId = "44444444-4444-4444-8444-444444444444" }, connect.CodeFailedPrecondition}, + {"operation", func(r *gen.InvokeSourceOperationRequest) { r.Operation = "another_operation" }, connect.CodeFailedPrecondition}, + {"effect", func(r *gen.InvokeSourceOperationRequest) { r.EffectId = "another-effect" }, connect.CodeNotFound}, + {"declaration", func(r *gen.InvokeSourceOperationRequest) { + r.ExpectedDeclarationDigest = proto.String("sha256:" + strings.Repeat("0", 64)) + }, connect.CodeFailedPrecondition}, + {"omitted declaration", func(r *gen.InvokeSourceOperationRequest) { r.ExpectedDeclarationDigest = nil }, connect.CodeInvalidArgument}, + {"empty declaration", func(r *gen.InvokeSourceOperationRequest) { r.ExpectedDeclarationDigest = proto.String("") }, connect.CodeInvalidArgument}, + } { + t.Run(tc.name, func(t *testing.T) { + request := proto.CloneOf(original) + tc.change(request) + response, err := h.VerifySourceOperationReceipt(ctx, connect.NewRequest(request)) + require.Equal(t, tc.code, connect.CodeOf(err)) + require.Nil(t, response) + require.NotContains(t, err.Error(), "retained") + }) + } + for _, transport := range []connect.ClientOption{connect.WithProtoJSON(), connect.WithGRPC(), connect.WithGRPCWeb()} { + stamp := connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc { + return func(_ context.Context, r connect.AnyRequest) (connect.AnyResponse, error) { return next(ctx, r) } + }) + _, handler := accountsv1connect.NewDatasourceServiceHandler(h, connect.WithInterceptors(stamp)) + server := httptest.NewServer(handler) + client := accountsv1connect.NewDatasourceServiceClient(server.Client(), server.URL, transport) + for range 2 { + response, err := client.VerifySourceOperationReceipt(t.Context(), connect.NewRequest(original)) + require.NoError(t, err) + require.Equal(t, "committed", response.Msg.GetReceipt().GetStatus()) + require.JSONEq(t, `{"value":"retained"}`, response.Msg.OutputJson) + } + server.Close() + } + // An older generated server must report unsupported, never ordinary success. + _, oldHandler := accountsv1connect.NewDatasourceServiceHandler(accountsv1connect.UnimplementedDatasourceServiceHandler{}) + old := httptest.NewServer(oldHandler) + defer old.Close() + _, err := accountsv1connect.NewDatasourceServiceClient(old.Client(), old.URL).VerifySourceOperationReceipt(ctx, connect.NewRequest(original)) + require.Equal(t, connect.CodeUnimplemented, connect.CodeOf(err)) + // A legacy marker cannot be promoted by supplying its admitted digest later. + legacy := proto.CloneOf(original) + legacy.ExpectedDeclarationDigest = nil + store.attempt.RequestDigest, err = receipts.RequestDigest(legacy) + require.NoError(t, err) + _, err = h.VerifySourceOperationReceipt(ctx, connect.NewRequest(original)) + require.Equal(t, connect.CodeFailedPrecondition, connect.CodeOf(err)) + _, err = h.LookupInvokeSourceOperation(ctx, connect.NewRequest(&gen.LookupInvokeSourceOperationRequest{EffectId: original.EffectId})) + require.NoError(t, err) +} + +func TestSourceOperationVerifyCurrentAuthorityAndRetention(t *testing.T) { + h, ctx, original, store := sourceVerificationFixture(t) + // Read-only source authority suffices; the supplied source never grants it. + read := context.WithValue(ctx, sourceOperationContextKey{}, &basev0.WorkContextV1{TenantId: original.OrgId, AuthorityScopes: []*basev0.WorkScopeV1{{ResourceKind: "datasource.sources", ResourceIds: []string{original.SourceId}, Actions: []string{"read"}}}}) + _, err := h.VerifySourceOperationReceipt(read, connect.NewRequest(original)) + require.NoError(t, err) + for _, removed := range []bool{false, true} { + if removed { + store.declaration = operations.Declaration{} + } else { + store.declaration.Digest = "replacement" + } + out, err := h.VerifySourceOperationReceipt(read, connect.NewRequest(original)) + require.NoError(t, err) + require.Equal(t, "committed", out.Msg.Receipt.Status) + } + store.allowed = false + _, err = h.VerifySourceOperationReceipt(read, connect.NewRequest(original)) + require.Equal(t, connect.CodePermissionDenied, connect.CodeOf(err)) + store.allowed = true + store.source.PersonalOwnerUserID = "another-actor" + _, err = h.VerifySourceOperationReceipt(read, connect.NewRequest(original)) + require.Equal(t, connect.CodePermissionDenied, connect.CodeOf(err)) + store.source.PersonalOwnerUserID = "" + other := stampVerifiedIdentity(t.Context(), "44444444-4444-4444-8444-444444444444", original.OrgId, auth.Assurance{}) + _, err = h.VerifySourceOperationReceipt(other, connect.NewRequest(original)) + require.Equal(t, connect.CodeFailedPrecondition, connect.CodeOf(err)) + otherTenant := stampVerifiedIdentity(t.Context(), store.attempt.ActorID, "55555555-5555-4555-8555-555555555555", auth.Assurance{}) + response, err := h.VerifySourceOperationReceipt(otherTenant, connect.NewRequest(original)) + require.Error(t, err) + require.Nil(t, response) + store.source = nil + _, err = h.VerifySourceOperationReceipt(read, connect.NewRequest(original)) + require.Equal(t, connect.CodeFailedPrecondition, connect.CodeOf(err)) + store.source = &business.DatasourceSource{ID: original.SourceId, OrgID: original.OrgId} + // Output expiry leaves the permanent marker and never calls a provider. + require.NoError(t, h.svc.ConfigureSourceOperationReceipts(receipts.NewMemoryStore())) + unknown, err := h.VerifySourceOperationReceipt(read, connect.NewRequest(original)) + require.NoError(t, err) + require.Equal(t, "unknown", unknown.Msg.Receipt.Status) + require.Equal(t, "{}", unknown.Msg.OutputJson) + store.attempt = nil + _, err = h.VerifySourceOperationReceipt(read, connect.NewRequest(original)) + require.Equal(t, connect.CodeNotFound, connect.CodeOf(err)) +} + +func TestSourceOperationVerifyNormalizationAndBounds(t *testing.T) { + h, ctx, original, store := sourceVerificationFixture(t) + request := connect.NewRequest(proto.CloneOf(original)) + request.Msg.EffectId = "" + request.Header().Set(receipts.EffectIDHeaderName, original.EffectId) + request.Header().Set(receipts.IdempotencyKeyHeaderName, original.EffectId) + _, err := h.VerifySourceOperationReceipt(ctx, request) + require.NoError(t, err) + request.Msg.EffectId = "different" + _, err = h.VerifySourceOperationReceipt(ctx, request) + require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err)) + // Account for the complete normalized envelope, including declaration and + // escaped JSON. At the exact bound the request remains readable. + request = connect.NewRequest(proto.CloneOf(original)) + wire, err := sourceWireJSON.Marshal(request.Msg) + require.NoError(t, err) + request.Msg.InputJson += strings.Repeat(" ", sourceInputEnvelopeBytes-len(wire)) + wire, err = sourceWireJSON.Marshal(request.Msg) + require.NoError(t, err) + require.Len(t, wire, sourceInputEnvelopeBytes) + store.attempt.RequestDigest, err = receipts.RequestDigest(request.Msg) + require.NoError(t, err) + _, err = h.VerifySourceOperationReceipt(ctx, request) + require.NoError(t, err) + request.Msg.InputJson += " " + _, err = h.VerifySourceOperationReceipt(ctx, request) + require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err)) +} + +func TestSourceOperationVerifyPOSTGateway(t *testing.T) { + h, ctx, original, store := sourceVerificationFixture(t) + stamp := connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc { + return func(_ context.Context, r connect.AnyRequest) (connect.AnyResponse, error) { return next(ctx, r) } + }) + _, handler := accountsv1connect.NewDatasourceServiceHandler(h, connect.WithInterceptors(stamp)) + endpoint := httptest.NewServer(h2c.NewHandler(handler, &http2.Server{})) + defer endpoint.Close() + conn, err := grpc.NewClient(endpoint.Listener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + defer conn.Close() + mux := runtime.NewServeMux() + require.NoError(t, gen.RegisterDatasourceServiceHandlerClient(t.Context(), mux, gen.NewDatasourceServiceClient(conn))) + wire, err := sourceWireJSON.Marshal(original) + require.NoError(t, err) + post := httptest.NewRequest(http.MethodPost, "/v1/datasource-operation-receipts/verify", strings.NewReader(string(wire))) + post.Header.Set("Content-Type", "application/json") + response := httptest.NewRecorder() + mux.ServeHTTP(response, post) + require.Equal(t, http.StatusOK, response.Code, response.Body.String()) + require.Contains(t, response.Body.String(), "retained") + bounded := proto.CloneOf(original) + bounded.InputJson += strings.Repeat(" ", sourceInputEnvelopeBytes-len(wire)) + store.attempt.RequestDigest, err = receipts.RequestDigest(bounded) + require.NoError(t, err) + for _, excess := range []bool{false, true} { + if excess { + bounded.InputJson += " " + } + wire, err := sourceWireJSON.Marshal(bounded) + require.NoError(t, err) + post := httptest.NewRequest(http.MethodPost, "/v1/datasource-operation-receipts/verify", strings.NewReader(string(wire))) + post.Header.Set("Content-Type", "application/json") + response := httptest.NewRecorder() + mux.ServeHTTP(response, post) + if excess { + require.Equal(t, http.StatusBadRequest, response.Code) + } else { + require.Equal(t, http.StatusOK, response.Code, response.Body.String()) + } + } + // Body:* admits no query-bound expectation, even beside a valid effect. + query := httptest.NewRequest(http.MethodPost, "/v1/datasource-operation-receipts/verify?input_json=private&effect_id=effect-one", strings.NewReader("{}")) + query.Header.Set("Content-Type", "application/json") + response = httptest.NewRecorder() + previousEmitter := emitHTTPFailureDiagnostic + var diagnostic httpFailureDiagnostic + emitHTTPFailureDiagnostic = func(d httpFailureDiagnostic) { diagnostic = d } + t.Cleanup(func() { emitHTTPFailureDiagnostic = previousEmitter }) + logRequestOutcome(mux).ServeHTTP(response, query) + require.Equal(t, http.StatusBadRequest, response.Code) + require.NotContains(t, response.Body.String(), "private") + require.NotContains(t, response.Body.String(), "retained") + logged, err := json.Marshal(diagnostic) + require.NoError(t, err) + require.NotContains(t, string(logged), "private") + require.NotContains(t, string(logged), "input_json") + // Connect does not expose this secret-bearing read through its GET protocol. + response = httptest.NewRecorder() + handler.ServeHTTP(response, httptest.NewRequest(http.MethodGet, accountsv1connect.DatasourceServiceVerifySourceOperationReceiptProcedure, nil)) + require.Equal(t, http.StatusMethodNotAllowed, response.Code) + policy, ok := business.LookupRPCPolicy(accountsv1connect.DatasourceServiceVerifySourceOperationReceiptProcedure) + require.True(t, ok) + require.Equal(t, policyv1.Sensitivity_SENSITIVITY_SECRET, policy.MethodPolicy.GetRequestSensitivity()) + require.Equal(t, policyv1.Sensitivity_SENSITIVITY_SECRET, policy.MethodPolicy.GetResponseSensitivity()) + openapi, err := os.ReadFile("../../../generated/openapi-raw/api.swagger.json") + require.NoError(t, err) + var spec struct { + Paths map[string]map[string]json.RawMessage `json:"paths"` + } + require.NoError(t, json.Unmarshal(openapi, &spec)) + path := spec.Paths["/v1/datasource-operation-receipts/verify"] + require.Len(t, path, 1) + var operation struct { + Parameters []struct { + In string `json:"in"` + } `json:"parameters"` + } + require.NoError(t, json.Unmarshal(path["post"], &operation)) + require.Len(t, operation.Parameters, 1) + require.Equal(t, "body", operation.Parameters[0].In) +} + +func TestSourceOperationVerifyStoredResponseBound(t *testing.T) { + h, ctx, original, store := sourceVerificationFixture(t) + receiptStore := receipts.NewMemoryStore() + require.NoError(t, h.svc.ConfigureSourceOperationReceipts(receiptStore)) + effectCtx := receipts.WithEffect(ctx, receipts.Effect{ID: original.EffectId, Tenant: original.OrgId, Method: business.SourceOperationMethod, RequestDigest: store.attempt.RequestDigest}) + out := &gen.InvokeSourceOperationResponse{OutputJson: strings.Repeat("x", sourceOutputEnvelopeBytes)} + require.NoError(t, receipts.Record(effectCtx, receiptStore, sourceWireTx{}, out)) + response, err := h.VerifySourceOperationReceipt(ctx, connect.NewRequest(original)) + require.Nil(t, response) + require.Equal(t, connect.CodeInternal, connect.CodeOf(err)) + require.EqualError(t, err, "internal: source receipt invalid") +} diff --git a/module/services/accounts/code/pkg/business/introspection.go b/module/services/accounts/code/pkg/business/introspection.go index 8779160eb..b10e8d9b8 100644 --- a/module/services/accounts/code/pkg/business/introspection.go +++ b/module/services/accounts/code/pkg/business/introspection.go @@ -81,6 +81,7 @@ var rpcDescriptions = withWorkContextConsumerDescriptions(map[string]string{ "DatasourceService/LookupReconcileSource": "Read back the receipt of one reconcile pass.", "DatasourceService/InvokeSourceOperation": "Call a declared source operation under current authority and an effect receipt.", "DatasourceService/LookupInvokeSourceOperation": "Read the current authorized outcome of a source effect without redispatching it.", + "DatasourceService/VerifySourceOperationReceipt": "Read a source receipt only when the original invocation and admitted declaration match.", "DatasourceService/DeclareSourceOperations": "Atomically replace an API source's declared operations as an organization administrator.", "DatasourceService/ListSourceOperations": "Read an API source's declared operations under current source authority.", "ModuleCapabilitiesService/GetCurrentInstallation": "Read current active installation identity as a verified organization member through an authenticated module.", diff --git a/module/services/accounts/code/pkg/business/owned_resource_resolver.go b/module/services/accounts/code/pkg/business/owned_resource_resolver.go index 1fe74523f..4ea98cc39 100644 --- a/module/services/accounts/code/pkg/business/owned_resource_resolver.go +++ b/module/services/accounts/code/pkg/business/owned_resource_resolver.go @@ -37,6 +37,7 @@ var ownedResourceResolvers = map[string]ownedResourceResolver{ SourceReceiptRetentionMethod: resolveSourceOperationOrg, "/saas.accounts.v1.DatasourceService/LookupPruneSourceOperationReceipts": resolveSourceEffectOrg, "/saas.accounts.v1.DatasourceService/LookupInvokeSourceOperation": resolveSourceEffectOrg, + "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt": resolveSourceEffectOrg, "/saas.accounts.v1.DatasourceService/LookupReconcileSource": resolveSourceEffectOrg, "/saas.accounts.v1.DatasourceService/ReconcileSource": resolveSourceOperationOrg, "/saas.accounts.v1.DashboardService/DeleteDashboard": resolveDashboardOrg, diff --git a/module/services/accounts/code/pkg/business/source_operation_integration.go b/module/services/accounts/code/pkg/business/source_operation_integration.go new file mode 100644 index 000000000..4fd5b6175 --- /dev/null +++ b/module/services/accounts/code/pkg/business/source_operation_integration.go @@ -0,0 +1,12 @@ +//go:build integration + +package business + +import "accounts/pkg/datasource/apisource" + +// SetSourceOperationIntegrationClient exposes the existing provider transport +// seam to cross-package integration tests. Identity, authority, admission, +// cipher and persistence remain real. Normal service builds exclude this file. +func (s *Service) SetSourceOperationIntegrationClient(fn func(apisource.Config, string) APIOperationClient) { + s.newAPIOperationClient = fn +} diff --git a/module/services/accounts/code/pkg/cataloggen/api_contract_surfaces_test.go b/module/services/accounts/code/pkg/cataloggen/api_contract_surfaces_test.go index d5ae56b81..1f780e4e7 100644 --- a/module/services/accounts/code/pkg/cataloggen/api_contract_surfaces_test.go +++ b/module/services/accounts/code/pkg/cataloggen/api_contract_surfaces_test.go @@ -48,7 +48,7 @@ func TestAPIContractSurfacesAreDeterministicCurrentAndListenerScoped(t *testing. } } require.Equal(t, business.ModuleAuthorityProcedures(), authority) - for _, method := range []string{"InvokeSourceOperation", "LookupInvokeSourceOperation", "PruneSourceOperationReceipts", "LookupPruneSourceOperationReceipts"} { + for _, method := range []string{"InvokeSourceOperation", "LookupInvokeSourceOperation", "VerifySourceOperationReceipt", "PruneSourceOperationReceipts", "LookupPruneSourceOperationReceipts"} { procedure := "/saas.accounts.v1.DatasourceService/" + method require.NotContains(t, authority, procedure) require.Contains(t, connectProcedures, procedure) diff --git a/module/services/accounts/code/pkg/gen/saas/accounts/v1/accountsv1connect/datasource.connect.go b/module/services/accounts/code/pkg/gen/saas/accounts/v1/accountsv1connect/datasource.connect.go index 773f6797d..efb4fe2e1 100644 --- a/module/services/accounts/code/pkg/gen/saas/accounts/v1/accountsv1connect/datasource.connect.go +++ b/module/services/accounts/code/pkg/gen/saas/accounts/v1/accountsv1connect/datasource.connect.go @@ -46,6 +46,9 @@ const ( // DatasourceServiceLookupInvokeSourceOperationProcedure is the fully-qualified name of the // DatasourceService's LookupInvokeSourceOperation RPC. DatasourceServiceLookupInvokeSourceOperationProcedure = "/saas.accounts.v1.DatasourceService/LookupInvokeSourceOperation" + // DatasourceServiceVerifySourceOperationReceiptProcedure is the fully-qualified name of the + // DatasourceService's VerifySourceOperationReceipt RPC. + DatasourceServiceVerifySourceOperationReceiptProcedure = "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt" // DatasourceServiceListSourceOperationsProcedure is the fully-qualified name of the // DatasourceService's ListSourceOperations RPC. DatasourceServiceListSourceOperationsProcedure = "/saas.accounts.v1.DatasourceService/ListSourceOperations" @@ -162,6 +165,13 @@ type DatasourceServiceClient interface { // Once an attempt exists, retained receipt evidence survives declaration // removal or replacement. Current source read authority still applies. LookupInvokeSourceOperation(context.Context, *connect.Request[v1.LookupInvokeSourceOperationRequest]) (*connect.Response[v1.InvokeSourceOperationResponse], error) + // VerifySourceOperationReceipt conditionally reads retained output using the + // exact original Invoke request, including a nonempty declaration precondition. + // Committed means the normalized request and admitted declaration match the + // stored attempt. Unknown remains unresolved; this method never redispatches. + // Current actor, tenant and stored-source read authority apply before comparison. + // This is independent of the paired Runnable Lookup contract above. + VerifySourceOperationReceipt(context.Context, *connect.Request[v1.InvokeSourceOperationRequest]) (*connect.Response[v1.InvokeSourceOperationResponse], error) // ListSourceOperations reads the currently admitted declarations under source authority. ListSourceOperations(context.Context, *connect.Request[v1.ListSourceOperationsRequest]) (*connect.Response[v1.ListSourceOperationsResponse], error) // DeclareSourceOperations atomically replaces the source operation set, as an administrator. @@ -338,6 +348,12 @@ func NewDatasourceServiceClient(httpClient connect.HTTPClient, baseURL string, o connect.WithSchema(datasourceServiceMethods.ByName("LookupInvokeSourceOperation")), connect.WithClientOptions(opts...), ), + verifySourceOperationReceipt: connect.NewClient[v1.InvokeSourceOperationRequest, v1.InvokeSourceOperationResponse]( + httpClient, + baseURL+DatasourceServiceVerifySourceOperationReceiptProcedure, + connect.WithSchema(datasourceServiceMethods.ByName("VerifySourceOperationReceipt")), + connect.WithClientOptions(opts...), + ), listSourceOperations: connect.NewClient[v1.ListSourceOperationsRequest, v1.ListSourceOperationsResponse]( httpClient, baseURL+DatasourceServiceListSourceOperationsProcedure, @@ -527,6 +543,7 @@ type datasourceServiceClient struct { lookupPruneSourceOperationReceipts *connect.Client[v1.LookupPruneSourceOperationReceiptsRequest, v1.PruneSourceOperationReceiptsResponse] invokeSourceOperation *connect.Client[v1.InvokeSourceOperationRequest, v1.InvokeSourceOperationResponse] lookupInvokeSourceOperation *connect.Client[v1.LookupInvokeSourceOperationRequest, v1.InvokeSourceOperationResponse] + verifySourceOperationReceipt *connect.Client[v1.InvokeSourceOperationRequest, v1.InvokeSourceOperationResponse] listSourceOperations *connect.Client[v1.ListSourceOperationsRequest, v1.ListSourceOperationsResponse] declareSourceOperations *connect.Client[v1.DeclareSourceOperationsRequest, v1.DeclareSourceOperationsResponse] addGitHubSource *connect.Client[v1.AddGitHubSourceRequest, v1.AddGitHubSourceResponse] @@ -581,6 +598,12 @@ func (c *datasourceServiceClient) LookupInvokeSourceOperation(ctx context.Contex return c.lookupInvokeSourceOperation.CallUnary(ctx, req) } +// VerifySourceOperationReceipt calls +// saas.accounts.v1.DatasourceService.VerifySourceOperationReceipt. +func (c *datasourceServiceClient) VerifySourceOperationReceipt(ctx context.Context, req *connect.Request[v1.InvokeSourceOperationRequest]) (*connect.Response[v1.InvokeSourceOperationResponse], error) { + return c.verifySourceOperationReceipt.CallUnary(ctx, req) +} + // ListSourceOperations calls saas.accounts.v1.DatasourceService.ListSourceOperations. func (c *datasourceServiceClient) ListSourceOperations(ctx context.Context, req *connect.Request[v1.ListSourceOperationsRequest]) (*connect.Response[v1.ListSourceOperationsResponse], error) { return c.listSourceOperations.CallUnary(ctx, req) @@ -757,6 +780,13 @@ type DatasourceServiceHandler interface { // Once an attempt exists, retained receipt evidence survives declaration // removal or replacement. Current source read authority still applies. LookupInvokeSourceOperation(context.Context, *connect.Request[v1.LookupInvokeSourceOperationRequest]) (*connect.Response[v1.InvokeSourceOperationResponse], error) + // VerifySourceOperationReceipt conditionally reads retained output using the + // exact original Invoke request, including a nonempty declaration precondition. + // Committed means the normalized request and admitted declaration match the + // stored attempt. Unknown remains unresolved; this method never redispatches. + // Current actor, tenant and stored-source read authority apply before comparison. + // This is independent of the paired Runnable Lookup contract above. + VerifySourceOperationReceipt(context.Context, *connect.Request[v1.InvokeSourceOperationRequest]) (*connect.Response[v1.InvokeSourceOperationResponse], error) // ListSourceOperations reads the currently admitted declarations under source authority. ListSourceOperations(context.Context, *connect.Request[v1.ListSourceOperationsRequest]) (*connect.Response[v1.ListSourceOperationsResponse], error) // DeclareSourceOperations atomically replaces the source operation set, as an administrator. @@ -929,6 +959,12 @@ func NewDatasourceServiceHandler(svc DatasourceServiceHandler, opts ...connect.H connect.WithSchema(datasourceServiceMethods.ByName("LookupInvokeSourceOperation")), connect.WithHandlerOptions(opts...), ) + datasourceServiceVerifySourceOperationReceiptHandler := connect.NewUnaryHandler( + DatasourceServiceVerifySourceOperationReceiptProcedure, + svc.VerifySourceOperationReceipt, + connect.WithSchema(datasourceServiceMethods.ByName("VerifySourceOperationReceipt")), + connect.WithHandlerOptions(opts...), + ) datasourceServiceListSourceOperationsHandler := connect.NewUnaryHandler( DatasourceServiceListSourceOperationsProcedure, svc.ListSourceOperations, @@ -1119,6 +1155,8 @@ func NewDatasourceServiceHandler(svc DatasourceServiceHandler, opts ...connect.H datasourceServiceInvokeSourceOperationHandler.ServeHTTP(w, r) case DatasourceServiceLookupInvokeSourceOperationProcedure: datasourceServiceLookupInvokeSourceOperationHandler.ServeHTTP(w, r) + case DatasourceServiceVerifySourceOperationReceiptProcedure: + datasourceServiceVerifySourceOperationReceiptHandler.ServeHTTP(w, r) case DatasourceServiceListSourceOperationsProcedure: datasourceServiceListSourceOperationsHandler.ServeHTTP(w, r) case DatasourceServiceDeclareSourceOperationsProcedure: @@ -1204,6 +1242,10 @@ func (UnimplementedDatasourceServiceHandler) LookupInvokeSourceOperation(context return nil, connect.NewError(connect.CodeUnimplemented, errors.New("saas.accounts.v1.DatasourceService.LookupInvokeSourceOperation is not implemented")) } +func (UnimplementedDatasourceServiceHandler) VerifySourceOperationReceipt(context.Context, *connect.Request[v1.InvokeSourceOperationRequest]) (*connect.Response[v1.InvokeSourceOperationResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("saas.accounts.v1.DatasourceService.VerifySourceOperationReceipt is not implemented")) +} + func (UnimplementedDatasourceServiceHandler) ListSourceOperations(context.Context, *connect.Request[v1.ListSourceOperationsRequest]) (*connect.Response[v1.ListSourceOperationsResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("saas.accounts.v1.DatasourceService.ListSourceOperations is not implemented")) } diff --git a/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource.pb.go b/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource.pb.go index 2f590aefa..835487b44 100644 --- a/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource.pb.go +++ b/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource.pb.go @@ -8121,7 +8121,7 @@ const file_saas_accounts_v1_datasource_proto_rawDesc = "" + "+SOURCE_DELEGATION_REVOCATION_MEMBER_REMOVED\x10\x04\x120\n" + ",SOURCE_DELEGATION_REVOCATION_PERMISSION_LOST\x10\x05\x12.\n" + "*SOURCE_DELEGATION_REVOCATION_USER_INACTIVE\x10\x06\x120\n" + - ",SOURCE_DELEGATION_REVOCATION_BINDING_CHANGED\x10\a2\xb19\n" + + ",SOURCE_DELEGATION_REVOCATION_BINDING_CHANGED\x10\a2\xb3;\n" + "\x11DatasourceService\x12\xb9\x03\n" + "\x1cPruneSourceOperationReceipts\x125.saas.accounts.v1.PruneSourceOperationReceiptsRequest\x1a6.saas.accounts.v1.PruneSourceOperationReceiptsResponse\"\xa9\x02\xc2\xf3\x18l\b\x02\x10\x03\x1a\x11datasource:invoke\"\x11datasource:invoke*\x0f\n" + "\tsource_id\x10\x04\x18\x030\x01:#\n" + @@ -8136,7 +8136,9 @@ const file_saas_accounts_v1_datasource_proto_rawDesc = "" + "\x02\b<\x12\x03\b\xd8\x04\x18\x05\"\x02\b\x02*\vUNAVAILABLE*\x12RESOURCE_EXHAUSTED*\aABORTED2\x0fsaas-datasourceJ?/saas.accounts.v1.DatasourceService/LookupInvokeSourceOperationP\x80\x80\x04X\x80\x80@`\x01r\x18\n" + "\x06source\x12\x06invoke\x12\x04read\x18\x01\x82\xd3\xe4\x93\x02U:\x01*\"P/v1/organizations/{org_id}/datasources/{source_id}/operations/{operation}:invoke\x12\x87\x02\n" + "\x1bLookupInvokeSourceOperation\x124.saas.accounts.v1.LookupInvokeSourceOperationRequest\x1a/.saas.accounts.v1.InvokeSourceOperationResponse\"\x80\x01\xc2\xf3\x18G\b\x02\x10\x03\x1a\x0fdatasource:read\"\x0fdatasource:read*\x0f\n" + - "\teffect_id\x10\x04\x18\x030\x01:\x02\x10\x01@\x01H\x03P\x03X\x04`\x01\x82\xd3\xe4\x93\x02/\x12-/v1/datasource-operation-receipts/{effect_id}\x12\x85\x02\n" + + "\teffect_id\x10\x04\x18\x030\x01:\x02\x10\x01@\x01H\x03P\x03X\x04`\x01\x82\xd3\xe4\x93\x02/\x12-/v1/datasource-operation-receipts/{effect_id}\x12\xff\x01\n" + + "\x1cVerifySourceOperationReceipt\x12..saas.accounts.v1.InvokeSourceOperationRequest\x1a/.saas.accounts.v1.InvokeSourceOperationResponse\"~\xc2\xf3\x18G\b\x02\x10\x03\x1a\x0fdatasource:read\"\x0fdatasource:read*\x0f\n" + + "\teffect_id\x10\x04\x18\x030\x01:\x02\x10\x01@\x01H\x03P\x04X\x04`\x01\x82\xd3\xe4\x93\x02-:\x01*\"(/v1/datasource-operation-receipts/verify\x12\x85\x02\n" + "\x14ListSourceOperations\x12-.saas.accounts.v1.ListSourceOperationsRequest\x1a..saas.accounts.v1.ListSourceOperationsResponse\"\x8d\x01\xc2\xf3\x18D\b\x02\x10\x03\x1a\x0fdatasource:read\"\x0fdatasource:read*\f\n" + "\x06org_id\x10\x02\x18\x010\x01:\x02\x10\x01@\x01H\x03P\x03X\x03`\x01\x82\xd3\xe4\x93\x02?\x12=/v1/organizations/{org_id}/datasources/{source_id}/operations\x12\x93\x02\n" + "\x17DeclareSourceOperations\x120.saas.accounts.v1.DeclareSourceOperationsRequest\x1a1.saas.accounts.v1.DeclareSourceOperationsResponse\"\x92\x01\xc2\xf3\x18F\b\x02\x10\x04*\f\n" + @@ -8446,72 +8448,74 @@ var file_saas_accounts_v1_datasource_proto_depIdxs = []int32{ 105, // 93: saas.accounts.v1.DatasourceService.LookupPruneSourceOperationReceipts:input_type -> saas.accounts.v1.LookupPruneSourceOperationReceiptsRequest 99, // 94: saas.accounts.v1.DatasourceService.InvokeSourceOperation:input_type -> saas.accounts.v1.InvokeSourceOperationRequest 102, // 95: saas.accounts.v1.DatasourceService.LookupInvokeSourceOperation:input_type -> saas.accounts.v1.LookupInvokeSourceOperationRequest - 97, // 96: saas.accounts.v1.DatasourceService.ListSourceOperations:input_type -> saas.accounts.v1.ListSourceOperationsRequest - 95, // 97: saas.accounts.v1.DatasourceService.DeclareSourceOperations:input_type -> saas.accounts.v1.DeclareSourceOperationsRequest - 20, // 98: saas.accounts.v1.DatasourceService.AddGitHubSource:input_type -> saas.accounts.v1.AddGitHubSourceRequest - 22, // 99: saas.accounts.v1.DatasourceService.AddSource:input_type -> saas.accounts.v1.AddSourceRequest - 24, // 100: saas.accounts.v1.DatasourceService.UpdateSource:input_type -> saas.accounts.v1.UpdateSourceRequest - 30, // 101: saas.accounts.v1.DatasourceService.GetDatasourceCatalog:input_type -> saas.accounts.v1.GetDatasourceCatalogRequest - 32, // 102: saas.accounts.v1.DatasourceService.ListSources:input_type -> saas.accounts.v1.ListSourcesRequest - 34, // 103: saas.accounts.v1.DatasourceService.GetSource:input_type -> saas.accounts.v1.GetSourceRequest - 36, // 104: saas.accounts.v1.DatasourceService.SyncSource:input_type -> saas.accounts.v1.SyncSourceRequest - 38, // 105: saas.accounts.v1.DatasourceService.GetSourceSync:input_type -> saas.accounts.v1.GetSourceSyncRequest - 44, // 106: saas.accounts.v1.DatasourceService.DeleteSource:input_type -> saas.accounts.v1.DeleteSourceRequest - 47, // 107: saas.accounts.v1.DatasourceService.BeginGitHubAppSetup:input_type -> saas.accounts.v1.BeginGitHubAppSetupRequest - 49, // 108: saas.accounts.v1.DatasourceService.CompleteGitHubAppSetup:input_type -> saas.accounts.v1.CompleteGitHubAppSetupRequest - 51, // 109: saas.accounts.v1.DatasourceService.MigrateGitHubSourceToApp:input_type -> saas.accounts.v1.MigrateGitHubSourceToAppRequest - 57, // 110: saas.accounts.v1.DatasourceService.BeginDatasourceAccountLink:input_type -> saas.accounts.v1.BeginDatasourceAccountLinkRequest - 59, // 111: saas.accounts.v1.DatasourceService.CompleteDatasourceAccountLink:input_type -> saas.accounts.v1.CompleteDatasourceAccountLinkRequest - 61, // 112: saas.accounts.v1.DatasourceService.ListMyDatasourceAccountLinks:input_type -> saas.accounts.v1.ListMyDatasourceAccountLinksRequest - 63, // 113: saas.accounts.v1.DatasourceService.DeleteDatasourceAccountLink:input_type -> saas.accounts.v1.DeleteDatasourceAccountLinkRequest - 65, // 114: saas.accounts.v1.DatasourceService.GetDatasourceDirectory:input_type -> saas.accounts.v1.GetDatasourceDirectoryRequest - 67, // 115: saas.accounts.v1.DatasourceService.BindDatasourceGroup:input_type -> saas.accounts.v1.BindDatasourceGroupRequest - 69, // 116: saas.accounts.v1.DatasourceService.UnbindDatasourceGroup:input_type -> saas.accounts.v1.UnbindDatasourceGroupRequest - 71, // 117: saas.accounts.v1.DatasourceService.ClaimDatasourceDomain:input_type -> saas.accounts.v1.ClaimDatasourceDomainRequest - 73, // 118: saas.accounts.v1.DatasourceService.VerifyDatasourceDomain:input_type -> saas.accounts.v1.VerifyDatasourceDomainRequest - 75, // 119: saas.accounts.v1.DatasourceService.DeleteDatasourceDomain:input_type -> saas.accounts.v1.DeleteDatasourceDomainRequest - 78, // 120: saas.accounts.v1.DatasourceService.ListSourceDelegations:input_type -> saas.accounts.v1.ListSourceDelegationsRequest - 80, // 121: saas.accounts.v1.DatasourceService.RevokeSourceDelegation:input_type -> saas.accounts.v1.RevokeSourceDelegationRequest - 87, // 122: saas.accounts.v1.DatasourceService.DelegateSourceTriggers:input_type -> saas.accounts.v1.DelegateSourceTriggersRequest - 89, // 123: saas.accounts.v1.DatasourceService.GetSourceTriggerDeclaration:input_type -> saas.accounts.v1.GetSourceTriggerDeclarationRequest - 91, // 124: saas.accounts.v1.DatasourceService.ReconcileSource:input_type -> saas.accounts.v1.ReconcileSourceRequest - 93, // 125: saas.accounts.v1.DatasourceService.LookupReconcileSource:input_type -> saas.accounts.v1.LookupReconcileSourceRequest - 104, // 126: saas.accounts.v1.DatasourceService.PruneSourceOperationReceipts:output_type -> saas.accounts.v1.PruneSourceOperationReceiptsResponse - 104, // 127: saas.accounts.v1.DatasourceService.LookupPruneSourceOperationReceipts:output_type -> saas.accounts.v1.PruneSourceOperationReceiptsResponse - 101, // 128: saas.accounts.v1.DatasourceService.InvokeSourceOperation:output_type -> saas.accounts.v1.InvokeSourceOperationResponse - 101, // 129: saas.accounts.v1.DatasourceService.LookupInvokeSourceOperation:output_type -> saas.accounts.v1.InvokeSourceOperationResponse - 98, // 130: saas.accounts.v1.DatasourceService.ListSourceOperations:output_type -> saas.accounts.v1.ListSourceOperationsResponse - 96, // 131: saas.accounts.v1.DatasourceService.DeclareSourceOperations:output_type -> saas.accounts.v1.DeclareSourceOperationsResponse - 21, // 132: saas.accounts.v1.DatasourceService.AddGitHubSource:output_type -> saas.accounts.v1.AddGitHubSourceResponse - 23, // 133: saas.accounts.v1.DatasourceService.AddSource:output_type -> saas.accounts.v1.AddSourceResponse - 26, // 134: saas.accounts.v1.DatasourceService.UpdateSource:output_type -> saas.accounts.v1.UpdateSourceResponse - 31, // 135: saas.accounts.v1.DatasourceService.GetDatasourceCatalog:output_type -> saas.accounts.v1.GetDatasourceCatalogResponse - 33, // 136: saas.accounts.v1.DatasourceService.ListSources:output_type -> saas.accounts.v1.ListSourcesResponse - 35, // 137: saas.accounts.v1.DatasourceService.GetSource:output_type -> saas.accounts.v1.GetSourceResponse - 37, // 138: saas.accounts.v1.DatasourceService.SyncSource:output_type -> saas.accounts.v1.SyncSourceResponse - 43, // 139: saas.accounts.v1.DatasourceService.GetSourceSync:output_type -> saas.accounts.v1.GetSourceSyncResponse - 45, // 140: saas.accounts.v1.DatasourceService.DeleteSource:output_type -> saas.accounts.v1.DeleteSourceResponse - 48, // 141: saas.accounts.v1.DatasourceService.BeginGitHubAppSetup:output_type -> saas.accounts.v1.BeginGitHubAppSetupResponse - 50, // 142: saas.accounts.v1.DatasourceService.CompleteGitHubAppSetup:output_type -> saas.accounts.v1.CompleteGitHubAppSetupResponse - 52, // 143: saas.accounts.v1.DatasourceService.MigrateGitHubSourceToApp:output_type -> saas.accounts.v1.MigrateGitHubSourceToAppResponse - 58, // 144: saas.accounts.v1.DatasourceService.BeginDatasourceAccountLink:output_type -> saas.accounts.v1.BeginDatasourceAccountLinkResponse - 60, // 145: saas.accounts.v1.DatasourceService.CompleteDatasourceAccountLink:output_type -> saas.accounts.v1.CompleteDatasourceAccountLinkResponse - 62, // 146: saas.accounts.v1.DatasourceService.ListMyDatasourceAccountLinks:output_type -> saas.accounts.v1.ListMyDatasourceAccountLinksResponse - 64, // 147: saas.accounts.v1.DatasourceService.DeleteDatasourceAccountLink:output_type -> saas.accounts.v1.DeleteDatasourceAccountLinkResponse - 66, // 148: saas.accounts.v1.DatasourceService.GetDatasourceDirectory:output_type -> saas.accounts.v1.GetDatasourceDirectoryResponse - 68, // 149: saas.accounts.v1.DatasourceService.BindDatasourceGroup:output_type -> saas.accounts.v1.BindDatasourceGroupResponse - 70, // 150: saas.accounts.v1.DatasourceService.UnbindDatasourceGroup:output_type -> saas.accounts.v1.UnbindDatasourceGroupResponse - 72, // 151: saas.accounts.v1.DatasourceService.ClaimDatasourceDomain:output_type -> saas.accounts.v1.ClaimDatasourceDomainResponse - 74, // 152: saas.accounts.v1.DatasourceService.VerifyDatasourceDomain:output_type -> saas.accounts.v1.VerifyDatasourceDomainResponse - 76, // 153: saas.accounts.v1.DatasourceService.DeleteDatasourceDomain:output_type -> saas.accounts.v1.DeleteDatasourceDomainResponse - 79, // 154: saas.accounts.v1.DatasourceService.ListSourceDelegations:output_type -> saas.accounts.v1.ListSourceDelegationsResponse - 81, // 155: saas.accounts.v1.DatasourceService.RevokeSourceDelegation:output_type -> saas.accounts.v1.RevokeSourceDelegationResponse - 88, // 156: saas.accounts.v1.DatasourceService.DelegateSourceTriggers:output_type -> saas.accounts.v1.DelegateSourceTriggersResponse - 90, // 157: saas.accounts.v1.DatasourceService.GetSourceTriggerDeclaration:output_type -> saas.accounts.v1.GetSourceTriggerDeclarationResponse - 92, // 158: saas.accounts.v1.DatasourceService.ReconcileSource:output_type -> saas.accounts.v1.ReconcileSourceResponse - 92, // 159: saas.accounts.v1.DatasourceService.LookupReconcileSource:output_type -> saas.accounts.v1.ReconcileSourceResponse - 126, // [126:160] is the sub-list for method output_type - 92, // [92:126] is the sub-list for method input_type + 99, // 96: saas.accounts.v1.DatasourceService.VerifySourceOperationReceipt:input_type -> saas.accounts.v1.InvokeSourceOperationRequest + 97, // 97: saas.accounts.v1.DatasourceService.ListSourceOperations:input_type -> saas.accounts.v1.ListSourceOperationsRequest + 95, // 98: saas.accounts.v1.DatasourceService.DeclareSourceOperations:input_type -> saas.accounts.v1.DeclareSourceOperationsRequest + 20, // 99: saas.accounts.v1.DatasourceService.AddGitHubSource:input_type -> saas.accounts.v1.AddGitHubSourceRequest + 22, // 100: saas.accounts.v1.DatasourceService.AddSource:input_type -> saas.accounts.v1.AddSourceRequest + 24, // 101: saas.accounts.v1.DatasourceService.UpdateSource:input_type -> saas.accounts.v1.UpdateSourceRequest + 30, // 102: saas.accounts.v1.DatasourceService.GetDatasourceCatalog:input_type -> saas.accounts.v1.GetDatasourceCatalogRequest + 32, // 103: saas.accounts.v1.DatasourceService.ListSources:input_type -> saas.accounts.v1.ListSourcesRequest + 34, // 104: saas.accounts.v1.DatasourceService.GetSource:input_type -> saas.accounts.v1.GetSourceRequest + 36, // 105: saas.accounts.v1.DatasourceService.SyncSource:input_type -> saas.accounts.v1.SyncSourceRequest + 38, // 106: saas.accounts.v1.DatasourceService.GetSourceSync:input_type -> saas.accounts.v1.GetSourceSyncRequest + 44, // 107: saas.accounts.v1.DatasourceService.DeleteSource:input_type -> saas.accounts.v1.DeleteSourceRequest + 47, // 108: saas.accounts.v1.DatasourceService.BeginGitHubAppSetup:input_type -> saas.accounts.v1.BeginGitHubAppSetupRequest + 49, // 109: saas.accounts.v1.DatasourceService.CompleteGitHubAppSetup:input_type -> saas.accounts.v1.CompleteGitHubAppSetupRequest + 51, // 110: saas.accounts.v1.DatasourceService.MigrateGitHubSourceToApp:input_type -> saas.accounts.v1.MigrateGitHubSourceToAppRequest + 57, // 111: saas.accounts.v1.DatasourceService.BeginDatasourceAccountLink:input_type -> saas.accounts.v1.BeginDatasourceAccountLinkRequest + 59, // 112: saas.accounts.v1.DatasourceService.CompleteDatasourceAccountLink:input_type -> saas.accounts.v1.CompleteDatasourceAccountLinkRequest + 61, // 113: saas.accounts.v1.DatasourceService.ListMyDatasourceAccountLinks:input_type -> saas.accounts.v1.ListMyDatasourceAccountLinksRequest + 63, // 114: saas.accounts.v1.DatasourceService.DeleteDatasourceAccountLink:input_type -> saas.accounts.v1.DeleteDatasourceAccountLinkRequest + 65, // 115: saas.accounts.v1.DatasourceService.GetDatasourceDirectory:input_type -> saas.accounts.v1.GetDatasourceDirectoryRequest + 67, // 116: saas.accounts.v1.DatasourceService.BindDatasourceGroup:input_type -> saas.accounts.v1.BindDatasourceGroupRequest + 69, // 117: saas.accounts.v1.DatasourceService.UnbindDatasourceGroup:input_type -> saas.accounts.v1.UnbindDatasourceGroupRequest + 71, // 118: saas.accounts.v1.DatasourceService.ClaimDatasourceDomain:input_type -> saas.accounts.v1.ClaimDatasourceDomainRequest + 73, // 119: saas.accounts.v1.DatasourceService.VerifyDatasourceDomain:input_type -> saas.accounts.v1.VerifyDatasourceDomainRequest + 75, // 120: saas.accounts.v1.DatasourceService.DeleteDatasourceDomain:input_type -> saas.accounts.v1.DeleteDatasourceDomainRequest + 78, // 121: saas.accounts.v1.DatasourceService.ListSourceDelegations:input_type -> saas.accounts.v1.ListSourceDelegationsRequest + 80, // 122: saas.accounts.v1.DatasourceService.RevokeSourceDelegation:input_type -> saas.accounts.v1.RevokeSourceDelegationRequest + 87, // 123: saas.accounts.v1.DatasourceService.DelegateSourceTriggers:input_type -> saas.accounts.v1.DelegateSourceTriggersRequest + 89, // 124: saas.accounts.v1.DatasourceService.GetSourceTriggerDeclaration:input_type -> saas.accounts.v1.GetSourceTriggerDeclarationRequest + 91, // 125: saas.accounts.v1.DatasourceService.ReconcileSource:input_type -> saas.accounts.v1.ReconcileSourceRequest + 93, // 126: saas.accounts.v1.DatasourceService.LookupReconcileSource:input_type -> saas.accounts.v1.LookupReconcileSourceRequest + 104, // 127: saas.accounts.v1.DatasourceService.PruneSourceOperationReceipts:output_type -> saas.accounts.v1.PruneSourceOperationReceiptsResponse + 104, // 128: saas.accounts.v1.DatasourceService.LookupPruneSourceOperationReceipts:output_type -> saas.accounts.v1.PruneSourceOperationReceiptsResponse + 101, // 129: saas.accounts.v1.DatasourceService.InvokeSourceOperation:output_type -> saas.accounts.v1.InvokeSourceOperationResponse + 101, // 130: saas.accounts.v1.DatasourceService.LookupInvokeSourceOperation:output_type -> saas.accounts.v1.InvokeSourceOperationResponse + 101, // 131: saas.accounts.v1.DatasourceService.VerifySourceOperationReceipt:output_type -> saas.accounts.v1.InvokeSourceOperationResponse + 98, // 132: saas.accounts.v1.DatasourceService.ListSourceOperations:output_type -> saas.accounts.v1.ListSourceOperationsResponse + 96, // 133: saas.accounts.v1.DatasourceService.DeclareSourceOperations:output_type -> saas.accounts.v1.DeclareSourceOperationsResponse + 21, // 134: saas.accounts.v1.DatasourceService.AddGitHubSource:output_type -> saas.accounts.v1.AddGitHubSourceResponse + 23, // 135: saas.accounts.v1.DatasourceService.AddSource:output_type -> saas.accounts.v1.AddSourceResponse + 26, // 136: saas.accounts.v1.DatasourceService.UpdateSource:output_type -> saas.accounts.v1.UpdateSourceResponse + 31, // 137: saas.accounts.v1.DatasourceService.GetDatasourceCatalog:output_type -> saas.accounts.v1.GetDatasourceCatalogResponse + 33, // 138: saas.accounts.v1.DatasourceService.ListSources:output_type -> saas.accounts.v1.ListSourcesResponse + 35, // 139: saas.accounts.v1.DatasourceService.GetSource:output_type -> saas.accounts.v1.GetSourceResponse + 37, // 140: saas.accounts.v1.DatasourceService.SyncSource:output_type -> saas.accounts.v1.SyncSourceResponse + 43, // 141: saas.accounts.v1.DatasourceService.GetSourceSync:output_type -> saas.accounts.v1.GetSourceSyncResponse + 45, // 142: saas.accounts.v1.DatasourceService.DeleteSource:output_type -> saas.accounts.v1.DeleteSourceResponse + 48, // 143: saas.accounts.v1.DatasourceService.BeginGitHubAppSetup:output_type -> saas.accounts.v1.BeginGitHubAppSetupResponse + 50, // 144: saas.accounts.v1.DatasourceService.CompleteGitHubAppSetup:output_type -> saas.accounts.v1.CompleteGitHubAppSetupResponse + 52, // 145: saas.accounts.v1.DatasourceService.MigrateGitHubSourceToApp:output_type -> saas.accounts.v1.MigrateGitHubSourceToAppResponse + 58, // 146: saas.accounts.v1.DatasourceService.BeginDatasourceAccountLink:output_type -> saas.accounts.v1.BeginDatasourceAccountLinkResponse + 60, // 147: saas.accounts.v1.DatasourceService.CompleteDatasourceAccountLink:output_type -> saas.accounts.v1.CompleteDatasourceAccountLinkResponse + 62, // 148: saas.accounts.v1.DatasourceService.ListMyDatasourceAccountLinks:output_type -> saas.accounts.v1.ListMyDatasourceAccountLinksResponse + 64, // 149: saas.accounts.v1.DatasourceService.DeleteDatasourceAccountLink:output_type -> saas.accounts.v1.DeleteDatasourceAccountLinkResponse + 66, // 150: saas.accounts.v1.DatasourceService.GetDatasourceDirectory:output_type -> saas.accounts.v1.GetDatasourceDirectoryResponse + 68, // 151: saas.accounts.v1.DatasourceService.BindDatasourceGroup:output_type -> saas.accounts.v1.BindDatasourceGroupResponse + 70, // 152: saas.accounts.v1.DatasourceService.UnbindDatasourceGroup:output_type -> saas.accounts.v1.UnbindDatasourceGroupResponse + 72, // 153: saas.accounts.v1.DatasourceService.ClaimDatasourceDomain:output_type -> saas.accounts.v1.ClaimDatasourceDomainResponse + 74, // 154: saas.accounts.v1.DatasourceService.VerifyDatasourceDomain:output_type -> saas.accounts.v1.VerifyDatasourceDomainResponse + 76, // 155: saas.accounts.v1.DatasourceService.DeleteDatasourceDomain:output_type -> saas.accounts.v1.DeleteDatasourceDomainResponse + 79, // 156: saas.accounts.v1.DatasourceService.ListSourceDelegations:output_type -> saas.accounts.v1.ListSourceDelegationsResponse + 81, // 157: saas.accounts.v1.DatasourceService.RevokeSourceDelegation:output_type -> saas.accounts.v1.RevokeSourceDelegationResponse + 88, // 158: saas.accounts.v1.DatasourceService.DelegateSourceTriggers:output_type -> saas.accounts.v1.DelegateSourceTriggersResponse + 90, // 159: saas.accounts.v1.DatasourceService.GetSourceTriggerDeclaration:output_type -> saas.accounts.v1.GetSourceTriggerDeclarationResponse + 92, // 160: saas.accounts.v1.DatasourceService.ReconcileSource:output_type -> saas.accounts.v1.ReconcileSourceResponse + 92, // 161: saas.accounts.v1.DatasourceService.LookupReconcileSource:output_type -> saas.accounts.v1.ReconcileSourceResponse + 127, // [127:162] is the sub-list for method output_type + 92, // [92:127] is the sub-list for method input_type 92, // [92:92] is the sub-list for extension type_name 92, // [92:92] is the sub-list for extension extendee 0, // [0:92] is the sub-list for field type_name diff --git a/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource.pb.gw.go b/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource.pb.gw.go index 4d1d70321..98b0ff851 100644 --- a/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource.pb.gw.go +++ b/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource.pb.gw.go @@ -151,6 +151,33 @@ func local_request_DatasourceService_LookupInvokeSourceOperation_0(ctx context.C return msg, metadata, err } +func request_DatasourceService_VerifySourceOperationReceipt_0(ctx context.Context, marshaler runtime.Marshaler, client DatasourceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq InvokeSourceOperationRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.VerifySourceOperationReceipt(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_DatasourceService_VerifySourceOperationReceipt_0(ctx context.Context, marshaler runtime.Marshaler, server DatasourceServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq InvokeSourceOperationRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.VerifySourceOperationReceipt(ctx, &protoReq) + return msg, metadata, err +} + func request_DatasourceService_ListSourceOperations_0(ctx context.Context, marshaler runtime.Marshaler, client DatasourceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var ( protoReq ListSourceOperationsRequest @@ -313,6 +340,26 @@ func RegisterDatasourceServiceHandlerServer(ctx context.Context, mux *runtime.Se } forward_DatasourceService_LookupInvokeSourceOperation_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_DatasourceService_VerifySourceOperationReceipt_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", runtime.WithHTTPPathPattern("/v1/datasource-operation-receipts/verify")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_DatasourceService_VerifySourceOperationReceipt_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_DatasourceService_VerifySourceOperationReceipt_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodGet, pattern_DatasourceService_ListSourceOperations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -427,6 +474,23 @@ func RegisterDatasourceServiceHandlerClient(ctx context.Context, mux *runtime.Se } forward_DatasourceService_LookupInvokeSourceOperation_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_DatasourceService_VerifySourceOperationReceipt_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", runtime.WithHTTPPathPattern("/v1/datasource-operation-receipts/verify")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_DatasourceService_VerifySourceOperationReceipt_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_DatasourceService_VerifySourceOperationReceipt_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodGet, pattern_DatasourceService_ListSourceOperations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -465,15 +529,17 @@ func RegisterDatasourceServiceHandlerClient(ctx context.Context, mux *runtime.Se } var ( - pattern_DatasourceService_InvokeSourceOperation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "organizations", "org_id", "datasources", "source_id", "operations", "operation"}, "invoke")) - pattern_DatasourceService_LookupInvokeSourceOperation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "datasource-operation-receipts", "effect_id"}, "")) - pattern_DatasourceService_ListSourceOperations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"v1", "organizations", "org_id", "datasources", "source_id", "operations"}, "")) - pattern_DatasourceService_DeclareSourceOperations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"v1", "organizations", "org_id", "datasources", "source_id", "operations"}, "")) + pattern_DatasourceService_InvokeSourceOperation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "organizations", "org_id", "datasources", "source_id", "operations", "operation"}, "invoke")) + pattern_DatasourceService_LookupInvokeSourceOperation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "datasource-operation-receipts", "effect_id"}, "")) + pattern_DatasourceService_VerifySourceOperationReceipt_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "datasource-operation-receipts", "verify"}, "")) + pattern_DatasourceService_ListSourceOperations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"v1", "organizations", "org_id", "datasources", "source_id", "operations"}, "")) + pattern_DatasourceService_DeclareSourceOperations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"v1", "organizations", "org_id", "datasources", "source_id", "operations"}, "")) ) var ( - forward_DatasourceService_InvokeSourceOperation_0 = runtime.ForwardResponseMessage - forward_DatasourceService_LookupInvokeSourceOperation_0 = runtime.ForwardResponseMessage - forward_DatasourceService_ListSourceOperations_0 = runtime.ForwardResponseMessage - forward_DatasourceService_DeclareSourceOperations_0 = runtime.ForwardResponseMessage + forward_DatasourceService_InvokeSourceOperation_0 = runtime.ForwardResponseMessage + forward_DatasourceService_LookupInvokeSourceOperation_0 = runtime.ForwardResponseMessage + forward_DatasourceService_VerifySourceOperationReceipt_0 = runtime.ForwardResponseMessage + forward_DatasourceService_ListSourceOperations_0 = runtime.ForwardResponseMessage + forward_DatasourceService_DeclareSourceOperations_0 = runtime.ForwardResponseMessage ) diff --git a/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource_grpc.pb.go b/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource_grpc.pb.go index acb01ed49..d1d77d39b 100644 --- a/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource_grpc.pb.go +++ b/module/services/accounts/code/pkg/gen/saas/accounts/v1/datasource_grpc.pb.go @@ -24,6 +24,7 @@ const ( DatasourceService_LookupPruneSourceOperationReceipts_FullMethodName = "/saas.accounts.v1.DatasourceService/LookupPruneSourceOperationReceipts" DatasourceService_InvokeSourceOperation_FullMethodName = "/saas.accounts.v1.DatasourceService/InvokeSourceOperation" DatasourceService_LookupInvokeSourceOperation_FullMethodName = "/saas.accounts.v1.DatasourceService/LookupInvokeSourceOperation" + DatasourceService_VerifySourceOperationReceipt_FullMethodName = "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt" DatasourceService_ListSourceOperations_FullMethodName = "/saas.accounts.v1.DatasourceService/ListSourceOperations" DatasourceService_DeclareSourceOperations_FullMethodName = "/saas.accounts.v1.DatasourceService/DeclareSourceOperations" DatasourceService_AddGitHubSource_FullMethodName = "/saas.accounts.v1.DatasourceService/AddGitHubSource" @@ -82,6 +83,13 @@ type DatasourceServiceClient interface { // Once an attempt exists, retained receipt evidence survives declaration // removal or replacement. Current source read authority still applies. LookupInvokeSourceOperation(ctx context.Context, in *LookupInvokeSourceOperationRequest, opts ...grpc.CallOption) (*InvokeSourceOperationResponse, error) + // VerifySourceOperationReceipt conditionally reads retained output using the + // exact original Invoke request, including a nonempty declaration precondition. + // Committed means the normalized request and admitted declaration match the + // stored attempt. Unknown remains unresolved; this method never redispatches. + // Current actor, tenant and stored-source read authority apply before comparison. + // This is independent of the paired Runnable Lookup contract above. + VerifySourceOperationReceipt(ctx context.Context, in *InvokeSourceOperationRequest, opts ...grpc.CallOption) (*InvokeSourceOperationResponse, error) // ListSourceOperations reads the currently admitted declarations under source authority. ListSourceOperations(ctx context.Context, in *ListSourceOperationsRequest, opts ...grpc.CallOption) (*ListSourceOperationsResponse, error) // DeclareSourceOperations atomically replaces the source operation set, as an administrator. @@ -271,6 +279,16 @@ func (c *datasourceServiceClient) LookupInvokeSourceOperation(ctx context.Contex return out, nil } +func (c *datasourceServiceClient) VerifySourceOperationReceipt(ctx context.Context, in *InvokeSourceOperationRequest, opts ...grpc.CallOption) (*InvokeSourceOperationResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(InvokeSourceOperationResponse) + err := c.cc.Invoke(ctx, DatasourceService_VerifySourceOperationReceipt_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *datasourceServiceClient) ListSourceOperations(ctx context.Context, in *ListSourceOperationsRequest, opts ...grpc.CallOption) (*ListSourceOperationsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListSourceOperationsResponse) @@ -597,6 +615,13 @@ type DatasourceServiceServer interface { // Once an attempt exists, retained receipt evidence survives declaration // removal or replacement. Current source read authority still applies. LookupInvokeSourceOperation(context.Context, *LookupInvokeSourceOperationRequest) (*InvokeSourceOperationResponse, error) + // VerifySourceOperationReceipt conditionally reads retained output using the + // exact original Invoke request, including a nonempty declaration precondition. + // Committed means the normalized request and admitted declaration match the + // stored attempt. Unknown remains unresolved; this method never redispatches. + // Current actor, tenant and stored-source read authority apply before comparison. + // This is independent of the paired Runnable Lookup contract above. + VerifySourceOperationReceipt(context.Context, *InvokeSourceOperationRequest) (*InvokeSourceOperationResponse, error) // ListSourceOperations reads the currently admitted declarations under source authority. ListSourceOperations(context.Context, *ListSourceOperationsRequest) (*ListSourceOperationsResponse, error) // DeclareSourceOperations atomically replaces the source operation set, as an administrator. @@ -758,6 +783,9 @@ func (UnimplementedDatasourceServiceServer) InvokeSourceOperation(context.Contex func (UnimplementedDatasourceServiceServer) LookupInvokeSourceOperation(context.Context, *LookupInvokeSourceOperationRequest) (*InvokeSourceOperationResponse, error) { return nil, status.Error(codes.Unimplemented, "method LookupInvokeSourceOperation not implemented") } +func (UnimplementedDatasourceServiceServer) VerifySourceOperationReceipt(context.Context, *InvokeSourceOperationRequest) (*InvokeSourceOperationResponse, error) { + return nil, status.Error(codes.Unimplemented, "method VerifySourceOperationReceipt not implemented") +} func (UnimplementedDatasourceServiceServer) ListSourceOperations(context.Context, *ListSourceOperationsRequest) (*ListSourceOperationsResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListSourceOperations not implemented") } @@ -941,6 +969,24 @@ func _DatasourceService_LookupInvokeSourceOperation_Handler(srv interface{}, ctx return interceptor(ctx, in, info, handler) } +func _DatasourceService_VerifySourceOperationReceipt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InvokeSourceOperationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DatasourceServiceServer).VerifySourceOperationReceipt(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: DatasourceService_VerifySourceOperationReceipt_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DatasourceServiceServer).VerifySourceOperationReceipt(ctx, req.(*InvokeSourceOperationRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _DatasourceService_ListSourceOperations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListSourceOperationsRequest) if err := dec(in); err != nil { @@ -1504,6 +1550,10 @@ var DatasourceService_ServiceDesc = grpc.ServiceDesc{ MethodName: "LookupInvokeSourceOperation", Handler: _DatasourceService_LookupInvokeSourceOperation_Handler, }, + { + MethodName: "VerifySourceOperationReceipt", + Handler: _DatasourceService_VerifySourceOperationReceipt_Handler, + }, { MethodName: "ListSourceOperations", Handler: _DatasourceService_ListSourceOperations_Handler, diff --git a/module/services/accounts/generated/api-contract-surfaces.json b/module/services/accounts/generated/api-contract-surfaces.json index 542eb61a1..e20dd44a1 100644 --- a/module/services/accounts/generated/api-contract-surfaces.json +++ b/module/services/accounts/generated/api-contract-surfaces.json @@ -238,7 +238,8 @@ "/saas.accounts.v1.DatasourceService/SyncSource", "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup", "/saas.accounts.v1.DatasourceService/UpdateSource", - "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain" + "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain", + "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt" ] }, { diff --git a/module/services/accounts/generated/authz-methods.json b/module/services/accounts/generated/authz-methods.json index d4274ef92..944d047f1 100644 --- a/module/services/accounts/generated/authz-methods.json +++ b/module/services/accounts/generated/authz-methods.json @@ -4117,6 +4117,53 @@ "policy_sha256": "3572d1c600161dd9cc67eadd737c10f79f7c9e2ed73140465031538f7baa3e85", "rate_limit_backend_failure_mode": "RATE_LIMIT_BACKEND_FAILURE_MODE_FAIL_OPEN" }, + { + "procedure": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", + "full_service": "saas.accounts.v1.DatasourceService", + "method": "VerifySourceOperationReceipt", + "input_type": "saas.accounts.v1.InvokeSourceOperationRequest", + "output_type": "saas.accounts.v1.InvokeSourceOperationResponse", + "client_streaming": false, + "server_streaming": false, + "policy": { + "exposure": "EXPOSURE_AUTHENTICATED", + "tenant": "TENANT_REQUIREMENT_ORG_MEMBER", + "permissions": [ + "datasource:read" + ], + "scopes": [ + "datasource:read" + ], + "resource_bindings": [ + { + "request_field": "effect_id", + "target": "RESOURCE_TARGET_OWNED_RESOURCE", + "lookup": "RESOURCE_LOOKUP_RESOURCE_TO_ORGANIZATION" + } + ], + "mfa": "MFA_REQUIREMENT_NONE", + "audit": { + "events": [], + "emission": "AUDIT_EMISSION_NONE" + }, + "idempotency": "IDEMPOTENCY_REQUIREMENT_FORBIDDEN", + "rate_limit": "RATE_LIMIT_CLASS_STANDARD_READ", + "request_sensitivity": "SENSITIVITY_SECRET", + "response_sensitivity": "SENSITIVITY_SECRET", + "platform_role": "PLATFORM_ROLE_REQUIREMENT_NONE", + "authentication_factor_attempt": false, + "conditions": [], + "impersonation": "IMPERSONATION_REQUIREMENT_UNSPECIFIED" + }, + "policy_tier": "org_member", + "owner": { + "module": "saas-starter", + "service": "accounts" + }, + "source_proto": "saas/accounts/v1/datasource.proto", + "policy_sha256": "12b8912362191baf4b79eb43a93ff269d625872ea953ddd1d1b82c2f020aa73d", + "rate_limit_backend_failure_mode": "RATE_LIMIT_BACKEND_FAILURE_MODE_FAIL_OPEN" + }, { "procedure": "/saas.accounts.v1.DelegationService/DecideDelegation", "full_service": "saas.accounts.v1.DelegationService", diff --git a/module/services/accounts/generated/gateway-routes.json b/module/services/accounts/generated/gateway-routes.json index 5a558fd21..07bdacb02 100644 --- a/module/services/accounts/generated/gateway-routes.json +++ b/module/services/accounts/generated/gateway-routes.json @@ -1089,6 +1089,22 @@ "rewrite_path": "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain", "remove_after": "2026-10-11" }, + { + "protocol": "GATEWAY_PROTOCOL_CONNECT", + "method": "POST", + "path": "/customers.DatasourceService/VerifySourceOperationReceipt", + "match": "GATEWAY_MATCH_EXACT", + "procedure": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", + "owner": { + "module": "saas-starter", + "service": "accounts" + }, + "upstream_endpoint": "connect", + "exposure": "EXPOSURE_AUTHENTICATED", + "source": "GATEWAY_ROUTE_SOURCE_COMPATIBILITY_ALIAS", + "rewrite_path": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", + "remove_after": "2026-10-11" + }, { "protocol": "GATEWAY_PROTOCOL_CONNECT", "method": "POST", @@ -4945,6 +4961,22 @@ "rewrite_path": "", "remove_after": "" }, + { + "protocol": "GATEWAY_PROTOCOL_CONNECT", + "method": "POST", + "path": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", + "match": "GATEWAY_MATCH_EXACT", + "procedure": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", + "owner": { + "module": "saas-starter", + "service": "accounts" + }, + "upstream_endpoint": "connect", + "exposure": "EXPOSURE_AUTHENTICATED", + "source": "GATEWAY_ROUTE_SOURCE_DESCRIPTOR", + "rewrite_path": "", + "remove_after": "" + }, { "protocol": "GATEWAY_PROTOCOL_CONNECT", "method": "POST", @@ -8993,6 +9025,22 @@ "rewrite_path": "", "remove_after": "" }, + { + "protocol": "GATEWAY_PROTOCOL_REST", + "method": "POST", + "path": "/v1/datasource-operation-receipts/verify", + "match": "GATEWAY_MATCH_EXACT", + "procedure": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", + "owner": { + "module": "saas-starter", + "service": "accounts" + }, + "upstream_endpoint": "rest", + "exposure": "EXPOSURE_AUTHENTICATED", + "source": "GATEWAY_ROUTE_SOURCE_DESCRIPTOR", + "rewrite_path": "", + "remove_after": "" + }, { "protocol": "GATEWAY_PROTOCOL_REST", "method": "POST", diff --git a/module/services/accounts/generated/openapi-raw/api.swagger.json b/module/services/accounts/generated/openapi-raw/api.swagger.json index 115c508ec..a5ab2c284 100644 --- a/module/services/accounts/generated/openapi-raw/api.swagger.json +++ b/module/services/accounts/generated/openapi-raw/api.swagger.json @@ -1400,6 +1400,40 @@ ] } }, + "/v1/datasource-operation-receipts/verify": { + "post": { + "summary": "VerifySourceOperationReceipt conditionally reads retained output using the\nexact original Invoke request, including a nonempty declaration precondition.\nCommitted means the normalized request and admitted declaration match the\nstored attempt. Unknown remains unresolved; this method never redispatches.\nCurrent actor, tenant and stored-source read authority apply before comparison.\nThis is independent of the paired Runnable Lookup contract above.", + "operationId": "DatasourceService_VerifySourceOperationReceipt", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1InvokeSourceOperationResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/googleRpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "description": "InvokeSourceOperationRequest carries exactly one JSON object in input_json.\neffect_id must match x-codefly-effect-id; either location may supply it.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InvokeSourceOperationRequest" + } + } + ], + "tags": [ + "DatasourceService" + ] + } + }, "/v1/datasource-operation-receipts/{effectId}": { "get": { "summary": "LookupInvokeSourceOperation recovers a receipt without contacting the provider.\nNotFound \"source effect not found\" means there is no attempt marker; retrying\nthe same effect is safe. An unknown receipt never authorizes redispatch.\nOnce an attempt exists, retained receipt evidence survives declaration\nremoval or replacement. Current source read authority still applies.", @@ -9578,6 +9612,31 @@ }, "description": "Invoice — trimmed view of Stripe's invoice object. Amounts are in\nthe smallest currency unit (cents for USD/EUR); FE divides by 100." }, + "v1InvokeSourceOperationRequest": { + "type": "object", + "properties": { + "orgId": { + "type": "string" + }, + "sourceId": { + "type": "string" + }, + "operation": { + "type": "string" + }, + "inputJson": { + "type": "string" + }, + "effectId": { + "type": "string" + }, + "expectedDeclarationDigest": { + "type": "string", + "description": "Optional for legacy callers. A caller that admitted a declaration supplies\nits canonical digest; a replacement is refused before provider dispatch.\nThis precondition participates in the receipt request fingerprint." + } + }, + "description": "InvokeSourceOperationRequest carries exactly one JSON object in input_json.\neffect_id must match x-codefly-effect-id; either location may supply it." + }, "v1InvokeSourceOperationResponse": { "type": "object", "properties": { diff --git a/module/services/accounts/generated/rest-surface.json b/module/services/accounts/generated/rest-surface.json index 870cd47c0..abaeb24da 100644 --- a/module/services/accounts/generated/rest-surface.json +++ b/module/services/accounts/generated/rest-surface.json @@ -1653,6 +1653,22 @@ "rewrite_path": "", "remove_after": "" }, + { + "protocol": "GATEWAY_PROTOCOL_REST", + "method": "POST", + "path": "/v1/datasource-operation-receipts/verify", + "match": "GATEWAY_MATCH_EXACT", + "procedure": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", + "owner": { + "module": "saas-starter", + "service": "accounts" + }, + "upstream_endpoint": "rest", + "exposure": "EXPOSURE_AUTHENTICATED", + "source": "GATEWAY_ROUTE_SOURCE_DESCRIPTOR", + "rewrite_path": "", + "remove_after": "" + }, { "protocol": "GATEWAY_PROTOCOL_REST", "method": "POST", diff --git a/module/services/accounts/generated/service-catalog.json b/module/services/accounts/generated/service-catalog.json index 87edf3db3..c78909f8e 100644 --- a/module/services/accounts/generated/service-catalog.json +++ b/module/services/accounts/generated/service-catalog.json @@ -198,7 +198,8 @@ "/saas.accounts.v1.DatasourceService/SyncSource", "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup", "/saas.accounts.v1.DatasourceService/UpdateSource", - "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain" + "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain", + "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt" ] }, { @@ -5558,6 +5559,67 @@ "service": "accounts" } }, + { + "procedure": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", + "service": "DatasourceService", + "full_service": "saas.accounts.v1.DatasourceService", + "method": "VerifySourceOperationReceipt", + "input_type": "saas.accounts.v1.InvokeSourceOperationRequest", + "output_type": "saas.accounts.v1.InvokeSourceOperationResponse", + "client_streaming": false, + "server_streaming": false, + "deprecated": false, + "source_proto": "saas/accounts/v1/datasource.proto", + "protocols": [ + "PROTOCOL_GRPC", + "PROTOCOL_CONNECT", + "PROTOCOL_REST" + ], + "http_bindings": [ + { + "method": "POST", + "path": "/v1/datasource-operation-receipts/verify", + "body": "*", + "response_body": "" + } + ], + "policy": { + "exposure": "EXPOSURE_AUTHENTICATED", + "tenant": "TENANT_REQUIREMENT_ORG_MEMBER", + "permissions": [ + "datasource:read" + ], + "scopes": [ + "datasource:read" + ], + "resource_bindings": [ + { + "request_field": "effect_id", + "target": "RESOURCE_TARGET_OWNED_RESOURCE", + "lookup": "RESOURCE_LOOKUP_RESOURCE_TO_ORGANIZATION" + } + ], + "mfa": "MFA_REQUIREMENT_NONE", + "audit": { + "events": [], + "emission": "AUDIT_EMISSION_NONE" + }, + "idempotency": "IDEMPOTENCY_REQUIREMENT_FORBIDDEN", + "rate_limit": "RATE_LIMIT_CLASS_STANDARD_READ", + "request_sensitivity": "SENSITIVITY_SECRET", + "response_sensitivity": "SENSITIVITY_SECRET", + "platform_role": "PLATFORM_ROLE_REQUIREMENT_NONE", + "authentication_factor_attempt": false, + "conditions": [], + "impersonation": "IMPERSONATION_REQUIREMENT_UNSPECIFIED" + }, + "policy_tier": "org_member", + "description": "Read a source receipt only when the original invocation and admitted declaration match.", + "owner": { + "module": "saas-starter", + "service": "accounts" + } + }, { "procedure": "/saas.accounts.v1.DelegationService/DecideDelegation", "service": "DelegationService", diff --git a/module/services/accounts/openapi/api.swagger.json b/module/services/accounts/openapi/api.swagger.json index 7450d6bd1..f6be8fb63 100644 --- a/module/services/accounts/openapi/api.swagger.json +++ b/module/services/accounts/openapi/api.swagger.json @@ -2757,6 +2757,31 @@ }, "type": "object" }, + "v1InvokeSourceOperationRequest": { + "description": "InvokeSourceOperationRequest carries exactly one JSON object in input_json.\neffect_id must match x-codefly-effect-id; either location may supply it.", + "properties": { + "effectId": { + "type": "string" + }, + "expectedDeclarationDigest": { + "description": "Optional for legacy callers. A caller that admitted a declaration supplies\nits canonical digest; a replacement is refused before provider dispatch.\nThis precondition participates in the receipt request fingerprint.", + "type": "string" + }, + "inputJson": { + "type": "string" + }, + "operation": { + "type": "string" + }, + "orgId": { + "type": "string" + }, + "sourceId": { + "type": "string" + } + }, + "type": "object" + }, "v1InvokeSourceOperationResponse": { "properties": { "outputJson": { @@ -7492,6 +7517,40 @@ ] } }, + "/v1/datasource-operation-receipts/verify": { + "post": { + "operationId": "DatasourceService_VerifySourceOperationReceipt", + "parameters": [ + { + "description": "InvokeSourceOperationRequest carries exactly one JSON object in input_json.\neffect_id must match x-codefly-effect-id; either location may supply it.", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InvokeSourceOperationRequest" + } + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1InvokeSourceOperationResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/googleRpcStatus" + } + } + }, + "summary": "VerifySourceOperationReceipt conditionally reads retained output using the\nexact original Invoke request, including a nonempty declaration precondition.\nCommitted means the normalized request and admitted declaration match the\nstored attempt. Unknown remains unresolved; this method never redispatches.\nCurrent actor, tenant and stored-source read authority apply before comparison.\nThis is independent of the paired Runnable Lookup contract above.", + "tags": [ + "DatasourceService" + ] + } + }, "/v1/datasource-operation-receipts/{effectId}": { "get": { "operationId": "DatasourceService_LookupInvokeSourceOperation", diff --git a/module/services/accounts/proto/saas/accounts/v1/datasource.proto b/module/services/accounts/proto/saas/accounts/v1/datasource.proto index c95696bd1..1df8959d4 100644 --- a/module/services/accounts/proto/saas/accounts/v1/datasource.proto +++ b/module/services/accounts/proto/saas/accounts/v1/datasource.proto @@ -1662,6 +1662,37 @@ service DatasourceService { }; } + // VerifySourceOperationReceipt conditionally reads retained output using the + // exact original Invoke request, including a nonempty declaration precondition. + // Committed means the normalized request and admitted declaration match the + // stored attempt. Unknown remains unresolved; this method never redispatches. + // Current actor, tenant and stored-source read authority apply before comparison. + // This is independent of the paired Runnable Lookup contract above. + rpc VerifySourceOperationReceipt(InvokeSourceOperationRequest) returns (InvokeSourceOperationResponse) { + option (google.api.http) = { + post: "/v1/datasource-operation-receipts/verify" + body: "*" + }; + option (saas.policy.v1.method_policy) = { + exposure: EXPOSURE_AUTHENTICATED + tenant: TENANT_REQUIREMENT_ORG_MEMBER + permissions: "datasource:read" + scopes: "datasource:read" + resource_bindings: { + request_field: "effect_id" + target: RESOURCE_TARGET_OWNED_RESOURCE + lookup: RESOURCE_LOOKUP_RESOURCE_TO_ORGANIZATION + } + mfa: MFA_REQUIREMENT_NONE + audit: {emission: AUDIT_EMISSION_NONE} + idempotency: IDEMPOTENCY_REQUIREMENT_FORBIDDEN + rate_limit: RATE_LIMIT_CLASS_STANDARD_READ + request_sensitivity: SENSITIVITY_SECRET + response_sensitivity: SENSITIVITY_SECRET + platform_role: PLATFORM_ROLE_REQUIREMENT_NONE + }; + } + // ListSourceOperations reads the currently admitted declarations under source authority. rpc ListSourceOperations(ListSourceOperationsRequest) returns (ListSourceOperationsResponse) { option (google.api.http) = {get: "/v1/organizations/{org_id}/datasources/{source_id}/operations"}; diff --git a/module/services/auth-gateway/code/authz_catalog_gen.go b/module/services/auth-gateway/code/authz_catalog_gen.go index 0643fdfda..a714052ff 100644 --- a/module/services/auth-gateway/code/authz_catalog_gen.go +++ b/module/services/auth-gateway/code/authz_catalog_gen.go @@ -109,6 +109,7 @@ var generatedAuthorizationByProcedure = map[string]generatedAuthorizationMetadat "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup": {exposure: edgeExposureAuthenticated, rateLimitClass: edgeRateLimitClassStandardWrite, rateLimitBackendFailClosed: false, authenticationFactorAttempt: false, policySHA256: "d658d313d1ed64a0e5493f089c8c2339c8e4c4bc714e3a10c4cd2ee963c2d3e7"}, "/saas.accounts.v1.DatasourceService/UpdateSource": {exposure: edgeExposureAuthenticated, rateLimitClass: edgeRateLimitClassStandardWrite, rateLimitBackendFailClosed: false, authenticationFactorAttempt: false, policySHA256: "8f18fbf423e4a4f0afa902be617d8b960ec24a684774367482aead685b1b19b0"}, "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain": {exposure: edgeExposureAuthenticated, rateLimitClass: edgeRateLimitClassStandardWrite, rateLimitBackendFailClosed: false, authenticationFactorAttempt: false, policySHA256: "3572d1c600161dd9cc67eadd737c10f79f7c9e2ed73140465031538f7baa3e85"}, + "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt": {exposure: edgeExposureAuthenticated, rateLimitClass: edgeRateLimitClassStandardRead, rateLimitBackendFailClosed: false, authenticationFactorAttempt: false, policySHA256: "12b8912362191baf4b79eb43a93ff269d625872ea953ddd1d1b82c2f020aa73d"}, "/saas.accounts.v1.DelegationService/DecideDelegation": {exposure: edgeExposureAuthenticated, rateLimitClass: edgeRateLimitClassStandardRead, rateLimitBackendFailClosed: false, authenticationFactorAttempt: false, policySHA256: "09931634771ddd7607ac12157e0f55b08894234bf81b188659590ba202f4d486"}, "/saas.accounts.v1.DelegationService/ListPendingDelegations": {exposure: edgeExposureAuthenticated, rateLimitClass: edgeRateLimitClassStandardRead, rateLimitBackendFailClosed: false, authenticationFactorAttempt: false, policySHA256: "ad07a0509490d86d9bb64cb28e5db5ef578575d2cbab8ee86d279ffe1392cca8"}, "/saas.accounts.v1.DelegationService/RequestDelegation": {exposure: edgeExposureAuthenticated, rateLimitClass: edgeRateLimitClassStandardWrite, rateLimitBackendFailClosed: false, authenticationFactorAttempt: false, policySHA256: "9f9023065c47c9a66cfe1d5893b78e28d36a08f377b078451d51eda61910d199"}, @@ -352,6 +353,7 @@ var generatedRESTProcedureByRoute = map[string]string{ "POST /v1/organizations/{org_id}/datasources/{source_id}/operations/{operation}:invoke": "/saas.accounts.v1.DatasourceService/InvokeSourceOperation", "GET /v1/organizations/{org_id}/datasources/{source_id}/operations": "/saas.accounts.v1.DatasourceService/ListSourceOperations", "GET /v1/datasource-operation-receipts/{effect_id}": "/saas.accounts.v1.DatasourceService/LookupInvokeSourceOperation", + "POST /v1/datasource-operation-receipts/verify": "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", "POST /v1/delegations/{id}:decide": "/saas.accounts.v1.DelegationService/DecideDelegation", "GET /v1/delegations:pending": "/saas.accounts.v1.DelegationService/ListPendingDelegations", "POST /v1/delegations": "/saas.accounts.v1.DelegationService/RequestDelegation", diff --git a/module/services/auth-gateway/code/routing_catalog_gen.go b/module/services/auth-gateway/code/routing_catalog_gen.go index 704e2aa90..9d82c81b8 100644 --- a/module/services/auth-gateway/code/routing_catalog_gen.go +++ b/module/services/auth-gateway/code/routing_catalog_gen.go @@ -74,6 +74,7 @@ func generatedCatalogConnectRoutes() []*RouteEntry { {Service: "accounts_connect", Method: "POST", Path: "/customers.DatasourceService/UnbindDatasourceGroup", UpstreamPath: "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup", Procedure: "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup"}, {Service: "accounts_connect", Method: "POST", Path: "/customers.DatasourceService/UpdateSource", UpstreamPath: "/saas.accounts.v1.DatasourceService/UpdateSource", Procedure: "/saas.accounts.v1.DatasourceService/UpdateSource"}, {Service: "accounts_connect", Method: "POST", Path: "/customers.DatasourceService/VerifyDatasourceDomain", UpstreamPath: "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain", Procedure: "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain"}, + {Service: "accounts_connect", Method: "POST", Path: "/customers.DatasourceService/VerifySourceOperationReceipt", UpstreamPath: "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", Procedure: "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt"}, {Service: "accounts_connect", Method: "POST", Path: "/customers.DelegationService/DecideDelegation", UpstreamPath: "/saas.accounts.v1.DelegationService/DecideDelegation", Procedure: "/saas.accounts.v1.DelegationService/DecideDelegation"}, {Service: "accounts_connect", Method: "POST", Path: "/customers.DelegationService/ListPendingDelegations", UpstreamPath: "/saas.accounts.v1.DelegationService/ListPendingDelegations", Procedure: "/saas.accounts.v1.DelegationService/ListPendingDelegations"}, {Service: "accounts_connect", Method: "POST", Path: "/customers.DelegationService/RequestDelegation", UpstreamPath: "/saas.accounts.v1.DelegationService/RequestDelegation", Procedure: "/saas.accounts.v1.DelegationService/RequestDelegation"}, @@ -315,6 +316,7 @@ func generatedCatalogConnectRoutes() []*RouteEntry { {Service: "accounts_connect", Method: "POST", Path: "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup", UpstreamPath: "", Procedure: "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup"}, {Service: "accounts_connect", Method: "POST", Path: "/saas.accounts.v1.DatasourceService/UpdateSource", UpstreamPath: "", Procedure: "/saas.accounts.v1.DatasourceService/UpdateSource"}, {Service: "accounts_connect", Method: "POST", Path: "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain", UpstreamPath: "", Procedure: "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain"}, + {Service: "accounts_connect", Method: "POST", Path: "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt", UpstreamPath: "", Procedure: "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt"}, {Service: "accounts_connect", Method: "POST", Path: "/saas.accounts.v1.DelegationService/DecideDelegation", UpstreamPath: "", Procedure: "/saas.accounts.v1.DelegationService/DecideDelegation"}, {Service: "accounts_connect", Method: "POST", Path: "/saas.accounts.v1.DelegationService/ListPendingDelegations", UpstreamPath: "", Procedure: "/saas.accounts.v1.DelegationService/ListPendingDelegations"}, {Service: "accounts_connect", Method: "POST", Path: "/saas.accounts.v1.DelegationService/RequestDelegation", UpstreamPath: "", Procedure: "/saas.accounts.v1.DelegationService/RequestDelegation"}, diff --git a/module/services/auth-gateway/code/routing_rest_catalog_gen.go b/module/services/auth-gateway/code/routing_rest_catalog_gen.go index 7ff0c1f1f..feff1ce63 100644 --- a/module/services/auth-gateway/code/routing_rest_catalog_gen.go +++ b/module/services/auth-gateway/code/routing_rest_catalog_gen.go @@ -107,6 +107,7 @@ func generatedCatalogRESTRoutes() []*RouteEntry { {Service: "accounts", Method: "POST", Path: "/v1/auth/token", Procedure: "/saas.accounts.v1.AuthService/ExchangeClientToken"}, {Service: "accounts", Method: "POST", Path: "/v1/billing/connect/portal", Procedure: "/saas.accounts.v1.BillingService/OpenPortal"}, {Service: "accounts", Method: "POST", Path: "/v1/consent/terms", Procedure: "/saas.accounts.v1.ConsentService/AcceptTerms"}, + {Service: "accounts", Method: "POST", Path: "/v1/datasource-operation-receipts/verify", Procedure: "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt"}, {Service: "accounts", Method: "POST", Path: "/v1/delegations", Procedure: "/saas.accounts.v1.DelegationService/RequestDelegation"}, {Service: "accounts", Method: "POST", Path: "/v1/delegations/{id}:decide", Procedure: "/saas.accounts.v1.DelegationService/DecideDelegation"}, {Service: "accounts", Method: "POST", Path: "/v1/gdpr/delete", Procedure: "/saas.accounts.v1.GDPRService/RequestDeletion"}, diff --git a/module/services/frontend/code/package-lock.json b/module/services/frontend/code/package-lock.json index f5679667a..14848ffbb 100644 --- a/module/services/frontend/code/package-lock.json +++ b/module/services/frontend/code/package-lock.json @@ -15,7 +15,7 @@ "@bufbuild/protobuf": "^2.11.0", "@codefly-dev/saas-plugin-contract": "2.4.4", "@codefly-dev/saas-plugin-react": "0.4.5", - "@codefly-dev/saas-sdk": "0.3.42", + "@codefly-dev/saas-sdk": "0.3.43", "@codefly-dev/saas-ui": "0.13.0", "@codefly-dev/ui": "0.13.0", "@codefly/saas-plugin-manifest": "0.1.2", @@ -15742,7 +15742,7 @@ }, "packages/saas-sdk": { "name": "@codefly-dev/saas-sdk", - "version": "0.3.42", + "version": "0.3.43", "license": "Apache-2.0", "dependencies": { "@bufbuild/protobuf": "^2.11.0", diff --git a/module/services/frontend/code/package.json b/module/services/frontend/code/package.json index 815db3fbb..5ea30bef4 100644 --- a/module/services/frontend/code/package.json +++ b/module/services/frontend/code/package.json @@ -39,7 +39,7 @@ "@bufbuild/protobuf": "^2.11.0", "@codefly-dev/saas-plugin-contract": "2.4.4", "@codefly-dev/saas-plugin-react": "0.4.5", - "@codefly-dev/saas-sdk": "0.3.42", + "@codefly-dev/saas-sdk": "0.3.43", "@codefly-dev/saas-ui": "0.13.0", "@codefly-dev/ui": "0.13.0", "@codefly/saas-plugin-manifest": "0.1.2", diff --git a/module/services/frontend/code/packages/saas-sdk/generated/contract/catalog.codefly.json b/module/services/frontend/code/packages/saas-sdk/generated/contract/catalog.codefly.json index 68c3d388e..32d1be645 100644 --- a/module/services/frontend/code/packages/saas-sdk/generated/contract/catalog.codefly.json +++ b/module/services/frontend/code/packages/saas-sdk/generated/contract/catalog.codefly.json @@ -10,7 +10,7 @@ "kind": "protobuf", "package": "", "path": "contract.binpb", - "digest": "sha256:da3be80f4ed222b07d24e2b23d5eb797a36b1334fef560b24aeecf2850ac48d6", + "digest": "sha256:63471499a4c1c4f3cdecd8e5f9abb01f7bc0771038bced64f67721f45ed3c3ca", "services": [ { "name": "AccessibleScopeService", @@ -66,7 +66,8 @@ "/saas.accounts.v1.DatasourceService/SyncSource", "/saas.accounts.v1.DatasourceService/UnbindDatasourceGroup", "/saas.accounts.v1.DatasourceService/UpdateSource", - "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain" + "/saas.accounts.v1.DatasourceService/VerifyDatasourceDomain", + "/saas.accounts.v1.DatasourceService/VerifySourceOperationReceipt" ] }, { diff --git a/module/services/frontend/code/packages/saas-sdk/generated/contract/contract.binpb b/module/services/frontend/code/packages/saas-sdk/generated/contract/contract.binpb index 4d1a16547775bf37a8db22c84eca85144126722d..05c7e2c5a96eac421757ca030af176f25cece16b 100644 GIT binary patch delta 10668 zcmZ9S36NApn#bwt*IBQtcvm)O(?HScgrS1x%+5N-8awLjxO42Rv%9f7G44)Fm)a{- zvwgVZ&S4@OC@)yX?=N-X(N@t(2C)fK68 zWvQBf%QiLKdRO7um)%~4j*euH!i)*Y-jCg#tSGdNPhL@WPvMmb$)AMIzdOGxyYKD2 zlM;ikF1x7q!h)QbtQB{%ZSmTP$>Y7!i+5C{lCq*(w+E^UcRwpG8l9b+EN17rQ~D$x zs4AXbt=Z<5OEL|) zp~G71)!lWOTw^Xfd_>D#nfmO|VRcP)>LHmCP1&K1IsL>Tsmyha!-wY^T3Ya|;n})e zvw8>`HVv;E*6@FTao|i{u0B&&KV0A0Io|NPmZ7)nt~IwbHlax!qT#VaGXI*pBiH!9 zIm8%_(KKgTb4}Ui#$k76>wkm>4b6CB%k7QznS3q_rMRuWp?QP~mu*%(Yi(-E=2|is zZe!CWnU-v>PFhBLN2-6h`s|1-{zJINThWtzHZ!8GL3RD6)?BXcmSNe<&l?->XdQv}xt1p7yY808 zJF`PlDKAx_CbCRAqdZYtx=g6c^R6vjmaEHuye$>zn=$R9J?CLhq^eSts?JdSWO<+9<@aph8s@zReYS`u|VqmIA+z;GX(M^g+Ju%r!c8(~dGezB4 z>M(9h;wg`L{>7bdbEQ-8#8sV9rF8z}iOYbl*H+LpC7r3B7~J``v~;Ff;HhznE^s{=1DsPM2Pj2odF`ufHTWZ z0GXPA*>(cR)CA1&#C$UWq?mvOW&-jFGBpDW?F^7%1{T>FAi@khqh~-(01+l&u~Mtk zhzJw#Y?p?Zfala*!#Dv#ilUd;jBV|=g~3}f2?FCTdZK@|7%F%uirUF*v@6-g=H@e+xHh2U*> zRX&L!zT=6Wv3S*&cf4MglrAw3?|6Un%Xl7=Ft^Qf4j6GsEpD5aK48R=A?kK3jtG%= zSaC!Z-SSfG^u+td95Kv&V9gQH+((`}B%W6d5puT`M+R{p+wl`Y+$UBX5yb7~9 zLNb`!*QF)Q?N{bL)#h9&4tt3j0lk*^37@`qPmBD zG0ra)DPpJ_@0;aHM0FE<_p&(YG(^aWzFDngP&e5(m5T`Krub&H5<%T#zPL0MUCE>) zgStYOmQeR6AL@=JxLi{xU4CLgaosNWjf1A_a3D zzBAvLOKEc*etNz!M~0{~tvMn@e$p2g#M=##z$xG<b)y1#UelPO5ywOyEo?3==LICL~-7v(UnEM zJil}a8H@Z&e;mt5L&h_{v(m^&YZ=e@>6JzX8KN$>GKdiQSs!O2ebgah8a?NW7fl)w zBaMny5s^}~)G8u_qL-{9A}D&<4xR{#mRUtaP_#U5*dHdz;An+%^eZ~*F2yQ8@m68# z2ky`E-7%O|zS*R@qbsX?vq^P_qE)`xq`E`VYTwyv6m{2%R{QC#MiCjJuCa=U5P7Xt zL_|gFeDS(bL<~h6tRf<%=nbog42s^giin_Sqg6x%MVqW5A}HD%Hyi*(WKgt4DO#v^ zau0RPPaJyeBlqdNhrw*~MHr`zhpue%qtdzEgQ9Kz;A`V7@}OwD?;JFWJgsQEpFU_5 zks<01tB44ZciPQ}h>CXk;sc|I7>Yi$n-LK=qusuHX}tP0M94jMGa`exPpmg0c-w0? zBO-X)=c`k+-i*i~Zokz_1aAkFw?o>Sk1FOT&K7po6rJjnTV!x_S~>a;F26vEwjeP%DD3*!{dGRTXxai( z=>qhnEijcXfTOm+RJs6;?hTwtL8;OO+R?p1dQwoTbYzHnUtlU75hC9om`X=f(XEdZ zBLneZP^xsqaP&|i-0$|tj|og|<6o4jv4N>=WKcCOFtv>cs>TPVwh=+qqk*bz+{}rf zYC>SPd?J{d7{FAAE^WzBim5?jVe#g@ZcSM}#HgkQqHml)Av!ZPsJ^On30G5tYkw2x zQwUen0%w776>3-0g7gC8iVRVwTUSJg{J3>R#C&=p5FN%9Fegs=krYdU#A`u$^>c|# zVb8Q=uj2asZf#jU!f=-aq9(Q$px zGDLmBN+d$$7p+7hN-PFqnUP2giOa1-B1&8txYxuIHAKi)tVA+MTxBH^LE>sFkq8pk z1a>zggT%F6T0-JFCGohHD5cmKB=!{h9&(431#kj5%VM+iuMf(cI1epCR=r zOhbg+WzCVn+kbX~% z4|MBPaQ;tAm#}s!`1S8&Ydv7?bl{8&OGToGwsty5j|)phf(%j5SZhRxeAZecV&Hn6((lwv}dm|3{%bGJU<6C<1unpdnn(Ul3|c|VE0^@O(x;Xk*=-g?5@ z#L($5-g;_p6T@_e@kWNIlR{Hmi4b{mXtIrn-ll|Ns_{k)Z_|`Fy*P^&aD?lHY*f^VnMyouUTR3^`%Srnic+2Q|zl3e9cDbF}`|fU$evXQsavZQRi4+ zM2P&f^+iNqb3?Jv_#%d{MK;ffm}iSa_lj7eh6wqr%`-AcTw)~>LE`f^&xj!L1xnN> zT{2jFu}e!xEGmgJw8Y+0EDsYK3yZ&Sr{#NNh|5D$RC}W@%R^ICdqdpv&=l3)5Vs<9 z-ZbKRYjG>W^qWQ;8KSPV;)oFWmC&5xh$!yWP^>lLh#_vBO*A5vXzOjFk-^bxcBDjb z^cS0GL~!)FO*A4X+7LIaMWT_x(HqLqZ@Ct6xZE5jK0%)SJX2WJki>UeU%A)j`(Rj` zLvxJlgHCM@%`vVIWNi-3F|H3}Z3&%^jjTRe)|N2+v5`fFs9UWpB1C@6$|9nyw?nbR z$RdWUoi@vem}T#V?%+7fG(^bvY?hJ1;0M+q5e$B4vy2D^KcYdsn~_1`?k+81aE~(h zUo_Yk1u#r}TR42e{Y}0vMz}8&{o>`=7hTyG*8H$^32*zt>wXun&c5)rKXkq^-uh~9 z`@{4%#v2);9MnrFiLUF`+BZjx5)*BJM9ShCpPz@3Cxb;Q`Z(rKc6T#b8 z)*BJLouIcLvI>yF+t*!M!rMvZ?Ge2?t5E~P#G_Gp_1&35`+p~U7ABl@bNOlv_Ow-4 zjb5F$3ag>;v{hIQg=a!%d{io=)mq`1Fg-ph6;d)pJ!=&bA@Vt^kcbM~A~7;56;fg- zd>}G~l!yvPN2ZW!h>#CPrjU|B;lq(Bq(o3SCNhPT2nxqW_Prt*6h6|WB@~W}pzwaJ zu%8r@qQsoSW#78@{p_GS7Oefwy_qTMfL; zkDL|8TaETMKT5AK-pCMjf%Qg&$P2AEB6?dCiRX+rVt89(y%Evd3pU|2M93GdH!^rz zYDZ55Z!cMIMDX@RKy~2$9!WaYPiiJ`x*@IAVxc6`ro3}m!{cA0)gmMS3`qIO8Lp%WqUOldZBBIeGMQp}O1N=S^{d0LwF zMWoi(Txr%986?fKLnVTw`O>T}B1l?bB@w~V!nmPYUu2N9NJ%=Jq@+Poyebn%i@D0m z1LgTa7|yHGeD^&Foq1K7@4g2?(yP*Z_dN)bR^htrW%>v# zm4*sdhBt1`4%z3t&M*OYJ7uq0(=*(NY1pMEsZ(3^+p2eESZy@nHl^u3DL(3?2^5-k zclHV7g;J1(y)z05@ME%mH7!e|WWmAlZDRx4dpKTGU6#H6bj!rQ$eaCUOxA&ReY5M8zXJLVbg++(U6Ixaz(b~7pbJ|imU86 zQQ{nxlvR0=%D{pEiCY2r_>N~$&a_5lYHN(B(wZr}4b;H%lg8!g*tF59QEIjpux9mHW{~c4< zSXX)E`9f!7`1ZSX#e%8p(c>dC^1F))mG3SJ-stOnWGY{741O3z|5Wr<56?GhXyi>U zuY5oFb;++W{?JG@6{BKZ_HSPHu>Uu!4{NiBfAP!eL*MwVk^kFbTCC5W?6>b&e_NKq ze<+$_Q4$7ejaq(FjP02C4~Iqmq)6dO0iU#HTy56ENu{Vx21CTb43E@Tx+aYEbfoT* z@$szM9>yOLsXMwhA8ll$1{Hhd$ARb7^)PBwq{c*rt^+FLkIkOQ11@0_cxD0r%eYA2 z)%AIS@yAE%fv&0E_!A=ajjpL^{E3meziSGO|6I2h_B8(U*|UDf6HsT=l*nt3YMXvh zp0pPyp$_w&5~=2#xeiA&B^vlp^&w8el<2R1n{(EIb86&I2WJCML!CVhh~ac_+7n?T z&eya^{rLa2g7IIBRNQ5>(u~MoDrcuI12Jkw6fTvM!-j*L=}rz44s=$e{wzml%Fthm z)I33F1^WC9y`dOl0WcM6aLN`&!2`uo^^o&3@p2S=H3#K0aV8cyP$ry-#gV$V>$7ks zUU6rF&%&8l((Q#f6K&bEw$$)cD5F+Ip0~aH)c#;YNnwhsBGo&GSD4UxxnS{td?M2;D9uRA#=%Dou{ zU(e60jTmx+gJT2SCO3a3z`f<*m;kpqQg;{A2e_QrAh)I4D^1 zchy5~sK(x9ccFU7wQ7HiuI@thR<2ctV{~;BV#BDzv}{657cjmVnCS^+g)4IBk zcx>6SAE9L%VFSlVE!zkaI7VsNMwr0yjLtZy!32$GyFCjUqct=hCq|)Y)OhW^RGxk; zc&t>!VUO1;&DTv4hcaH9JE{+XF<#&ENRCki#suxp5{#n7n4rU1g29GSCpru!jQpI& zj%;^YCN87rwJPiCR?CcKG{q4yWkgdQ5gUl6IU*(yz33*-1fuDVhzUe9@)tH^TVaFI z%*^PgGzyKHqrDX`91nh63Ne>CTJBLHj%1FOdsGOaIa=;fA%x~?f4K;SR%oscmx~Y^ zMxEz`m@x8uC&Wad1zIf<&?`=e4MIzt5EF#joDdU)mO3FO2({-g90(yc z2rbKmme?D4Pi$k_+fn|<6T!=+o|w&Qt&)7%^u)2O*6D54hcH^L@BV(iih9DRqW$e+ z)YBSObhurN*f8oEXT*e&*J^p|z(k{UTD>kt%rJT*GqUd;n0PbVpo4qzn~{wea-){F z4s3vX%fT@LZnKuR4oraCqO%>)-i+8Fx7GPF0d89cchs zTq?q`?9#oyT73w(UHbkX~tE((xGLi(=h7LveRi89oPOysp3hclkn# zfp|mvW8>$H9a7 z6>1}f91+VE$_B(yvFwjbKzt^aE0hU{&&KZU0vixV$Lj0(p2-BnF)%94EzUKu(q5U?#=Q4^|&SZc_Z{uXDKsa+70!p~xjxZgLzh6gf7G`a&#k z7nm?|IhK1H6XmAFYP!fVLvDtXW1`%wICv_^~H*xfF6s zV}FClrB-ff9BvRfHjLWtGAGAGx#h81Epp6|t2j9(%B_v@iPC8u zTkq!21i9Co924YT@3Q9DAooVMS3>U1Om3Ck6^v1vWA9+Oxie@l8BB3=tg4@b431@U zJou3u&H!$6{MY}U!x_MBiTwithfOp4B)%mM4+tC^M&0V*m@x9TSl*N|5pH{|b_yIb z;C4AUCc?cN2j9%$Y{Zc7IXE`Jz3-;a1h@|z924O763%|0WCPqjcd;@7Zhr<>v2YDW z9g4lqxP0qUu&mU8IUb7D?KxEg4(3pN$B(KHA$KVL`G4nf4Ujt=`xiy7!O9(u!;2!v zhEb0=IVOyJ)X6bX?pUl&iX1cKPB}Ry%AJm7udoqAo^f()kUQt(m>~DDlVgJ1d0wpd zaj#&5+=Xthgxn{Y+>_j7dl_{(_J);@T?u|u>V+9zj#c#?TQ3~S<@ol$%-wpy?Q;CH z-{)?<;C3bUTa)Vc(961AiNn^Ux;?OA)T_>o2_s)~ZcKFhG*;KejTvq?GBDKUZQ78e(Vm>@JHv0F&?CYKFFLlY2TKQMk zf)SCviEIQ+ z82On*u1Y2vJ)5X;Np%ZlhSB&$wooRnt%*r+Uk+y@hI}rOEtCy#lk)jv`b>bEoX8f+ z1h^Lxw}rAnuH5aFfSZ!R&9ZQf_$Dy%+RA-C3#OGCF~u2)?4XS}mKllcppAf=k;o3( z2)LPvzeL~~E!@l`Tq1C677J?jIa_C(&E^#Rec#NQ-DeJs(kB-|uKY#4R9BVxkHD;yCMiB=|RjSw+| zXsugYOk7*9Cc)jgn~fN9y<1ysaC_akF~RK(x3-wz_9orFML0IVZRqw&xNXeb{+@1q zv9%@MACuaqpR|-q|6J%@{@3fl!~fP7bKR1t{`uwD7YDT^8Sw4uLkMn3e(g)@_ zt%-k71p8XStx0%L1lcg^HYdo0k++v8{wZiE?MT!vG2_3%Y_~IGqS#-kpy2QJbl#kvBMwa?vR)?Kc zKOD?qXVni@hn-bFSRG0HPO<7|t&SvNr&zIJ)T7Rd2_qkKtBr}Pts_yVM2;D9A2~TD z%AHAMm$VT>o^^6;ko(xpp9ym3og5S7E>P~@TMbVBH^thxHrFGZN!j6QrQgHK-ikf=P4!-4ohV- zU;^RrG}{d98x1xPKHcq=ARLi`@b|o6`x`Yn^=6eHy%qdNsXt~oI+eYkKMrMdDtkeH zxQ$L_FX#`qF{wXO-1=L$F=;qc+}JSc*i<%ACX75TmA!z8ZsSw+d|KT^nc+4ml}(h1 zZZD*=^lZeCW#`5Qx2bOSOmLg#+?e3@BHipaMQm`J-tCoen~}L~vrBIPzDrEKm6JcJ z-&7ia8O}}R_BH^AGB=gm+W@%DP387B0B-YAe}%XWux|6xaD}+BVbuA~jR_+!aBfU= zTbQcF;>HZOS28!dhcab*=#o_SP&N>?xrs7?XlW{YC=-aHcbA$mv9)fQHRG_>x@Fc3uC;ENHG^wi>c1mg z&6aCj8onc3Y#8-b$Hjz^*E=pIa=n(S4Z_6?u8nS)F>#r_mC8p?8!_Z&x6IgJxYZdl z!El>fW=t^LPDA^h5gQP9bbBQX-_8uL1iU^6;@h^=`xJ)9gO;*>s?b=u>DNEumj+_G z9S(6Ij;q5V4g_L{LmUXiYs<7s$J5ZN&535Uppkxx2ACL*3n)mcGg2I4t~ z$V9~R8KV8FH;?#lE;v~m@&A0{WZ59w>3o?#HgCIK; ze?nlYyT>3aJJf^|%2Vp=pU8g*XU;CbXN_EdY?$I`BlmVDOmU2n3y=vj9BbsaBqq#o zT(=iuhT{!pc)q|Hwiq?rc;4>H-l+a`ZK(zGnr-Bl@D?1*Y$Lyfw_skgjr3{Q)vls^GhqE=sRvU++{*xC=_vsiM`?VE$`N-`l%J4|Z!!<85+ecp^^2 zy6hx%d2ROhJg=IhNtp1ojA^}5Z+2lq1=EJEo=6%`+-THx^GgSc41gU*{j}@<41l){ zHZl8qWs8qz0pJ~j_XAxL0Cr~o#cX?zA8gbfBM diff --git a/module/services/frontend/code/packages/saas-sdk/generated/library.codefly.yaml b/module/services/frontend/code/packages/saas-sdk/generated/library.codefly.yaml index c71813471..96346ce8e 100644 --- a/module/services/frontend/code/packages/saas-sdk/generated/library.codefly.yaml +++ b/module/services/frontend/code/packages/saas-sdk/generated/library.codefly.yaml @@ -12,7 +12,7 @@ sources: module: saas-starter service: accounts endpoint: connect - contract-digest: sha256:606e52170c2e55688ce163eb1d54c347f0d19ac40915d7fb6252f2034b787c0e + contract-digest: sha256:7e1acbb32e08f5a5a41c5da10fb73b4436c4cb53c991af657d7d80a2648e862e services: - AccessibleScopeService - AuditService diff --git a/module/services/frontend/code/packages/saas-sdk/generated/typescript/src/gen/saas/accounts/v1/datasource_pb.ts b/module/services/frontend/code/packages/saas-sdk/generated/typescript/src/gen/saas/accounts/v1/datasource_pb.ts index 224ac5185..b74c9a599 100644 --- a/module/services/frontend/code/packages/saas-sdk/generated/typescript/src/gen/saas/accounts/v1/datasource_pb.ts +++ b/module/services/frontend/code/packages/saas-sdk/generated/typescript/src/gen/saas/accounts/v1/datasource_pb.ts @@ -18,7 +18,7 @@ import type { JsonObject, Message } from "@bufbuild/protobuf"; * Describes the file saas/accounts/v1/datasource.proto. */ export const file_saas_accounts_v1_datasource: GenFile = /*@__PURE__*/ - fileDesc("CiFzYWFzL2FjY291bnRzL3YxL2RhdGFzb3VyY2UucHJvdG8SEHNhYXMuYWNjb3VudHMudjEiXgoWR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIMCgRyZXBvGAEgASgJEg0KBXBhdGhzGAIgAygJEg4KBmJyYW5jaBgDIAEoCRIXCg9maWxlX2V4dGVuc2lvbnMYBCADKAki9AEKD0FwaU9BdXRoMkNvbmZpZxI2CgVncmFudBgEIAEoDjInLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnLkdyYW50EhEKCXRva2VuX3VybBgBIAEoCRIRCgljbGllbnRfaWQYAiABKAkSDgoGc2NvcGVzGAMgAygJInMKBUdyYW50EhUKEUdSQU5UX1VOU1BFQ0lGSUVEEAASFwoTR1JBTlRfUkVGUkVTSF9UT0tFThABEhwKGEdSQU5UX0NMSUVOVF9DUkVERU5USUFMUxACEhwKGEdSQU5UX0FVVEhPUklaQVRJT05fQ09ERRADIuoBChNBcGlEYXRhc291cmNlQ29uZmlnEhAKCGJhc2VfdXJsGAEgASgJEhUKDXJlc291cmNlX3BhdGgYAiABKAkSPAoPY3JlZGVudGlhbF9raW5kGAMgASgOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIZChFjcmVkZW50aWFsX2hlYWRlchgEIAEoCRIeChZjcmVkZW50aWFsX3F1ZXJ5X3BhcmFtGAUgASgJEjEKBm9hdXRoMhgGIAEoCzIhLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnIkEKF0NyYXdsZXJEYXRhc291cmNlQ29uZmlnEhMKC3NpdGVtYXBfdXJsGAEgASgJEhEKCW1heF9wYWdlcxgCIAEoDSKrAgoWVXBsb2FkRGF0YXNvdXJjZUNvbmZpZxIQCghlbmRwb2ludBgBIAEoCRIOCgZyZWdpb24YAiABKAkSDgoGYnVja2V0GAMgASgJEg4KBnByZWZpeBgEIAEoCRIVCg1hY2Nlc3Nfa2V5X2lkGAUgASgJEhMKC21heF9vYmplY3RzGAYgASgNEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACEkkKD2ZpbGVfZXh0ZW5zaW9ucxgJIAMoCUIwukgtkgEqECAiJnIkEAIYITIeXlwuW0EtWmEtejAtOV1bQS1aYS16MC05Ll8tXSokIoMHCgpEYXRhc291cmNlEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRI2Cghwcm92aWRlchgDIAEoDjIkLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyEjgKBmdpdGh1YhgFIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIyCgZzdGF0dXMYBiABKA4yIi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTdGF0dXMSGgoSd2ViaG9va19jb25maWd1cmVkGAcgASgIEi4KCmNyZWF0ZWRfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDmxhc3Rfc3luY2VkX2F0GAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgNhcGkYCyABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWcSOgoHY3Jhd2xlchgMIAEoCzIpLnNhYXMuYWNjb3VudHMudjEuQ3Jhd2xlckRhdGFzb3VyY2VDb25maWcSOAoGdXBsb2FkGA0gASgLMiguc2Fhcy5hY2NvdW50cy52MS5VcGxvYWREYXRhc291cmNlQ29uZmlnEhgKEGJvdW5kYXJ5X25vZGVfaWQYDiABKAkSNAoQbGFzdF9pbmdlc3RlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHAoUbGFzdF9pbmdlc3RlZF9jb21taXQYECABKAkSFQoNc3RhdHVzX3JlYXNvbhgRIAEoCRIWCg5ib3VuZGFyeV9sYWJlbBgSIAEoCRISCgpjb25mb3JtYW50GBMgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgUIAEoCRI/Cg1saXZlX2RlbGl2ZXJ5GBUgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlTGl2ZURlbGl2ZXJ5EjUKEnJlY29uY2lsZV9pbnRlcnZhbBgWIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkoECAQQBVIRdGFyZ2V0X2NvbGxlY3Rpb24isgMKFkFkZEdpdEh1YlNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI7CgRyZXBvGAIgASgJQi26SCpyKBADGP8BMiFeW0EtWmEtejAtOV8uLV0rL1tBLVphLXowLTlfLi1dKyQSIAoFcGF0aHMYAyADKAlCEbpIDpIBCxBAIgdyBRABGIAEEhgKBmJyYW5jaBgEIAEoCUIIukgFcgMY/wESJAoQYm91bmRhcnlfbm9kZV9pZBgIIAEoCUIIukgFcgOwAQFIABImChBjb2xsZWN0aW9uX2xhYmVsGAkgASgJQgq6SAdyBRABGP8BSAASHgoMYWNjZXNzX3Rva2VuGAYgASgJQgi6SAVyAxiACBIgCg53ZWJob29rX3NlY3JldBgHIAEoCUIIukgFcgMYgAgSSQoPZmlsZV9leHRlbnNpb25zGAogAygJQjC6SC2SASoQICImciQQAhghMh5eXC5bQS1aYS16MC05XVtBLVphLXowLTkuXy1dKiRCEQoIYm91bmRhcnkSBbpIAggBSgQIBRAGUhF0YXJnZXRfY29sbGVjdGlvbiJLChdBZGRHaXRIdWJTb3VyY2VSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsgEChBBZGRTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESQgoIcHJvdmlkZXIYAiABKA4yJC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VQcm92aWRlckIKukgHggEEEAEgABI6CgZnaXRodWIYBCABKAsyKC5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkRhdGFzb3VyY2VDb25maWdIABI0CgNhcGkYBSABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWdIABI8CgdjcmF3bGVyGAggASgLMikuc2Fhcy5hY2NvdW50cy52MS5DcmF3bGVyRGF0YXNvdXJjZUNvbmZpZ0gAEjoKBnVwbG9hZBgJIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuVXBsb2FkRGF0YXNvdXJjZUNvbmZpZ0gAEiQKEGJvdW5kYXJ5X25vZGVfaWQYDCABKAlCCLpIBXIDsAEBSAESJgoQY29sbGVjdGlvbl9sYWJlbBgNIAEoCUIKukgHcgUQARj/AUgBEhwKCmNyZWRlbnRpYWwYBiABKAlCCLpIBXIDGIAgEiAKDndlYmhvb2tfc2VjcmV0GAcgASgJQgi6SAVyAxiACBImChRvYXV0aDJfY2xpZW50X3NlY3JldBgKIAEoCUIIukgFcgMYgAhCCAoGY29uZmlnQhEKCGJvdW5kYXJ5EgW6SAIIAUoECAMQBFIRdGFyZ2V0X2NvbGxlY3Rpb24iRQoRQWRkU291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSLkAgoTVXBkYXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIYCgZicmFuY2gYAyABKAlCCLpIBXIDGP8BEiAKBXBhdGhzGAQgAygJQhG6SA6SAQsQQCIHcgUQARiABBJJCg9maWxlX2V4dGVuc2lvbnMYBSADKAlCMLpILZIBKhAgIiZyJBACGCEyHl5cLltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJBI8CghleHBlY3RlZBgGIAEoCzIiLnNhYXMuYWNjb3VudHMudjEuU291cmNlRmV0Y2hTY29wZUIGukgDyAEBEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACIs8BChBTb3VyY2VGZXRjaFNjb3BlEhgKBmJyYW5jaBgBIAEoCUIIukgFcgMY/wESIAoFcGF0aHMYAiADKAlCEbpIDpIBCxBAIgdyBRABGIAEEikKD2ZpbGVfZXh0ZW5zaW9ucxgDIAMoCUIQukgNkgEKECAiBnIEEAEYIRIpChBpbmNsdWRlX3BhdHRlcm5zGAQgAygJQg+6SAySAQkQECIFcgMYgAISKQoQZXhjbHVkZV9wYXR0ZXJucxgFIAMoCUIPukgMkgEJEBAiBXIDGIACIlgKFFVwZGF0ZVNvdXJjZVJlc3BvbnNlEjAKCmRhdGFzb3VyY2UYASABKAsyHC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2USDgoGam9iX2lkGAIgASgJIloKFURhdGFzb3VyY2VDb25maWdGaWVsZBILCgNrZXkYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEgwKBGhlbHAYAyABKAkSEAoIcmVxdWlyZWQYBCABKAgixAEKGURhdGFzb3VyY2VDb25uZWN0b3JCdWRnZXQSGgoSbWF4X2l0ZW1zX3Blcl9jYWxsGAEgASgNEhoKEm1heF9ieXRlc19wZXJfY2FsbBgCIAEoAxIWCg5tYXhfaXRlbV9ieXRlcxgDIAEoAxIdChVvcGVyYXRpb25zX3Blcl93aW5kb3cYBCABKA0SFgoOd2luZG93X3NlY29uZHMYBSABKAMSIAoYYmFja2dyb3VuZF9zaGFyZV9wZXJjZW50GAYgASgNIqoGChxEYXRhc291cmNlUHJvdmlkZXJEZXNjcmlwdG9yEjYKCHByb3ZpZGVyGAEgASgOMiQuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUHJvdmlkZXISFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEj4KDWNvbmZpZ19maWVsZHMYBCADKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDb25maWdGaWVsZBIYChBzdXBwb3J0c193ZWJob29rGAUgASgIEkcKGnN1cHBvcnRlZF9jcmVkZW50aWFsX2tpbmRzGAYgAygOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIRCgljb25uZWN0b3IYByABKAkSQQoJaW50ZXJmYWNlGAggASgOMi4uc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQ29ubmVjdG9ySW50ZXJmYWNlEkQKEGNyZWRlbnRpYWxfbW9kZXMYCSADKA4yKi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRI/Cg1yZWFkZXJzX21vZGVsGAogASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUmVhZGVyc01vZGVsEjsKBmJ1ZGdldBgLIAEoCzIrLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUNvbm5lY3RvckJ1ZGdldBISCgpjb25mb3JtYW50GAwgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgNIAEoCRIbChNhY2NlcHRzX25ld19zb3VyY2VzGA4gASgIEiAKGGxpdmVfZGVsaXZlcnlfY29uZmlndXJlZBgPIAEoCBIaChJhY2NlcHRzX29wZXJhdGlvbnMYECABKAgSFgoOb3BlcmF0aW9uc19nYXAYESABKAkSGwoTb2F1dGhfYXV0aG9yaXplX3VybBgSIAEoCRIXCg9vYXV0aF90b2tlbl91cmwYEyABKAkSFAoMb2F1dGhfc2NvcGVzGBQgAygJIh0KG0dldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdCJhChxHZXREYXRhc291cmNlQ2F0YWxvZ1Jlc3BvbnNlEkEKCXByb3ZpZGVycxgBIAMoCzIuLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyRGVzY3JpcHRvciIuChJMaXN0U291cmNlc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJIChNMaXN0U291cmNlc1Jlc3BvbnNlEjEKC2RhdGFzb3VyY2VzGAEgAygLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIkIKEEdldFNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiRQoRR2V0U291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSJ2ChFTeW5jU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIeCgxhY2Nlc3NfdG9rZW4YAyABKAlCCLpIBXIDGIAgEhEKCXJlY29ubmVjdBgEIAEoCCIkChJTeW5jU291cmNlUmVzcG9uc2USDgoGam9iX2lkGAEgASgJImoKFEdldFNvdXJjZVN5bmNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgZqb2JfaWQYAyABKAlCC7pICNgBAXIDsAEBIpUBChJTb3VyY2VTeW5jRGVsaXZlcnkSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARItCgVzdGF0ZRgCIAEoDjIWLnNhYXMuam9icy52MS5Kb2JTdGF0ZUIGukgDyAEBEjYKCWV4ZWN1dGlvbhgDIAEoCzIjLnNhYXMuam9icy52MS5Kb2JFeGVjdXRpb25SZWZlcmVuY2UiiwEKEVNvdXJjZVN5bmNDaGFuZ2VzEg0KBWZpbGVzGAEgASgNEg0KBWFkZGVkGAIgASgNEhAKCG1vZGlmaWVkGAMgASgNEg8KB2RlbGV0ZWQYBCABKA0SEwoLc3BsaXRfa25vd24YBSABKAgSEAoIc25hcHNob3QYBiABKAgSDgoGY29tbWl0GAcgASgJIq0BChFTb3VyY2VTeW5jRmFpbHVyZRI5CgZyZWFzb24YASABKA4yKS5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNGYWlsdXJlUmVhc29uEgwKBGNvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCRIQCghyZXRyeWluZxgEIAEoCBIsCghyZXRyeV9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAQKElNvdXJjZVN5bmNQcm9ncmVzcxIwCgVwaGFzZRgBIAEoDjIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY1BoYXNlEjQKB3RyaWdnZXIYAiABKA4yIy5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNUcmlnZ2VyEi0KCXF1ZXVlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoLZmV0Y2hpbmdfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi8KC2NvbXBpbGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1oYW5kZWRfb2ZmX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIvCgtmaW5pc2hlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoHY2hhbmdlcxgIIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0NoYW5nZXMSNAoHZmFpbHVyZRgJIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0ZhaWx1cmUSDwoHYXR0ZW1wdBgKIAEoDRIUCgxtYXhfYXR0ZW1wdHMYCyABKA0i0gEKFUdldFNvdXJjZVN5bmNSZXNwb25zZRIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBEi0KBXN0YXRlGAIgASgOMhYuc2Fhcy5qb2JzLnYxLkpvYlN0YXRlQga6SAPIAQESOAoKZGVsaXZlcmllcxgDIAMoCzIkLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0RlbGl2ZXJ5EjYKCHByb2dyZXNzGAQgASgLMiQuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VTeW5jUHJvZ3Jlc3MiRQoTRGVsZXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASIWChREZWxldGVTb3VyY2VSZXNwb25zZSJWChNHaXRIdWJBcHBSZXBvc2l0b3J5EgwKBHJlcG8YASABKAkSFgoOZGVmYXVsdF9icmFuY2gYAiABKAkSGQoRYWxyZWFkeV9jb25uZWN0ZWQYAyABKAgiNgoaQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJxChtCZWdpbkdpdEh1YkFwcFNldHVwUmVzcG9uc2USEwoLaW5zdGFsbF91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAinAEKHUNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEY/wESLAoPaW5zdGFsbGF0aW9uX2lkGAMgASgJQhO6SBByDhABGCAyCF5bMC05XSskEhgKBGNvZGUYBCABKAlCCrpIB3IFEAEY/wEidgoeQ29tcGxldGVHaXRIdWJBcHBTZXR1cFJlc3BvbnNlEhcKD2luc3RhbGxhdGlvbl9pZBgBIAEoCRI7CgxyZXBvc2l0b3JpZXMYAiADKAsyJS5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkFwcFJlcG9zaXRvcnkiUQofTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASJUCiBNaWdyYXRlR2l0SHViU291cmNlVG9BcHBSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsQBChVEYXRhc291cmNlQWNjb3VudExpbmsSCgoCaWQYASABKAkSDgoGb3JnX2lkGAIgASgJEg8KB3VzZXJfaWQYAyABKAkSEQoJY29ubmVjdG9yGAQgASgJEhsKE3Byb3ZpZGVyX2FjY291bnRfaWQYBSABKAkSHgoWcHJvdmlkZXJfYWNjb3VudF9sb2dpbhgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK3AQoWRGF0YXNvdXJjZUdyb3VwQmluZGluZxIKCgJpZBgBIAEoCRIOCgZvcmdfaWQYAiABKAkSEQoJY29ubmVjdG9yGAMgASgJEhkKEXByb3ZpZGVyX2dyb3VwX2lkGAQgASgJEg8KB3RlYW1faWQYBSABKAkSEgoKY3JlYXRlZF9ieRgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKUAgoYRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRIOCgZkb21haW4YAyABKAkSOAoGc3RhdHVzGAQgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRG9tYWluU3RhdHVzEhcKD3R4dF9yZWNvcmRfbmFtZRgFIAEoCRIYChB0eHRfcmVjb3JkX3ZhbHVlGAYgASgJEi8KC3ZlcmlmaWVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjcmVhdGVkX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIzChdEYXRhc291cmNlRGlyZWN0b3J5VGVhbRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJIqYBCiFCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIeCgxyZWRpcmVjdF91cmkYAyABKAlCCLpIBXIDGIAQEhEKCXNvdXJjZV9pZBgEIAEoCSJ6CiJCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEhUKDWF1dGhvcml6ZV91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAidQokQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEYgEASGAoEY29kZRgDIAEoCUIKukgHcgUQARj/ASJeCiVDb21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEjUKBGxpbmsYASABKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VBY2NvdW50TGluayI/CiNMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBIl4KJExpc3RNeURhdGFzb3VyY2VBY2NvdW50TGlua3NSZXNwb25zZRI2CgVsaW5rcxgBIAMoCzInLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUFjY291bnRMaW5rIlQKIkRlbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiJQojRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rUmVzcG9uc2UiOQodR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASKLAgoeR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlEjYKBWxpbmtzGAEgAygLMicuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQWNjb3VudExpbmsSOgoIYmluZGluZ3MYAiADKAsyKC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VHcm91cEJpbmRpbmcSOwoHZG9tYWlucxgDIAMoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEjgKBXRlYW1zGAQgAygLMikuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRGlyZWN0b3J5VGVhbSKuAQoaQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIlChFwcm92aWRlcl9ncm91cF9pZBgDIAEoCUIKukgHcgUQARj/ARIZCgd0ZWFtX2lkGAQgASgJQgi6SAVyA7ABASJYChtCaW5kRGF0YXNvdXJjZUdyb3VwUmVzcG9uc2USOQoHYmluZGluZxgBIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUdyb3VwQmluZGluZyJOChxVbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIh8KHVVuYmluZERhdGFzb3VyY2VHcm91cFJlc3BvbnNlIlQKHENsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIaCgZkb21haW4YAiABKAlCCrpIB3IFEAMY/QEiWwodQ2xhaW1EYXRhc291cmNlRG9tYWluUmVzcG9uc2USOgoGZG9tYWluGAEgASgLMiouc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlVmVyaWZpZWREb21haW4iTwodVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiXAoeVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlEjoKBmRvbWFpbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluIk8KHURlbGV0ZURhdGFzb3VyY2VEb21haW5SZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIiAKHkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSKeAgoQU291cmNlRGVsZWdhdGlvbhIKCgJpZBgBIAEoCRIRCglzb3VyY2VfaWQYAiABKAkSFAoMcHJpbmNpcGFsX2lkGAMgASgJEg4KBm1vZHVsZRgEIAEoCRIPCgdiaW5kaW5nGAUgASgJEi4KCmNyZWF0ZWRfYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnJldm9rZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEkAKCnJldm9jYXRpb24YCCABKA4yLC5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb25SZXZvY2F0aW9uEhIKCnJldm9rZWRfYnkYCSABKAkigQEKHExpc3RTb3VyY2VEZWxlZ2F0aW9uc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIgCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBSACIAQESFwoPaW5jbHVkZV9yZXZva2VkGAMgASgIQgwKCl9zb3VyY2VfaWQiWAodTGlzdFNvdXJjZURlbGVnYXRpb25zUmVzcG9uc2USNwoLZGVsZWdhdGlvbnMYASADKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iTwodUmV2b2tlU291cmNlRGVsZWdhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiWAoeUmV2b2tlU291cmNlRGVsZWdhdGlvblJlc3BvbnNlEjYKCmRlbGVnYXRpb24YASABKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iMgoPVHJpZ2dlcklkZW50aXR5Eg4KBnNvdXJjZRgBIAEoCRIPCgdiaW5kaW5nGAIgASgJIoQBChdEZWNsYXJlZFRyaWdnZXJTY2hlZHVsZRIMCgRjcm9uGAEgASgJEhAKCHRpbWV6b25lGAIgASgJEhIKCm1pc3NlZF9ydW4YAyABKAkSDwoHb3ZlcmxhcBgEIAEoCRIQCghkZWFkbGluZRgFIAEoAxISCgppbnB1dF9qc29uGAYgASgJIucCChpUcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRIRCglyZWZlcmVuY2UYASABKAkSFQoNZGVsZWdhdGlvbl9pZBgCIAEoCRIOCgZtb2R1bGUYAyABKAkSDwoHYmluZGluZxgEIAEoCRIQCghhdWRpZW5jZRgFIAEoCRIOCgZ0ZW5hbnQYBiABKAkSGgoSb3duZXJfcHJpbmNpcGFsX2lkGAcgASgJEg4KBnNjb3BlcxgIIAMoCRIOCgZhY3RpdmUYCSABKAgSLgoKY3JlYXRlZF9hdBgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKcmV2b2tlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASQAoKcmV2b2NhdGlvbhgMIAEoDjIsLnNhYXMuYWNjb3VudHMudjEuU291cmNlRGVsZWdhdGlvblJldm9jYXRpb24ivgEKE1RyaWdnZXJDaGlsZENvbnRleHQSFQoNZGVsZWdhdGlvbl9pZBgBIAEoCRIOCgZtb2R1bGUYAiABKAkSDwoHYmluZGluZxgDIAEoCRIQCghhdWRpZW5jZRgEIAEoCRIOCgZzY29wZXMYBSADKAkSDgoGbG9va3VwGAYgASgIEi0KCW1pbnRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGcmVjb3JkGAggASgJIs0CChhTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb24SDwoHcmVsZWFzZRgBIAEoCRIRCglvcGVyYXRpb24YAiABKAkSOwoIc2NoZWR1bGUYAyABKAsyKS5zYWFzLmFjY291bnRzLnYxLkRlY2xhcmVkVHJpZ2dlclNjaGVkdWxlEjMKCGlkZW50aXR5GAQgASgLMiEuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VySWRlbnRpdHkSDgoGZGlnZXN0GAUgASgJEjYKEmxhc3Rfb2NjdXJyZW5jZV9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNgoSbmV4dF9vY2N1cnJlbmNlX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChN1bmRlY2xhcmFibGVfcmVhc29uGAggASgJIlYKHURlbGVnYXRlU291cmNlVHJpZ2dlcnNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABASJjCh5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVzcG9uc2USQQoLZGVsZWdhdGlvbnMYASADKAsyLC5zYWFzLmFjY291bnRzLnYxLlRyaWdnZXJEZWxlZ2F0aW9uUmVmZXJlbmNlIlsKIkdldFNvdXJjZVRyaWdnZXJEZWNsYXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBIuIBCiNHZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZRI/CgtkZWNsYXJhdGlvbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuU291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEkEKC2RlbGVnYXRpb25zGAIgAygLMiwuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRI3CghjaGlsZHJlbhgDIAMoCzIlLnNhYXMuYWNjb3VudHMudjEuVHJpZ2dlckNoaWxkQ29udGV4dCJuChZSZWNvbmNpbGVTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIdCgllZmZlY3RfaWQYAyABKAlCCrpIB3IFEAEYgAEiTAoXUmVjb25jaWxlU291cmNlUmVzcG9uc2USEQoJZWZmZWN0X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIOCgZqb2JfaWQYAyABKAkiPQocTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBIdCgllZmZlY3RfaWQYASABKAlCCrpIB3IFEAEYgAEi8QIKD1NvdXJjZU9wZXJhdGlvbhIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg4KBm1ldGhvZBgDIAEoCRIMCgRwYXRoGAQgASgJEg0KBXF1ZXJ5GAUgAygJEi0KDGlucHV0X3NjaGVtYRgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSLgoNb3V0cHV0X3NjaGVtYRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSOAoGZWZmZWN0GAggASgOMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24uRWZmZWN0EhgKEG1heF9vdXRwdXRfYnl0ZXMYCSABKA0SDgoGZGlnZXN0GAogASgJIksKBkVmZmVjdBIWChJFRkZFQ1RfVU5TUEVDSUZJRUQQABIUChBFRkZFQ1RfUkVBRF9PTkxZEAESEwoPRUZGRUNUX01VVEFUSU9OEAIijgEKHkRlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQESNQoKb3BlcmF0aW9ucxgDIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlgKH0RlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVzcG9uc2USNQoKb3BlcmF0aW9ucxgBIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlQKG0xpc3RTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQEiVQocTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXNwb25zZRI1CgpvcGVyYXRpb25zGAEgAygLMiEuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24irgIKHEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBEjAKCW9wZXJhdGlvbhgDIAEoCUIdukgachgyFl5bYS16XVthLXowLTlfXXswLDYzfSQSHQoKaW5wdXRfanNvbhgEIAEoCUIJukgGcgQogIAEEhsKCWVmZmVjdF9pZBgFIAEoCUIIukgFcgMogAESSQobZXhwZWN0ZWRfZGVjbGFyYXRpb25fZGlnZXN0GAYgASgJQh+6SBxyGjIYXihzaGEyNTY6WzAtOWEtZl17NjR9KT8kSACIAQFCHgocX2V4cGVjdGVkX2RlY2xhcmF0aW9uX2RpZ2VzdCJ/ChZTb3VyY2VPcGVyYXRpb25SZWNlaXB0EhEKCWVmZmVjdF9pZBgBIAEoCRIUCgxjb21taXR0ZWRfYXQYAiABKAkSDgoGc3RhdHVzGAMgASgJEhcKD3Byb3ZpZGVyX3N0YXR1cxgEIAEoDRITCgtvdXRwdXRfanNvbhgFIAEoCSJvCh1JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZRITCgtvdXRwdXRfanNvbhgBIAEoCRI5CgdyZWNlaXB0GAIgASgLMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb25SZWNlaXB0IkMKIkxvb2t1cEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSHQoJZWZmZWN0X2lkGAEgASgJQgq6SAdyBRABKIABInkKI1BydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgllZmZlY3RfaWQYAyABKAlCCLpIBXIDKIABIlsKJFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZRIRCgllZmZlY3RfaWQYASABKAkSEAoIcmVjZWlwdHMYAiABKAMSDgoGc3RhdHVzGAMgASgJIkoKKUxvb2t1cFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0Eh0KCWVmZmVjdF9pZBgBIAEoCUIKukgHcgUQASiAASq3AQoSRGF0YXNvdXJjZVByb3ZpZGVyEiMKH0RBVEFTT1VSQ0VfUFJPVklERVJfVU5TUEVDSUZJRUQQABIeChpEQVRBU09VUkNFX1BST1ZJREVSX0dJVEhVQhABEhsKF0RBVEFTT1VSQ0VfUFJPVklERVJfQVBJEAISHwobREFUQVNPVVJDRV9QUk9WSURFUl9DUkFXTEVSEAMSHgoaREFUQVNPVVJDRV9QUk9WSURFUl9VUExPQUQQBCqRAQoQRGF0YXNvdXJjZVN0YXR1cxIhCh1EQVRBU09VUkNFX1NUQVRVU19VTlNQRUNJRklFRBAAEhwKGERBVEFTT1VSQ0VfU1RBVFVTX0FDVElWRRABEhwKGERBVEFTT1VSQ0VfU1RBVFVTX1BBVVNFRBACEh4KGkRBVEFTT1VSQ0VfU1RBVFVTX0RFR1JBREVEEAMqvAEKFkRhdGFzb3VyY2VMaXZlRGVsaXZlcnkSKAokREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX1VOU1BFQ0lGSUVEEAASIQodREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX05PTkUQARIrCidEQVRBU09VUkNFX0xJVkVfREVMSVZFUllfU09VUkNFX1dFQkhPT0sQAhIoCiREQVRBU09VUkNFX0xJVkVfREVMSVZFUllfQVBQX1dFQkhPT0sQAyrWAQoRQXBpQ3JlZGVudGlhbEtpbmQSIwofQVBJX0NSRURFTlRJQUxfS0lORF9VTlNQRUNJRklFRBAAEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfQkVBUkVSEAESHQoZQVBJX0NSRURFTlRJQUxfS0lORF9CQVNJQxACEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfSEVBREVSEAMSHQoZQVBJX0NSRURFTlRJQUxfS0lORF9RVUVSWRAEEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfT0FVVEgyEAUqpgIKHERhdGFzb3VyY2VDb25uZWN0b3JJbnRlcmZhY2USLgoqREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1VOU1BFQ0lGSUVEEAASKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX0ZJTEVTEAESKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1BBR0VTEAISKgomREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1JFQ09SRFMQAxIrCidEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfTUVTU0FHRVMQBBIpCiVEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfRVZFTlRTEAUq7AEKGERhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRIqCiZEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9VTlNQRUNJRklFRBAAEiMKH0RBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX05PTkUQARImCiJEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9PUkdfQVBQEAISKQolREFUQVNPVVJDRV9DUkVERU5USUFMX01PREVfVVNFUl9PQVVUSBADEiwKKERBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX1NUQVRJQ19TRUNSRVQQBCqXAQoWRGF0YXNvdXJjZVJlYWRlcnNNb2RlbBIoCiREQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfVU5TUEVDSUZJRUQQABIqCiZEQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfU09VUkNFX1NDT1BFRBABEicKI0RBVEFTT1VSQ0VfUkVBREVSU19NT0RFTF9UUkFOU0xBVEVEEAIq7gEKD1NvdXJjZVN5bmNQaGFzZRIhCh1TT1VSQ0VfU1lOQ19QSEFTRV9VTlNQRUNJRklFRBAAEhwKGFNPVVJDRV9TWU5DX1BIQVNFX1FVRVVFRBABEh4KGlNPVVJDRV9TWU5DX1BIQVNFX0ZFVENISU5HEAISHgoaU09VUkNFX1NZTkNfUEhBU0VfQ09NUElMRUQQAxIgChxTT1VSQ0VfU1lOQ19QSEFTRV9IQU5ERURfT0ZGEAQSGgoWU09VUkNFX1NZTkNfUEhBU0VfRE9ORRAFEhwKGFNPVVJDRV9TWU5DX1BIQVNFX0ZBSUxFRBAGKqYDChdTb3VyY2VTeW5jRmFpbHVyZVJlYXNvbhIqCiZTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEisKJ1NPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX1JBVEVfTElNSVRFRBABEikKJVNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX0NSRURFTlRJQUwQAhIsCihTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9BQ0NFU1NfREVOSUVEEAMSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fTk9UX0ZPVU5EEAQSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fVE9PX0xBUkdFEAUSLworU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fSE9TVF9VTkFWQUlMQUJMRRAGEiQKIFNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX09USEVSEAcSLgoqU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fREVMSVZFUllfRkFJTEVEEAgqwgEKEVNvdXJjZVN5bmNUcmlnZ2VyEiMKH1NPVVJDRV9TWU5DX1RSSUdHRVJfVU5TUEVDSUZJRUQQABIeChpTT1VSQ0VfU1lOQ19UUklHR0VSX01BTlVBTBABEiEKHVNPVVJDRV9TWU5DX1RSSUdHRVJfU0NIRURVTEVEEAISHwobU09VUkNFX1NZTkNfVFJJR0dFUl9XRUJIT09LEAMSJAogU09VUkNFX1NZTkNfVFJJR0dFUl9SRUNPTkZJR1VSRUQQBCqPAQoWRGF0YXNvdXJjZURvbWFpblN0YXR1cxIoCiREQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIkCiBEQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfUEVORElORxABEiUKIURBVEFTT1VSQ0VfRE9NQUlOX1NUQVRVU19WRVJJRklFRBACKpUDChpTb3VyY2VEZWxlZ2F0aW9uUmV2b2NhdGlvbhIsCihTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VOU1BFQ0lGSUVEEAASKAokU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVZPS0VEEAESKQolU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVBMQUNFRBACEi8KK1NPVVJDRV9ERUxFR0FUSU9OX1JFVk9DQVRJT05fU09VUkNFX0RFTEVURUQQAxIvCitTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX01FTUJFUl9SRU1PVkVEEAQSMAosU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9QRVJNSVNTSU9OX0xPU1QQBRIuCipTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VTRVJfSU5BQ1RJVkUQBhIwCixTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX0JJTkRJTkdfQ0hBTkdFRBAHMrE5ChFEYXRhc291cmNlU2VydmljZRK5AwocUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI1LnNhYXMuYWNjb3VudHMudjEuUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSKpAsLzGGwIAhADGhFkYXRhc291cmNlOmludm9rZSIRZGF0YXNvdXJjZTppbnZva2UqDwoJc291cmNlX2lkEAQYAzABOiMKH3NhYXMuZGF0YXNvdXJjZS5yZWNlaXB0cy5wcnVuZWQQAkADSARQA1gDYAHa8xi0AQoCCDwSAwjYBBgFIgIIAioLVU5BVkFJTEFCTEUqElJFU09VUkNFX0VYSEFVU1RFRCoHQUJPUlRFRDIPc2Fhcy1kYXRhc291cmNlSkYvc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlU2VydmljZS9Mb29rdXBQcnVuZVNvdXJjZU9wZXJhdGlvblJlY2VpcHRzUIAgWIAgYAFyGAoGc291cmNlEgZpbnZva2USBHJlYWQYARLmAQoiTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI7LnNhYXMuYWNjb3VudHMudjEuTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSJLwvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUANYA2ABEvwDChVJbnZva2VTb3VyY2VPcGVyYXRpb24SLi5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlc3BvbnNlIoEDwvMYbggCEAMaEWRhdGFzb3VyY2U6aW52b2tlIhFkYXRhc291cmNlOmludm9rZSoPCglzb3VyY2VfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEARAA0gEUARYBGAB2vMYrwEKAgg8EgMI2AQYBSICCAIqC1VOQVZBSUxBQkxFKhJSRVNPVVJDRV9FWEhBVVNURUQqB0FCT1JURUQyD3NhYXMtZGF0YXNvdXJjZUo/L3NhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVNlcnZpY2UvTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uUICABFiAgEBgAXIYCgZzb3VyY2USBmludm9rZRIEcmVhZBgBgtPkkwJVOgEqIlAvdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zL3tvcGVyYXRpb259Omludm9rZRKHAgobTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5Mb29rdXBJbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKAAcLzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ADWARgAYLT5JMCLxItL3YxL2RhdGFzb3VyY2Utb3BlcmF0aW9uLXJlY2VpcHRzL3tlZmZlY3RfaWR9EoUCChRMaXN0U291cmNlT3BlcmF0aW9ucxItLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0Gi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIo0BwvMYRAgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKgwKBm9yZ19pZBACGAEwAToCEAFAAUgDUANYA2ABgtPkkwI/Ej0vdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zEpMCChdEZWNsYXJlU291cmNlT3BlcmF0aW9ucxIwLnNhYXMuYWNjb3VudHMudjEuRGVjbGFyZVNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0GjEuc2Fhcy5hY2NvdW50cy52MS5EZWNsYXJlU291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIpIBwvMYRggCEAQqDAoGb3JnX2lkEAIYATABOiYKInNhYXMuZGF0YXNvdXJjZS5vcGVyYXRpb24uZGVjbGFyZWQQAkABSARQA1gDYAGC0+STAkI6ASoiPS92MS9vcmdhbml6YXRpb25zL3tvcmdfaWR9L2RhdGFzb3VyY2VzL3tzb3VyY2VfaWR9L29wZXJhdGlvbnMSrAEKD0FkZEdpdEh1YlNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVzcG9uc2UiRMLzGEAIAhAEKgwKBm9yZ19pZBACGAEwATogChxzYWFzLmRhdGFzb3VyY2Uuc291cmNlLmFkZGVkEAJAAUgEUARYA2ABEpoBCglBZGRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlc3BvbnNlIkTC8xhACAIQBCoMCgZvcmdfaWQQAhgBMAE6IAocc2Fhcy5kYXRhc291cmNlLnNvdXJjZS5hZGRlZBACQAFIBFAEWANgARKlAQoMVXBkYXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UudXBkYXRlZBACQAFIBFACWANgARKPAQoUR2V0RGF0YXNvdXJjZUNhdGFsb2cSLS5zYWFzLmFjY291bnRzLnYxLkdldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdBouLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZUNhdGFsb2dSZXNwb25zZSIYwvMYFAgCEAEwAToCEAFAAUgDUAJYAmABEoIBCgtMaXN0U291cmNlcxIkLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZXNSZXF1ZXN0GiUuc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARJ8CglHZXRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKeAQoKU3luY1NvdXJjZRIjLnNhYXMuYWNjb3VudHMudjEuU3luY1NvdXJjZVJlcXVlc3QaJC5zYWFzLmFjY291bnRzLnYxLlN5bmNTb3VyY2VSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5zb3VyY2Uuc3luY2VkEAJAAUgEUARYAmABEogBCg1HZXRTb3VyY2VTeW5jEiYuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VTeW5jUmVxdWVzdBonLnNhYXMuYWNjb3VudHMudjEuR2V0U291cmNlU3luY1Jlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKlAQoMRGVsZXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UucmVtb3ZlZBACQAFIBFACWAJgARLEAQoTQmVnaW5HaXRIdWJBcHBTZXR1cBIsLnNhYXMuYWNjb3VudHMudjEuQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJlZ2luR2l0SHViQXBwU2V0dXBSZXNwb25zZSJQwvMYTAgCEAQqDAoGb3JnX2lkEAIYATABOiwKKHNhYXMuZGF0YXNvdXJjZS5naXRodWJfYXBwLnNldHVwX3N0YXJ0ZWQQAkABSARQAlgEYAESzwEKFkNvbXBsZXRlR2l0SHViQXBwU2V0dXASLy5zYWFzLmFjY291bnRzLnYxLkNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZUdpdEh1YkFwcFNldHVwUmVzcG9uc2UiUsLzGE4IAhAEKgwKBm9yZ19pZBACGAEwATouCipzYWFzLmRhdGFzb3VyY2UuZ2l0aHViX2FwcC5zZXR1cF9jb21wbGV0ZWQQAkABSARQBFgDYAESzQEKGE1pZ3JhdGVHaXRIdWJTb3VyY2VUb0FwcBIxLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBoyLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuY3JlZGVudGlhbC51cGRhdGVkEAJAAUgEUAJYA2ABEtUBChpCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGluaxIzLnNhYXMuYWNjb3VudHMudjEuQmVnaW5EYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjQuc2Fhcy5hY2NvdW50cy52MS5CZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkzC8xhICAIQAyoMCgZvcmdfaWQQAhgBMAE6KAokc2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua19zdGFydGVkEAJAAUgEUAJYBGABEtgBCh1Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGluaxI2LnNhYXMuYWNjb3VudHMudjEuQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0Gjcuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkbC8xhCCAIQAyoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua2VkEAJAAUgEUARYA2ABErUBChxMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzEjUuc2Fhcy5hY2NvdW50cy52MS5MaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBo2LnNhYXMuYWNjb3VudHMudjEuTGlzdE15RGF0YXNvdXJjZUFjY291bnRMaW5rc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARLUAQobRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rEjQuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXNwb25zZSJIwvMYRAgCEAMqDAoGb3JnX2lkEAIYATABOiQKIHNhYXMuZGF0YXNvdXJjZS5hY2NvdW50X3VubGlua2VkEAJAAUgEUAJYA2ABEqMBChZHZXREYXRhc291cmNlRGlyZWN0b3J5Ei8uc2Fhcy5hY2NvdW50cy52MS5HZXREYXRhc291cmNlRGlyZWN0b3J5UmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARK3AQoTQmluZERhdGFzb3VyY2VHcm91cBIsLnNhYXMuYWNjb3VudHMudjEuQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJDwvMYPwgCEAQqDAoGb3JnX2lkEAIYATABOh8KG3NhYXMuZGF0YXNvdXJjZS5ncm91cF9ib3VuZBACQAFIBFACWANgARK/AQoVVW5iaW5kRGF0YXNvdXJjZUdyb3VwEi4uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5ncm91cF91bmJvdW5kEAJAAUgEUAJYA2ABEsABChVDbGFpbURhdGFzb3VyY2VEb21haW4SLi5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkbC8xhCCAIQBCoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmRvbWFpbl9jbGFpbWVkEAJAAUgEUAJYA2ABEsQBChZWZXJpZnlEYXRhc291cmNlRG9tYWluEi8uc2Fhcy5hY2NvdW50cy52MS5WZXJpZnlEYXRhc291cmNlRG9tYWluUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkfC8xhDCAIQBCoMCgZvcmdfaWQQAhgBMAE6Iwofc2Fhcy5kYXRhc291cmNlLmRvbWFpbl92ZXJpZmllZBACQAFIBFACWANgARLDAQoWRGVsZXRlRGF0YXNvdXJjZURvbWFpbhIvLnNhYXMuYWNjb3VudHMudjEuRGVsZXRlRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaMC5zYWFzLmFjY291bnRzLnYxLkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5kb21haW5fcmVtb3ZlZBACQAFIBFACWANgARKgAQoVTGlzdFNvdXJjZURlbGVnYXRpb25zEi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESxwEKFlJldm9rZVNvdXJjZURlbGVnYXRpb24SLy5zYWFzLmFjY291bnRzLnYxLlJldm9rZVNvdXJjZURlbGVnYXRpb25SZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5SZXZva2VTb3VyY2VEZWxlZ2F0aW9uUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuZGVsZWdhdGlvbi5yZXZva2VkEAJAAUgEUAJYA2ABEusBChZEZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzEi8uc2Fhcy5hY2NvdW50cy52MS5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuRGVsZWdhdGVTb3VyY2VUcmlnZ2Vyc1Jlc3BvbnNlIm7C8xhqCAIQBCoMCgZvcmdfaWQQAhgBMAE6Sgoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24uY3JlYXRlZAoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24ucmV2b2tlZBACQAFIBFACWANgARKyAQobR2V0U291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESgwMKD1JlY29uY2lsZVNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UimgLC8xhqCAIQAxoRZGF0YXNvdXJjZTppbnZva2UiEWRhdGFzb3VyY2U6aW52b2tlKg8KCXNvdXJjZV9pZBAEGAMwATohCh1zYWFzLmRhdGFzb3VyY2Uuc291cmNlLnN5bmNlZBACQANIBFACWAJgAdrzGKcBCgIIPBIDCNgEGAUiAggCKgtVTkFWQUlMQUJMRSoSUkVTT1VSQ0VfRVhIQVVTVEVEKgdBQk9SVEVEMg9zYWFzLWRhdGFzb3VyY2VKOS9zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTZXJ2aWNlL0xvb2t1cFJlY29uY2lsZVNvdXJjZVCAIFiAIGABchgKBnNvdXJjZRIGaW52b2tlEgRyZWFkGAESvwEKFUxvb2t1cFJlY29uY2lsZVNvdXJjZRIuLnNhYXMuYWNjb3VudHMudjEuTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UiS8LzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ACWAJgAWIGcHJvdG8z", [file_buf_validate_validate, file_codefly_runnable_v0_options, file_google_api_annotations, file_google_protobuf_duration, file_google_protobuf_struct, file_google_protobuf_timestamp, file_saas_jobs_v1_jobs, file_saas_policy_v1_options]); + fileDesc("CiFzYWFzL2FjY291bnRzL3YxL2RhdGFzb3VyY2UucHJvdG8SEHNhYXMuYWNjb3VudHMudjEiXgoWR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIMCgRyZXBvGAEgASgJEg0KBXBhdGhzGAIgAygJEg4KBmJyYW5jaBgDIAEoCRIXCg9maWxlX2V4dGVuc2lvbnMYBCADKAki9AEKD0FwaU9BdXRoMkNvbmZpZxI2CgVncmFudBgEIAEoDjInLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnLkdyYW50EhEKCXRva2VuX3VybBgBIAEoCRIRCgljbGllbnRfaWQYAiABKAkSDgoGc2NvcGVzGAMgAygJInMKBUdyYW50EhUKEUdSQU5UX1VOU1BFQ0lGSUVEEAASFwoTR1JBTlRfUkVGUkVTSF9UT0tFThABEhwKGEdSQU5UX0NMSUVOVF9DUkVERU5USUFMUxACEhwKGEdSQU5UX0FVVEhPUklaQVRJT05fQ09ERRADIuoBChNBcGlEYXRhc291cmNlQ29uZmlnEhAKCGJhc2VfdXJsGAEgASgJEhUKDXJlc291cmNlX3BhdGgYAiABKAkSPAoPY3JlZGVudGlhbF9raW5kGAMgASgOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIZChFjcmVkZW50aWFsX2hlYWRlchgEIAEoCRIeChZjcmVkZW50aWFsX3F1ZXJ5X3BhcmFtGAUgASgJEjEKBm9hdXRoMhgGIAEoCzIhLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnIkEKF0NyYXdsZXJEYXRhc291cmNlQ29uZmlnEhMKC3NpdGVtYXBfdXJsGAEgASgJEhEKCW1heF9wYWdlcxgCIAEoDSKrAgoWVXBsb2FkRGF0YXNvdXJjZUNvbmZpZxIQCghlbmRwb2ludBgBIAEoCRIOCgZyZWdpb24YAiABKAkSDgoGYnVja2V0GAMgASgJEg4KBnByZWZpeBgEIAEoCRIVCg1hY2Nlc3Nfa2V5X2lkGAUgASgJEhMKC21heF9vYmplY3RzGAYgASgNEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACEkkKD2ZpbGVfZXh0ZW5zaW9ucxgJIAMoCUIwukgtkgEqECAiJnIkEAIYITIeXlwuW0EtWmEtejAtOV1bQS1aYS16MC05Ll8tXSokIoMHCgpEYXRhc291cmNlEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRI2Cghwcm92aWRlchgDIAEoDjIkLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyEjgKBmdpdGh1YhgFIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIyCgZzdGF0dXMYBiABKA4yIi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTdGF0dXMSGgoSd2ViaG9va19jb25maWd1cmVkGAcgASgIEi4KCmNyZWF0ZWRfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDmxhc3Rfc3luY2VkX2F0GAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgNhcGkYCyABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWcSOgoHY3Jhd2xlchgMIAEoCzIpLnNhYXMuYWNjb3VudHMudjEuQ3Jhd2xlckRhdGFzb3VyY2VDb25maWcSOAoGdXBsb2FkGA0gASgLMiguc2Fhcy5hY2NvdW50cy52MS5VcGxvYWREYXRhc291cmNlQ29uZmlnEhgKEGJvdW5kYXJ5X25vZGVfaWQYDiABKAkSNAoQbGFzdF9pbmdlc3RlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHAoUbGFzdF9pbmdlc3RlZF9jb21taXQYECABKAkSFQoNc3RhdHVzX3JlYXNvbhgRIAEoCRIWCg5ib3VuZGFyeV9sYWJlbBgSIAEoCRISCgpjb25mb3JtYW50GBMgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgUIAEoCRI/Cg1saXZlX2RlbGl2ZXJ5GBUgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlTGl2ZURlbGl2ZXJ5EjUKEnJlY29uY2lsZV9pbnRlcnZhbBgWIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkoECAQQBVIRdGFyZ2V0X2NvbGxlY3Rpb24isgMKFkFkZEdpdEh1YlNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI7CgRyZXBvGAIgASgJQi26SCpyKBADGP8BMiFeW0EtWmEtejAtOV8uLV0rL1tBLVphLXowLTlfLi1dKyQSIAoFcGF0aHMYAyADKAlCEbpIDpIBCxBAIgdyBRABGIAEEhgKBmJyYW5jaBgEIAEoCUIIukgFcgMY/wESJAoQYm91bmRhcnlfbm9kZV9pZBgIIAEoCUIIukgFcgOwAQFIABImChBjb2xsZWN0aW9uX2xhYmVsGAkgASgJQgq6SAdyBRABGP8BSAASHgoMYWNjZXNzX3Rva2VuGAYgASgJQgi6SAVyAxiACBIgCg53ZWJob29rX3NlY3JldBgHIAEoCUIIukgFcgMYgAgSSQoPZmlsZV9leHRlbnNpb25zGAogAygJQjC6SC2SASoQICImciQQAhghMh5eXC5bQS1aYS16MC05XVtBLVphLXowLTkuXy1dKiRCEQoIYm91bmRhcnkSBbpIAggBSgQIBRAGUhF0YXJnZXRfY29sbGVjdGlvbiJLChdBZGRHaXRIdWJTb3VyY2VSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsgEChBBZGRTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESQgoIcHJvdmlkZXIYAiABKA4yJC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VQcm92aWRlckIKukgHggEEEAEgABI6CgZnaXRodWIYBCABKAsyKC5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkRhdGFzb3VyY2VDb25maWdIABI0CgNhcGkYBSABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWdIABI8CgdjcmF3bGVyGAggASgLMikuc2Fhcy5hY2NvdW50cy52MS5DcmF3bGVyRGF0YXNvdXJjZUNvbmZpZ0gAEjoKBnVwbG9hZBgJIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuVXBsb2FkRGF0YXNvdXJjZUNvbmZpZ0gAEiQKEGJvdW5kYXJ5X25vZGVfaWQYDCABKAlCCLpIBXIDsAEBSAESJgoQY29sbGVjdGlvbl9sYWJlbBgNIAEoCUIKukgHcgUQARj/AUgBEhwKCmNyZWRlbnRpYWwYBiABKAlCCLpIBXIDGIAgEiAKDndlYmhvb2tfc2VjcmV0GAcgASgJQgi6SAVyAxiACBImChRvYXV0aDJfY2xpZW50X3NlY3JldBgKIAEoCUIIukgFcgMYgAhCCAoGY29uZmlnQhEKCGJvdW5kYXJ5EgW6SAIIAUoECAMQBFIRdGFyZ2V0X2NvbGxlY3Rpb24iRQoRQWRkU291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSLkAgoTVXBkYXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIYCgZicmFuY2gYAyABKAlCCLpIBXIDGP8BEiAKBXBhdGhzGAQgAygJQhG6SA6SAQsQQCIHcgUQARiABBJJCg9maWxlX2V4dGVuc2lvbnMYBSADKAlCMLpILZIBKhAgIiZyJBACGCEyHl5cLltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJBI8CghleHBlY3RlZBgGIAEoCzIiLnNhYXMuYWNjb3VudHMudjEuU291cmNlRmV0Y2hTY29wZUIGukgDyAEBEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACIs8BChBTb3VyY2VGZXRjaFNjb3BlEhgKBmJyYW5jaBgBIAEoCUIIukgFcgMY/wESIAoFcGF0aHMYAiADKAlCEbpIDpIBCxBAIgdyBRABGIAEEikKD2ZpbGVfZXh0ZW5zaW9ucxgDIAMoCUIQukgNkgEKECAiBnIEEAEYIRIpChBpbmNsdWRlX3BhdHRlcm5zGAQgAygJQg+6SAySAQkQECIFcgMYgAISKQoQZXhjbHVkZV9wYXR0ZXJucxgFIAMoCUIPukgMkgEJEBAiBXIDGIACIlgKFFVwZGF0ZVNvdXJjZVJlc3BvbnNlEjAKCmRhdGFzb3VyY2UYASABKAsyHC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2USDgoGam9iX2lkGAIgASgJIloKFURhdGFzb3VyY2VDb25maWdGaWVsZBILCgNrZXkYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEgwKBGhlbHAYAyABKAkSEAoIcmVxdWlyZWQYBCABKAgixAEKGURhdGFzb3VyY2VDb25uZWN0b3JCdWRnZXQSGgoSbWF4X2l0ZW1zX3Blcl9jYWxsGAEgASgNEhoKEm1heF9ieXRlc19wZXJfY2FsbBgCIAEoAxIWCg5tYXhfaXRlbV9ieXRlcxgDIAEoAxIdChVvcGVyYXRpb25zX3Blcl93aW5kb3cYBCABKA0SFgoOd2luZG93X3NlY29uZHMYBSABKAMSIAoYYmFja2dyb3VuZF9zaGFyZV9wZXJjZW50GAYgASgNIqoGChxEYXRhc291cmNlUHJvdmlkZXJEZXNjcmlwdG9yEjYKCHByb3ZpZGVyGAEgASgOMiQuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUHJvdmlkZXISFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEj4KDWNvbmZpZ19maWVsZHMYBCADKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDb25maWdGaWVsZBIYChBzdXBwb3J0c193ZWJob29rGAUgASgIEkcKGnN1cHBvcnRlZF9jcmVkZW50aWFsX2tpbmRzGAYgAygOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIRCgljb25uZWN0b3IYByABKAkSQQoJaW50ZXJmYWNlGAggASgOMi4uc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQ29ubmVjdG9ySW50ZXJmYWNlEkQKEGNyZWRlbnRpYWxfbW9kZXMYCSADKA4yKi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRI/Cg1yZWFkZXJzX21vZGVsGAogASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUmVhZGVyc01vZGVsEjsKBmJ1ZGdldBgLIAEoCzIrLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUNvbm5lY3RvckJ1ZGdldBISCgpjb25mb3JtYW50GAwgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgNIAEoCRIbChNhY2NlcHRzX25ld19zb3VyY2VzGA4gASgIEiAKGGxpdmVfZGVsaXZlcnlfY29uZmlndXJlZBgPIAEoCBIaChJhY2NlcHRzX29wZXJhdGlvbnMYECABKAgSFgoOb3BlcmF0aW9uc19nYXAYESABKAkSGwoTb2F1dGhfYXV0aG9yaXplX3VybBgSIAEoCRIXCg9vYXV0aF90b2tlbl91cmwYEyABKAkSFAoMb2F1dGhfc2NvcGVzGBQgAygJIh0KG0dldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdCJhChxHZXREYXRhc291cmNlQ2F0YWxvZ1Jlc3BvbnNlEkEKCXByb3ZpZGVycxgBIAMoCzIuLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyRGVzY3JpcHRvciIuChJMaXN0U291cmNlc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJIChNMaXN0U291cmNlc1Jlc3BvbnNlEjEKC2RhdGFzb3VyY2VzGAEgAygLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIkIKEEdldFNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiRQoRR2V0U291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSJ2ChFTeW5jU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIeCgxhY2Nlc3NfdG9rZW4YAyABKAlCCLpIBXIDGIAgEhEKCXJlY29ubmVjdBgEIAEoCCIkChJTeW5jU291cmNlUmVzcG9uc2USDgoGam9iX2lkGAEgASgJImoKFEdldFNvdXJjZVN5bmNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgZqb2JfaWQYAyABKAlCC7pICNgBAXIDsAEBIpUBChJTb3VyY2VTeW5jRGVsaXZlcnkSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARItCgVzdGF0ZRgCIAEoDjIWLnNhYXMuam9icy52MS5Kb2JTdGF0ZUIGukgDyAEBEjYKCWV4ZWN1dGlvbhgDIAEoCzIjLnNhYXMuam9icy52MS5Kb2JFeGVjdXRpb25SZWZlcmVuY2UiiwEKEVNvdXJjZVN5bmNDaGFuZ2VzEg0KBWZpbGVzGAEgASgNEg0KBWFkZGVkGAIgASgNEhAKCG1vZGlmaWVkGAMgASgNEg8KB2RlbGV0ZWQYBCABKA0SEwoLc3BsaXRfa25vd24YBSABKAgSEAoIc25hcHNob3QYBiABKAgSDgoGY29tbWl0GAcgASgJIq0BChFTb3VyY2VTeW5jRmFpbHVyZRI5CgZyZWFzb24YASABKA4yKS5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNGYWlsdXJlUmVhc29uEgwKBGNvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCRIQCghyZXRyeWluZxgEIAEoCBIsCghyZXRyeV9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAQKElNvdXJjZVN5bmNQcm9ncmVzcxIwCgVwaGFzZRgBIAEoDjIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY1BoYXNlEjQKB3RyaWdnZXIYAiABKA4yIy5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNUcmlnZ2VyEi0KCXF1ZXVlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoLZmV0Y2hpbmdfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi8KC2NvbXBpbGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1oYW5kZWRfb2ZmX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIvCgtmaW5pc2hlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoHY2hhbmdlcxgIIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0NoYW5nZXMSNAoHZmFpbHVyZRgJIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0ZhaWx1cmUSDwoHYXR0ZW1wdBgKIAEoDRIUCgxtYXhfYXR0ZW1wdHMYCyABKA0i0gEKFUdldFNvdXJjZVN5bmNSZXNwb25zZRIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBEi0KBXN0YXRlGAIgASgOMhYuc2Fhcy5qb2JzLnYxLkpvYlN0YXRlQga6SAPIAQESOAoKZGVsaXZlcmllcxgDIAMoCzIkLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0RlbGl2ZXJ5EjYKCHByb2dyZXNzGAQgASgLMiQuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VTeW5jUHJvZ3Jlc3MiRQoTRGVsZXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASIWChREZWxldGVTb3VyY2VSZXNwb25zZSJWChNHaXRIdWJBcHBSZXBvc2l0b3J5EgwKBHJlcG8YASABKAkSFgoOZGVmYXVsdF9icmFuY2gYAiABKAkSGQoRYWxyZWFkeV9jb25uZWN0ZWQYAyABKAgiNgoaQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJxChtCZWdpbkdpdEh1YkFwcFNldHVwUmVzcG9uc2USEwoLaW5zdGFsbF91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAinAEKHUNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEY/wESLAoPaW5zdGFsbGF0aW9uX2lkGAMgASgJQhO6SBByDhABGCAyCF5bMC05XSskEhgKBGNvZGUYBCABKAlCCrpIB3IFEAEY/wEidgoeQ29tcGxldGVHaXRIdWJBcHBTZXR1cFJlc3BvbnNlEhcKD2luc3RhbGxhdGlvbl9pZBgBIAEoCRI7CgxyZXBvc2l0b3JpZXMYAiADKAsyJS5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkFwcFJlcG9zaXRvcnkiUQofTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASJUCiBNaWdyYXRlR2l0SHViU291cmNlVG9BcHBSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsQBChVEYXRhc291cmNlQWNjb3VudExpbmsSCgoCaWQYASABKAkSDgoGb3JnX2lkGAIgASgJEg8KB3VzZXJfaWQYAyABKAkSEQoJY29ubmVjdG9yGAQgASgJEhsKE3Byb3ZpZGVyX2FjY291bnRfaWQYBSABKAkSHgoWcHJvdmlkZXJfYWNjb3VudF9sb2dpbhgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK3AQoWRGF0YXNvdXJjZUdyb3VwQmluZGluZxIKCgJpZBgBIAEoCRIOCgZvcmdfaWQYAiABKAkSEQoJY29ubmVjdG9yGAMgASgJEhkKEXByb3ZpZGVyX2dyb3VwX2lkGAQgASgJEg8KB3RlYW1faWQYBSABKAkSEgoKY3JlYXRlZF9ieRgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKUAgoYRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRIOCgZkb21haW4YAyABKAkSOAoGc3RhdHVzGAQgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRG9tYWluU3RhdHVzEhcKD3R4dF9yZWNvcmRfbmFtZRgFIAEoCRIYChB0eHRfcmVjb3JkX3ZhbHVlGAYgASgJEi8KC3ZlcmlmaWVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjcmVhdGVkX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIzChdEYXRhc291cmNlRGlyZWN0b3J5VGVhbRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJIqYBCiFCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIeCgxyZWRpcmVjdF91cmkYAyABKAlCCLpIBXIDGIAQEhEKCXNvdXJjZV9pZBgEIAEoCSJ6CiJCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEhUKDWF1dGhvcml6ZV91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAidQokQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEYgEASGAoEY29kZRgDIAEoCUIKukgHcgUQARj/ASJeCiVDb21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEjUKBGxpbmsYASABKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VBY2NvdW50TGluayI/CiNMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBIl4KJExpc3RNeURhdGFzb3VyY2VBY2NvdW50TGlua3NSZXNwb25zZRI2CgVsaW5rcxgBIAMoCzInLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUFjY291bnRMaW5rIlQKIkRlbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiJQojRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rUmVzcG9uc2UiOQodR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASKLAgoeR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlEjYKBWxpbmtzGAEgAygLMicuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQWNjb3VudExpbmsSOgoIYmluZGluZ3MYAiADKAsyKC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VHcm91cEJpbmRpbmcSOwoHZG9tYWlucxgDIAMoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEjgKBXRlYW1zGAQgAygLMikuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRGlyZWN0b3J5VGVhbSKuAQoaQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIlChFwcm92aWRlcl9ncm91cF9pZBgDIAEoCUIKukgHcgUQARj/ARIZCgd0ZWFtX2lkGAQgASgJQgi6SAVyA7ABASJYChtCaW5kRGF0YXNvdXJjZUdyb3VwUmVzcG9uc2USOQoHYmluZGluZxgBIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUdyb3VwQmluZGluZyJOChxVbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIh8KHVVuYmluZERhdGFzb3VyY2VHcm91cFJlc3BvbnNlIlQKHENsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIaCgZkb21haW4YAiABKAlCCrpIB3IFEAMY/QEiWwodQ2xhaW1EYXRhc291cmNlRG9tYWluUmVzcG9uc2USOgoGZG9tYWluGAEgASgLMiouc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlVmVyaWZpZWREb21haW4iTwodVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiXAoeVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlEjoKBmRvbWFpbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluIk8KHURlbGV0ZURhdGFzb3VyY2VEb21haW5SZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIiAKHkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSKeAgoQU291cmNlRGVsZWdhdGlvbhIKCgJpZBgBIAEoCRIRCglzb3VyY2VfaWQYAiABKAkSFAoMcHJpbmNpcGFsX2lkGAMgASgJEg4KBm1vZHVsZRgEIAEoCRIPCgdiaW5kaW5nGAUgASgJEi4KCmNyZWF0ZWRfYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnJldm9rZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEkAKCnJldm9jYXRpb24YCCABKA4yLC5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb25SZXZvY2F0aW9uEhIKCnJldm9rZWRfYnkYCSABKAkigQEKHExpc3RTb3VyY2VEZWxlZ2F0aW9uc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIgCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBSACIAQESFwoPaW5jbHVkZV9yZXZva2VkGAMgASgIQgwKCl9zb3VyY2VfaWQiWAodTGlzdFNvdXJjZURlbGVnYXRpb25zUmVzcG9uc2USNwoLZGVsZWdhdGlvbnMYASADKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iTwodUmV2b2tlU291cmNlRGVsZWdhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiWAoeUmV2b2tlU291cmNlRGVsZWdhdGlvblJlc3BvbnNlEjYKCmRlbGVnYXRpb24YASABKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iMgoPVHJpZ2dlcklkZW50aXR5Eg4KBnNvdXJjZRgBIAEoCRIPCgdiaW5kaW5nGAIgASgJIoQBChdEZWNsYXJlZFRyaWdnZXJTY2hlZHVsZRIMCgRjcm9uGAEgASgJEhAKCHRpbWV6b25lGAIgASgJEhIKCm1pc3NlZF9ydW4YAyABKAkSDwoHb3ZlcmxhcBgEIAEoCRIQCghkZWFkbGluZRgFIAEoAxISCgppbnB1dF9qc29uGAYgASgJIucCChpUcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRIRCglyZWZlcmVuY2UYASABKAkSFQoNZGVsZWdhdGlvbl9pZBgCIAEoCRIOCgZtb2R1bGUYAyABKAkSDwoHYmluZGluZxgEIAEoCRIQCghhdWRpZW5jZRgFIAEoCRIOCgZ0ZW5hbnQYBiABKAkSGgoSb3duZXJfcHJpbmNpcGFsX2lkGAcgASgJEg4KBnNjb3BlcxgIIAMoCRIOCgZhY3RpdmUYCSABKAgSLgoKY3JlYXRlZF9hdBgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKcmV2b2tlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASQAoKcmV2b2NhdGlvbhgMIAEoDjIsLnNhYXMuYWNjb3VudHMudjEuU291cmNlRGVsZWdhdGlvblJldm9jYXRpb24ivgEKE1RyaWdnZXJDaGlsZENvbnRleHQSFQoNZGVsZWdhdGlvbl9pZBgBIAEoCRIOCgZtb2R1bGUYAiABKAkSDwoHYmluZGluZxgDIAEoCRIQCghhdWRpZW5jZRgEIAEoCRIOCgZzY29wZXMYBSADKAkSDgoGbG9va3VwGAYgASgIEi0KCW1pbnRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGcmVjb3JkGAggASgJIs0CChhTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb24SDwoHcmVsZWFzZRgBIAEoCRIRCglvcGVyYXRpb24YAiABKAkSOwoIc2NoZWR1bGUYAyABKAsyKS5zYWFzLmFjY291bnRzLnYxLkRlY2xhcmVkVHJpZ2dlclNjaGVkdWxlEjMKCGlkZW50aXR5GAQgASgLMiEuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VySWRlbnRpdHkSDgoGZGlnZXN0GAUgASgJEjYKEmxhc3Rfb2NjdXJyZW5jZV9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNgoSbmV4dF9vY2N1cnJlbmNlX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChN1bmRlY2xhcmFibGVfcmVhc29uGAggASgJIlYKHURlbGVnYXRlU291cmNlVHJpZ2dlcnNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABASJjCh5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVzcG9uc2USQQoLZGVsZWdhdGlvbnMYASADKAsyLC5zYWFzLmFjY291bnRzLnYxLlRyaWdnZXJEZWxlZ2F0aW9uUmVmZXJlbmNlIlsKIkdldFNvdXJjZVRyaWdnZXJEZWNsYXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBIuIBCiNHZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZRI/CgtkZWNsYXJhdGlvbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuU291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEkEKC2RlbGVnYXRpb25zGAIgAygLMiwuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRI3CghjaGlsZHJlbhgDIAMoCzIlLnNhYXMuYWNjb3VudHMudjEuVHJpZ2dlckNoaWxkQ29udGV4dCJuChZSZWNvbmNpbGVTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIdCgllZmZlY3RfaWQYAyABKAlCCrpIB3IFEAEYgAEiTAoXUmVjb25jaWxlU291cmNlUmVzcG9uc2USEQoJZWZmZWN0X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIOCgZqb2JfaWQYAyABKAkiPQocTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBIdCgllZmZlY3RfaWQYASABKAlCCrpIB3IFEAEYgAEi8QIKD1NvdXJjZU9wZXJhdGlvbhIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg4KBm1ldGhvZBgDIAEoCRIMCgRwYXRoGAQgASgJEg0KBXF1ZXJ5GAUgAygJEi0KDGlucHV0X3NjaGVtYRgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSLgoNb3V0cHV0X3NjaGVtYRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSOAoGZWZmZWN0GAggASgOMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24uRWZmZWN0EhgKEG1heF9vdXRwdXRfYnl0ZXMYCSABKA0SDgoGZGlnZXN0GAogASgJIksKBkVmZmVjdBIWChJFRkZFQ1RfVU5TUEVDSUZJRUQQABIUChBFRkZFQ1RfUkVBRF9PTkxZEAESEwoPRUZGRUNUX01VVEFUSU9OEAIijgEKHkRlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQESNQoKb3BlcmF0aW9ucxgDIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlgKH0RlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVzcG9uc2USNQoKb3BlcmF0aW9ucxgBIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlQKG0xpc3RTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQEiVQocTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXNwb25zZRI1CgpvcGVyYXRpb25zGAEgAygLMiEuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24irgIKHEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBEjAKCW9wZXJhdGlvbhgDIAEoCUIdukgachgyFl5bYS16XVthLXowLTlfXXswLDYzfSQSHQoKaW5wdXRfanNvbhgEIAEoCUIJukgGcgQogIAEEhsKCWVmZmVjdF9pZBgFIAEoCUIIukgFcgMogAESSQobZXhwZWN0ZWRfZGVjbGFyYXRpb25fZGlnZXN0GAYgASgJQh+6SBxyGjIYXihzaGEyNTY6WzAtOWEtZl17NjR9KT8kSACIAQFCHgocX2V4cGVjdGVkX2RlY2xhcmF0aW9uX2RpZ2VzdCJ/ChZTb3VyY2VPcGVyYXRpb25SZWNlaXB0EhEKCWVmZmVjdF9pZBgBIAEoCRIUCgxjb21taXR0ZWRfYXQYAiABKAkSDgoGc3RhdHVzGAMgASgJEhcKD3Byb3ZpZGVyX3N0YXR1cxgEIAEoDRITCgtvdXRwdXRfanNvbhgFIAEoCSJvCh1JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZRITCgtvdXRwdXRfanNvbhgBIAEoCRI5CgdyZWNlaXB0GAIgASgLMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb25SZWNlaXB0IkMKIkxvb2t1cEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSHQoJZWZmZWN0X2lkGAEgASgJQgq6SAdyBRABKIABInkKI1BydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgllZmZlY3RfaWQYAyABKAlCCLpIBXIDKIABIlsKJFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZRIRCgllZmZlY3RfaWQYASABKAkSEAoIcmVjZWlwdHMYAiABKAMSDgoGc3RhdHVzGAMgASgJIkoKKUxvb2t1cFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0Eh0KCWVmZmVjdF9pZBgBIAEoCUIKukgHcgUQASiAASq3AQoSRGF0YXNvdXJjZVByb3ZpZGVyEiMKH0RBVEFTT1VSQ0VfUFJPVklERVJfVU5TUEVDSUZJRUQQABIeChpEQVRBU09VUkNFX1BST1ZJREVSX0dJVEhVQhABEhsKF0RBVEFTT1VSQ0VfUFJPVklERVJfQVBJEAISHwobREFUQVNPVVJDRV9QUk9WSURFUl9DUkFXTEVSEAMSHgoaREFUQVNPVVJDRV9QUk9WSURFUl9VUExPQUQQBCqRAQoQRGF0YXNvdXJjZVN0YXR1cxIhCh1EQVRBU09VUkNFX1NUQVRVU19VTlNQRUNJRklFRBAAEhwKGERBVEFTT1VSQ0VfU1RBVFVTX0FDVElWRRABEhwKGERBVEFTT1VSQ0VfU1RBVFVTX1BBVVNFRBACEh4KGkRBVEFTT1VSQ0VfU1RBVFVTX0RFR1JBREVEEAMqvAEKFkRhdGFzb3VyY2VMaXZlRGVsaXZlcnkSKAokREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX1VOU1BFQ0lGSUVEEAASIQodREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX05PTkUQARIrCidEQVRBU09VUkNFX0xJVkVfREVMSVZFUllfU09VUkNFX1dFQkhPT0sQAhIoCiREQVRBU09VUkNFX0xJVkVfREVMSVZFUllfQVBQX1dFQkhPT0sQAyrWAQoRQXBpQ3JlZGVudGlhbEtpbmQSIwofQVBJX0NSRURFTlRJQUxfS0lORF9VTlNQRUNJRklFRBAAEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfQkVBUkVSEAESHQoZQVBJX0NSRURFTlRJQUxfS0lORF9CQVNJQxACEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfSEVBREVSEAMSHQoZQVBJX0NSRURFTlRJQUxfS0lORF9RVUVSWRAEEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfT0FVVEgyEAUqpgIKHERhdGFzb3VyY2VDb25uZWN0b3JJbnRlcmZhY2USLgoqREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1VOU1BFQ0lGSUVEEAASKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX0ZJTEVTEAESKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1BBR0VTEAISKgomREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1JFQ09SRFMQAxIrCidEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfTUVTU0FHRVMQBBIpCiVEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfRVZFTlRTEAUq7AEKGERhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRIqCiZEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9VTlNQRUNJRklFRBAAEiMKH0RBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX05PTkUQARImCiJEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9PUkdfQVBQEAISKQolREFUQVNPVVJDRV9DUkVERU5USUFMX01PREVfVVNFUl9PQVVUSBADEiwKKERBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX1NUQVRJQ19TRUNSRVQQBCqXAQoWRGF0YXNvdXJjZVJlYWRlcnNNb2RlbBIoCiREQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfVU5TUEVDSUZJRUQQABIqCiZEQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfU09VUkNFX1NDT1BFRBABEicKI0RBVEFTT1VSQ0VfUkVBREVSU19NT0RFTF9UUkFOU0xBVEVEEAIq7gEKD1NvdXJjZVN5bmNQaGFzZRIhCh1TT1VSQ0VfU1lOQ19QSEFTRV9VTlNQRUNJRklFRBAAEhwKGFNPVVJDRV9TWU5DX1BIQVNFX1FVRVVFRBABEh4KGlNPVVJDRV9TWU5DX1BIQVNFX0ZFVENISU5HEAISHgoaU09VUkNFX1NZTkNfUEhBU0VfQ09NUElMRUQQAxIgChxTT1VSQ0VfU1lOQ19QSEFTRV9IQU5ERURfT0ZGEAQSGgoWU09VUkNFX1NZTkNfUEhBU0VfRE9ORRAFEhwKGFNPVVJDRV9TWU5DX1BIQVNFX0ZBSUxFRBAGKqYDChdTb3VyY2VTeW5jRmFpbHVyZVJlYXNvbhIqCiZTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEisKJ1NPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX1JBVEVfTElNSVRFRBABEikKJVNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX0NSRURFTlRJQUwQAhIsCihTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9BQ0NFU1NfREVOSUVEEAMSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fTk9UX0ZPVU5EEAQSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fVE9PX0xBUkdFEAUSLworU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fSE9TVF9VTkFWQUlMQUJMRRAGEiQKIFNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX09USEVSEAcSLgoqU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fREVMSVZFUllfRkFJTEVEEAgqwgEKEVNvdXJjZVN5bmNUcmlnZ2VyEiMKH1NPVVJDRV9TWU5DX1RSSUdHRVJfVU5TUEVDSUZJRUQQABIeChpTT1VSQ0VfU1lOQ19UUklHR0VSX01BTlVBTBABEiEKHVNPVVJDRV9TWU5DX1RSSUdHRVJfU0NIRURVTEVEEAISHwobU09VUkNFX1NZTkNfVFJJR0dFUl9XRUJIT09LEAMSJAogU09VUkNFX1NZTkNfVFJJR0dFUl9SRUNPTkZJR1VSRUQQBCqPAQoWRGF0YXNvdXJjZURvbWFpblN0YXR1cxIoCiREQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIkCiBEQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfUEVORElORxABEiUKIURBVEFTT1VSQ0VfRE9NQUlOX1NUQVRVU19WRVJJRklFRBACKpUDChpTb3VyY2VEZWxlZ2F0aW9uUmV2b2NhdGlvbhIsCihTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VOU1BFQ0lGSUVEEAASKAokU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVZPS0VEEAESKQolU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVBMQUNFRBACEi8KK1NPVVJDRV9ERUxFR0FUSU9OX1JFVk9DQVRJT05fU09VUkNFX0RFTEVURUQQAxIvCitTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX01FTUJFUl9SRU1PVkVEEAQSMAosU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9QRVJNSVNTSU9OX0xPU1QQBRIuCipTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VTRVJfSU5BQ1RJVkUQBhIwCixTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX0JJTkRJTkdfQ0hBTkdFRBAHMrM7ChFEYXRhc291cmNlU2VydmljZRK5AwocUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI1LnNhYXMuYWNjb3VudHMudjEuUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSKpAsLzGGwIAhADGhFkYXRhc291cmNlOmludm9rZSIRZGF0YXNvdXJjZTppbnZva2UqDwoJc291cmNlX2lkEAQYAzABOiMKH3NhYXMuZGF0YXNvdXJjZS5yZWNlaXB0cy5wcnVuZWQQAkADSARQA1gDYAHa8xi0AQoCCDwSAwjYBBgFIgIIAioLVU5BVkFJTEFCTEUqElJFU09VUkNFX0VYSEFVU1RFRCoHQUJPUlRFRDIPc2Fhcy1kYXRhc291cmNlSkYvc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlU2VydmljZS9Mb29rdXBQcnVuZVNvdXJjZU9wZXJhdGlvblJlY2VpcHRzUIAgWIAgYAFyGAoGc291cmNlEgZpbnZva2USBHJlYWQYARLmAQoiTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI7LnNhYXMuYWNjb3VudHMudjEuTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSJLwvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUANYA2ABEvwDChVJbnZva2VTb3VyY2VPcGVyYXRpb24SLi5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlc3BvbnNlIoEDwvMYbggCEAMaEWRhdGFzb3VyY2U6aW52b2tlIhFkYXRhc291cmNlOmludm9rZSoPCglzb3VyY2VfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEARAA0gEUARYBGAB2vMYrwEKAgg8EgMI2AQYBSICCAIqC1VOQVZBSUxBQkxFKhJSRVNPVVJDRV9FWEhBVVNURUQqB0FCT1JURUQyD3NhYXMtZGF0YXNvdXJjZUo/L3NhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVNlcnZpY2UvTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uUICABFiAgEBgAXIYCgZzb3VyY2USBmludm9rZRIEcmVhZBgBgtPkkwJVOgEqIlAvdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zL3tvcGVyYXRpb259Omludm9rZRKHAgobTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5Mb29rdXBJbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKAAcLzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ADWARgAYLT5JMCLxItL3YxL2RhdGFzb3VyY2Utb3BlcmF0aW9uLXJlY2VpcHRzL3tlZmZlY3RfaWR9Ev8BChxWZXJpZnlTb3VyY2VPcGVyYXRpb25SZWNlaXB0Ei4uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSJ+wvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUARYBGABgtPkkwItOgEqIigvdjEvZGF0YXNvdXJjZS1vcGVyYXRpb24tcmVjZWlwdHMvdmVyaWZ5EoUCChRMaXN0U291cmNlT3BlcmF0aW9ucxItLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0Gi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIo0BwvMYRAgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKgwKBm9yZ19pZBACGAEwAToCEAFAAUgDUANYA2ABgtPkkwI/Ej0vdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zEpMCChdEZWNsYXJlU291cmNlT3BlcmF0aW9ucxIwLnNhYXMuYWNjb3VudHMudjEuRGVjbGFyZVNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0GjEuc2Fhcy5hY2NvdW50cy52MS5EZWNsYXJlU291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIpIBwvMYRggCEAQqDAoGb3JnX2lkEAIYATABOiYKInNhYXMuZGF0YXNvdXJjZS5vcGVyYXRpb24uZGVjbGFyZWQQAkABSARQA1gDYAGC0+STAkI6ASoiPS92MS9vcmdhbml6YXRpb25zL3tvcmdfaWR9L2RhdGFzb3VyY2VzL3tzb3VyY2VfaWR9L29wZXJhdGlvbnMSrAEKD0FkZEdpdEh1YlNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVzcG9uc2UiRMLzGEAIAhAEKgwKBm9yZ19pZBACGAEwATogChxzYWFzLmRhdGFzb3VyY2Uuc291cmNlLmFkZGVkEAJAAUgEUARYA2ABEpoBCglBZGRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlc3BvbnNlIkTC8xhACAIQBCoMCgZvcmdfaWQQAhgBMAE6IAocc2Fhcy5kYXRhc291cmNlLnNvdXJjZS5hZGRlZBACQAFIBFAEWANgARKlAQoMVXBkYXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UudXBkYXRlZBACQAFIBFACWANgARKPAQoUR2V0RGF0YXNvdXJjZUNhdGFsb2cSLS5zYWFzLmFjY291bnRzLnYxLkdldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdBouLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZUNhdGFsb2dSZXNwb25zZSIYwvMYFAgCEAEwAToCEAFAAUgDUAJYAmABEoIBCgtMaXN0U291cmNlcxIkLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZXNSZXF1ZXN0GiUuc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARJ8CglHZXRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKeAQoKU3luY1NvdXJjZRIjLnNhYXMuYWNjb3VudHMudjEuU3luY1NvdXJjZVJlcXVlc3QaJC5zYWFzLmFjY291bnRzLnYxLlN5bmNTb3VyY2VSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5zb3VyY2Uuc3luY2VkEAJAAUgEUARYAmABEogBCg1HZXRTb3VyY2VTeW5jEiYuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VTeW5jUmVxdWVzdBonLnNhYXMuYWNjb3VudHMudjEuR2V0U291cmNlU3luY1Jlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKlAQoMRGVsZXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UucmVtb3ZlZBACQAFIBFACWAJgARLEAQoTQmVnaW5HaXRIdWJBcHBTZXR1cBIsLnNhYXMuYWNjb3VudHMudjEuQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJlZ2luR2l0SHViQXBwU2V0dXBSZXNwb25zZSJQwvMYTAgCEAQqDAoGb3JnX2lkEAIYATABOiwKKHNhYXMuZGF0YXNvdXJjZS5naXRodWJfYXBwLnNldHVwX3N0YXJ0ZWQQAkABSARQAlgEYAESzwEKFkNvbXBsZXRlR2l0SHViQXBwU2V0dXASLy5zYWFzLmFjY291bnRzLnYxLkNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZUdpdEh1YkFwcFNldHVwUmVzcG9uc2UiUsLzGE4IAhAEKgwKBm9yZ19pZBACGAEwATouCipzYWFzLmRhdGFzb3VyY2UuZ2l0aHViX2FwcC5zZXR1cF9jb21wbGV0ZWQQAkABSARQBFgDYAESzQEKGE1pZ3JhdGVHaXRIdWJTb3VyY2VUb0FwcBIxLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBoyLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuY3JlZGVudGlhbC51cGRhdGVkEAJAAUgEUAJYA2ABEtUBChpCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGluaxIzLnNhYXMuYWNjb3VudHMudjEuQmVnaW5EYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjQuc2Fhcy5hY2NvdW50cy52MS5CZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkzC8xhICAIQAyoMCgZvcmdfaWQQAhgBMAE6KAokc2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua19zdGFydGVkEAJAAUgEUAJYBGABEtgBCh1Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGluaxI2LnNhYXMuYWNjb3VudHMudjEuQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0Gjcuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkbC8xhCCAIQAyoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua2VkEAJAAUgEUARYA2ABErUBChxMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzEjUuc2Fhcy5hY2NvdW50cy52MS5MaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBo2LnNhYXMuYWNjb3VudHMudjEuTGlzdE15RGF0YXNvdXJjZUFjY291bnRMaW5rc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARLUAQobRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rEjQuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXNwb25zZSJIwvMYRAgCEAMqDAoGb3JnX2lkEAIYATABOiQKIHNhYXMuZGF0YXNvdXJjZS5hY2NvdW50X3VubGlua2VkEAJAAUgEUAJYA2ABEqMBChZHZXREYXRhc291cmNlRGlyZWN0b3J5Ei8uc2Fhcy5hY2NvdW50cy52MS5HZXREYXRhc291cmNlRGlyZWN0b3J5UmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARK3AQoTQmluZERhdGFzb3VyY2VHcm91cBIsLnNhYXMuYWNjb3VudHMudjEuQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJDwvMYPwgCEAQqDAoGb3JnX2lkEAIYATABOh8KG3NhYXMuZGF0YXNvdXJjZS5ncm91cF9ib3VuZBACQAFIBFACWANgARK/AQoVVW5iaW5kRGF0YXNvdXJjZUdyb3VwEi4uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5ncm91cF91bmJvdW5kEAJAAUgEUAJYA2ABEsABChVDbGFpbURhdGFzb3VyY2VEb21haW4SLi5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkbC8xhCCAIQBCoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmRvbWFpbl9jbGFpbWVkEAJAAUgEUAJYA2ABEsQBChZWZXJpZnlEYXRhc291cmNlRG9tYWluEi8uc2Fhcy5hY2NvdW50cy52MS5WZXJpZnlEYXRhc291cmNlRG9tYWluUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkfC8xhDCAIQBCoMCgZvcmdfaWQQAhgBMAE6Iwofc2Fhcy5kYXRhc291cmNlLmRvbWFpbl92ZXJpZmllZBACQAFIBFACWANgARLDAQoWRGVsZXRlRGF0YXNvdXJjZURvbWFpbhIvLnNhYXMuYWNjb3VudHMudjEuRGVsZXRlRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaMC5zYWFzLmFjY291bnRzLnYxLkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5kb21haW5fcmVtb3ZlZBACQAFIBFACWANgARKgAQoVTGlzdFNvdXJjZURlbGVnYXRpb25zEi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESxwEKFlJldm9rZVNvdXJjZURlbGVnYXRpb24SLy5zYWFzLmFjY291bnRzLnYxLlJldm9rZVNvdXJjZURlbGVnYXRpb25SZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5SZXZva2VTb3VyY2VEZWxlZ2F0aW9uUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuZGVsZWdhdGlvbi5yZXZva2VkEAJAAUgEUAJYA2ABEusBChZEZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzEi8uc2Fhcy5hY2NvdW50cy52MS5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuRGVsZWdhdGVTb3VyY2VUcmlnZ2Vyc1Jlc3BvbnNlIm7C8xhqCAIQBCoMCgZvcmdfaWQQAhgBMAE6Sgoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24uY3JlYXRlZAoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24ucmV2b2tlZBACQAFIBFACWANgARKyAQobR2V0U291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESgwMKD1JlY29uY2lsZVNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UimgLC8xhqCAIQAxoRZGF0YXNvdXJjZTppbnZva2UiEWRhdGFzb3VyY2U6aW52b2tlKg8KCXNvdXJjZV9pZBAEGAMwATohCh1zYWFzLmRhdGFzb3VyY2Uuc291cmNlLnN5bmNlZBACQANIBFACWAJgAdrzGKcBCgIIPBIDCNgEGAUiAggCKgtVTkFWQUlMQUJMRSoSUkVTT1VSQ0VfRVhIQVVTVEVEKgdBQk9SVEVEMg9zYWFzLWRhdGFzb3VyY2VKOS9zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTZXJ2aWNlL0xvb2t1cFJlY29uY2lsZVNvdXJjZVCAIFiAIGABchgKBnNvdXJjZRIGaW52b2tlEgRyZWFkGAESvwEKFUxvb2t1cFJlY29uY2lsZVNvdXJjZRIuLnNhYXMuYWNjb3VudHMudjEuTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UiS8LzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ACWAJgAWIGcHJvdG8z", [file_buf_validate_validate, file_codefly_runnable_v0_options, file_google_api_annotations, file_google_protobuf_duration, file_google_protobuf_struct, file_google_protobuf_timestamp, file_saas_jobs_v1_jobs, file_saas_policy_v1_options]); /** * GitHubDatasourceConfig is the public, non-secret configuration of a GitHub @@ -4227,6 +4227,21 @@ export const DatasourceService: GenService<{ input: typeof LookupInvokeSourceOperationRequestSchema; output: typeof InvokeSourceOperationResponseSchema; }, + /** + * VerifySourceOperationReceipt conditionally reads retained output using the + * exact original Invoke request, including a nonempty declaration precondition. + * Committed means the normalized request and admitted declaration match the + * stored attempt. Unknown remains unresolved; this method never redispatches. + * Current actor, tenant and stored-source read authority apply before comparison. + * This is independent of the paired Runnable Lookup contract above. + * + * @generated from rpc saas.accounts.v1.DatasourceService.VerifySourceOperationReceipt + */ + verifySourceOperationReceipt: { + methodKind: "unary"; + input: typeof InvokeSourceOperationRequestSchema; + output: typeof InvokeSourceOperationResponseSchema; + }, /** * ListSourceOperations reads the currently admitted declarations under source authority. * diff --git a/module/services/frontend/code/packages/saas-sdk/package.json b/module/services/frontend/code/packages/saas-sdk/package.json index b7791c0a9..efccbf7cc 100644 --- a/module/services/frontend/code/packages/saas-sdk/package.json +++ b/module/services/frontend/code/packages/saas-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@codefly-dev/saas-sdk", - "version": "0.3.42", + "version": "0.3.43", "description": "Typed Connect client, gateway-bound facades, and audit data-graph tooling for the saas-starter public API.", "repository": { "type": "git", diff --git a/module/services/frontend/code/packages/saas-sdk/test/source-declaration.test.ts b/module/services/frontend/code/packages/saas-sdk/test/source-declaration.test.ts index 91a00e4ac..5a82a716f 100644 --- a/module/services/frontend/code/packages/saas-sdk/test/source-declaration.test.ts +++ b/module/services/frontend/code/packages/saas-sdk/test/source-declaration.test.ts @@ -1,5 +1,5 @@ import { toJson } from "@bufbuild/protobuf"; -import { createRouterTransport } from "@connectrpc/connect"; +import { Code, createRouterTransport } from "@connectrpc/connect"; import { expect, it } from "vitest"; import { accounts, DatasourceService } from "../src/index.js"; @@ -26,8 +26,47 @@ it("carries a caller's declaration precondition through the maintained source cl const expectedDeclarationDigest = `sha256:${"a".repeat(64)}`; await client.invokeSourceOperation({ ...input, expectedDeclarationDigest }); await client.invokeSourceOperation(input); - expect(observed).toEqual([ - { ...input, expectedDeclarationDigest }, - input, - ]); + expect(observed).toEqual([{ ...input, expectedDeclarationDigest }, input]); +}); + +it("verifies the exact original invocation through the maintained public client", async () => { + const input = { + orgId: "11111111-1111-4111-8111-111111111111", + sourceId: "22222222-2222-4222-8222-222222222222", + operation: "read_item", + inputJson: '{ "id": "a" }', + effectId: "retained-call", + expectedDeclarationDigest: `sha256:${"a".repeat(64)}`, + }; + const transport = createRouterTransport(({ service }) => { + service(DatasourceService, { + verifySourceOperationReceipt(request) { + expect( + toJson( + DatasourceService.method.verifySourceOperationReceipt.input, + request, + ), + ).toEqual(input); + return { + outputJson: "{}", + receipt: { + effectId: input.effectId, + status: "committed", + outputJson: "{}", + }, + }; + }, + }); + }); + const response = await accounts + .New(transport) + .datasource() + .verifySourceOperationReceipt(input); + expect(response.receipt?.status).toBe("committed"); + const oldServer = createRouterTransport(({ service }) => { + service(DatasourceService, {}); + }); + await expect( + accounts.New(oldServer).datasource().verifySourceOperationReceipt(input), + ).rejects.toMatchObject({ code: Code.Unimplemented }); }); diff --git a/module/services/frontend/code/src/gen/saas/accounts/v1/datasource_pb.ts b/module/services/frontend/code/src/gen/saas/accounts/v1/datasource_pb.ts index 846d23168..5565af190 100644 --- a/module/services/frontend/code/src/gen/saas/accounts/v1/datasource_pb.ts +++ b/module/services/frontend/code/src/gen/saas/accounts/v1/datasource_pb.ts @@ -18,7 +18,7 @@ import type { JsonObject, Message } from "@bufbuild/protobuf"; * Describes the file saas/accounts/v1/datasource.proto. */ export const file_saas_accounts_v1_datasource: GenFile = /*@__PURE__*/ - fileDesc("CiFzYWFzL2FjY291bnRzL3YxL2RhdGFzb3VyY2UucHJvdG8SEHNhYXMuYWNjb3VudHMudjEiXgoWR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIMCgRyZXBvGAEgASgJEg0KBXBhdGhzGAIgAygJEg4KBmJyYW5jaBgDIAEoCRIXCg9maWxlX2V4dGVuc2lvbnMYBCADKAki9AEKD0FwaU9BdXRoMkNvbmZpZxI2CgVncmFudBgEIAEoDjInLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnLkdyYW50EhEKCXRva2VuX3VybBgBIAEoCRIRCgljbGllbnRfaWQYAiABKAkSDgoGc2NvcGVzGAMgAygJInMKBUdyYW50EhUKEUdSQU5UX1VOU1BFQ0lGSUVEEAASFwoTR1JBTlRfUkVGUkVTSF9UT0tFThABEhwKGEdSQU5UX0NMSUVOVF9DUkVERU5USUFMUxACEhwKGEdSQU5UX0FVVEhPUklaQVRJT05fQ09ERRADIuoBChNBcGlEYXRhc291cmNlQ29uZmlnEhAKCGJhc2VfdXJsGAEgASgJEhUKDXJlc291cmNlX3BhdGgYAiABKAkSPAoPY3JlZGVudGlhbF9raW5kGAMgASgOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIZChFjcmVkZW50aWFsX2hlYWRlchgEIAEoCRIeChZjcmVkZW50aWFsX3F1ZXJ5X3BhcmFtGAUgASgJEjEKBm9hdXRoMhgGIAEoCzIhLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnIkEKF0NyYXdsZXJEYXRhc291cmNlQ29uZmlnEhMKC3NpdGVtYXBfdXJsGAEgASgJEhEKCW1heF9wYWdlcxgCIAEoDSKrAgoWVXBsb2FkRGF0YXNvdXJjZUNvbmZpZxIQCghlbmRwb2ludBgBIAEoCRIOCgZyZWdpb24YAiABKAkSDgoGYnVja2V0GAMgASgJEg4KBnByZWZpeBgEIAEoCRIVCg1hY2Nlc3Nfa2V5X2lkGAUgASgJEhMKC21heF9vYmplY3RzGAYgASgNEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACEkkKD2ZpbGVfZXh0ZW5zaW9ucxgJIAMoCUIwukgtkgEqECAiJnIkEAIYITIeXlwuW0EtWmEtejAtOV1bQS1aYS16MC05Ll8tXSokIoMHCgpEYXRhc291cmNlEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRI2Cghwcm92aWRlchgDIAEoDjIkLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyEjgKBmdpdGh1YhgFIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIyCgZzdGF0dXMYBiABKA4yIi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTdGF0dXMSGgoSd2ViaG9va19jb25maWd1cmVkGAcgASgIEi4KCmNyZWF0ZWRfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDmxhc3Rfc3luY2VkX2F0GAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgNhcGkYCyABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWcSOgoHY3Jhd2xlchgMIAEoCzIpLnNhYXMuYWNjb3VudHMudjEuQ3Jhd2xlckRhdGFzb3VyY2VDb25maWcSOAoGdXBsb2FkGA0gASgLMiguc2Fhcy5hY2NvdW50cy52MS5VcGxvYWREYXRhc291cmNlQ29uZmlnEhgKEGJvdW5kYXJ5X25vZGVfaWQYDiABKAkSNAoQbGFzdF9pbmdlc3RlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHAoUbGFzdF9pbmdlc3RlZF9jb21taXQYECABKAkSFQoNc3RhdHVzX3JlYXNvbhgRIAEoCRIWCg5ib3VuZGFyeV9sYWJlbBgSIAEoCRISCgpjb25mb3JtYW50GBMgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgUIAEoCRI/Cg1saXZlX2RlbGl2ZXJ5GBUgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlTGl2ZURlbGl2ZXJ5EjUKEnJlY29uY2lsZV9pbnRlcnZhbBgWIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkoECAQQBVIRdGFyZ2V0X2NvbGxlY3Rpb24isgMKFkFkZEdpdEh1YlNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI7CgRyZXBvGAIgASgJQi26SCpyKBADGP8BMiFeW0EtWmEtejAtOV8uLV0rL1tBLVphLXowLTlfLi1dKyQSIAoFcGF0aHMYAyADKAlCEbpIDpIBCxBAIgdyBRABGIAEEhgKBmJyYW5jaBgEIAEoCUIIukgFcgMY/wESJAoQYm91bmRhcnlfbm9kZV9pZBgIIAEoCUIIukgFcgOwAQFIABImChBjb2xsZWN0aW9uX2xhYmVsGAkgASgJQgq6SAdyBRABGP8BSAASHgoMYWNjZXNzX3Rva2VuGAYgASgJQgi6SAVyAxiACBIgCg53ZWJob29rX3NlY3JldBgHIAEoCUIIukgFcgMYgAgSSQoPZmlsZV9leHRlbnNpb25zGAogAygJQjC6SC2SASoQICImciQQAhghMh5eXC5bQS1aYS16MC05XVtBLVphLXowLTkuXy1dKiRCEQoIYm91bmRhcnkSBbpIAggBSgQIBRAGUhF0YXJnZXRfY29sbGVjdGlvbiJLChdBZGRHaXRIdWJTb3VyY2VSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsgEChBBZGRTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESQgoIcHJvdmlkZXIYAiABKA4yJC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VQcm92aWRlckIKukgHggEEEAEgABI6CgZnaXRodWIYBCABKAsyKC5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkRhdGFzb3VyY2VDb25maWdIABI0CgNhcGkYBSABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWdIABI8CgdjcmF3bGVyGAggASgLMikuc2Fhcy5hY2NvdW50cy52MS5DcmF3bGVyRGF0YXNvdXJjZUNvbmZpZ0gAEjoKBnVwbG9hZBgJIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuVXBsb2FkRGF0YXNvdXJjZUNvbmZpZ0gAEiQKEGJvdW5kYXJ5X25vZGVfaWQYDCABKAlCCLpIBXIDsAEBSAESJgoQY29sbGVjdGlvbl9sYWJlbBgNIAEoCUIKukgHcgUQARj/AUgBEhwKCmNyZWRlbnRpYWwYBiABKAlCCLpIBXIDGIAgEiAKDndlYmhvb2tfc2VjcmV0GAcgASgJQgi6SAVyAxiACBImChRvYXV0aDJfY2xpZW50X3NlY3JldBgKIAEoCUIIukgFcgMYgAhCCAoGY29uZmlnQhEKCGJvdW5kYXJ5EgW6SAIIAUoECAMQBFIRdGFyZ2V0X2NvbGxlY3Rpb24iRQoRQWRkU291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSLkAgoTVXBkYXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIYCgZicmFuY2gYAyABKAlCCLpIBXIDGP8BEiAKBXBhdGhzGAQgAygJQhG6SA6SAQsQQCIHcgUQARiABBJJCg9maWxlX2V4dGVuc2lvbnMYBSADKAlCMLpILZIBKhAgIiZyJBACGCEyHl5cLltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJBI8CghleHBlY3RlZBgGIAEoCzIiLnNhYXMuYWNjb3VudHMudjEuU291cmNlRmV0Y2hTY29wZUIGukgDyAEBEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACIs8BChBTb3VyY2VGZXRjaFNjb3BlEhgKBmJyYW5jaBgBIAEoCUIIukgFcgMY/wESIAoFcGF0aHMYAiADKAlCEbpIDpIBCxBAIgdyBRABGIAEEikKD2ZpbGVfZXh0ZW5zaW9ucxgDIAMoCUIQukgNkgEKECAiBnIEEAEYIRIpChBpbmNsdWRlX3BhdHRlcm5zGAQgAygJQg+6SAySAQkQECIFcgMYgAISKQoQZXhjbHVkZV9wYXR0ZXJucxgFIAMoCUIPukgMkgEJEBAiBXIDGIACIlgKFFVwZGF0ZVNvdXJjZVJlc3BvbnNlEjAKCmRhdGFzb3VyY2UYASABKAsyHC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2USDgoGam9iX2lkGAIgASgJIloKFURhdGFzb3VyY2VDb25maWdGaWVsZBILCgNrZXkYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEgwKBGhlbHAYAyABKAkSEAoIcmVxdWlyZWQYBCABKAgixAEKGURhdGFzb3VyY2VDb25uZWN0b3JCdWRnZXQSGgoSbWF4X2l0ZW1zX3Blcl9jYWxsGAEgASgNEhoKEm1heF9ieXRlc19wZXJfY2FsbBgCIAEoAxIWCg5tYXhfaXRlbV9ieXRlcxgDIAEoAxIdChVvcGVyYXRpb25zX3Blcl93aW5kb3cYBCABKA0SFgoOd2luZG93X3NlY29uZHMYBSABKAMSIAoYYmFja2dyb3VuZF9zaGFyZV9wZXJjZW50GAYgASgNIqoGChxEYXRhc291cmNlUHJvdmlkZXJEZXNjcmlwdG9yEjYKCHByb3ZpZGVyGAEgASgOMiQuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUHJvdmlkZXISFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEj4KDWNvbmZpZ19maWVsZHMYBCADKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDb25maWdGaWVsZBIYChBzdXBwb3J0c193ZWJob29rGAUgASgIEkcKGnN1cHBvcnRlZF9jcmVkZW50aWFsX2tpbmRzGAYgAygOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIRCgljb25uZWN0b3IYByABKAkSQQoJaW50ZXJmYWNlGAggASgOMi4uc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQ29ubmVjdG9ySW50ZXJmYWNlEkQKEGNyZWRlbnRpYWxfbW9kZXMYCSADKA4yKi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRI/Cg1yZWFkZXJzX21vZGVsGAogASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUmVhZGVyc01vZGVsEjsKBmJ1ZGdldBgLIAEoCzIrLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUNvbm5lY3RvckJ1ZGdldBISCgpjb25mb3JtYW50GAwgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgNIAEoCRIbChNhY2NlcHRzX25ld19zb3VyY2VzGA4gASgIEiAKGGxpdmVfZGVsaXZlcnlfY29uZmlndXJlZBgPIAEoCBIaChJhY2NlcHRzX29wZXJhdGlvbnMYECABKAgSFgoOb3BlcmF0aW9uc19nYXAYESABKAkSGwoTb2F1dGhfYXV0aG9yaXplX3VybBgSIAEoCRIXCg9vYXV0aF90b2tlbl91cmwYEyABKAkSFAoMb2F1dGhfc2NvcGVzGBQgAygJIh0KG0dldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdCJhChxHZXREYXRhc291cmNlQ2F0YWxvZ1Jlc3BvbnNlEkEKCXByb3ZpZGVycxgBIAMoCzIuLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyRGVzY3JpcHRvciIuChJMaXN0U291cmNlc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJIChNMaXN0U291cmNlc1Jlc3BvbnNlEjEKC2RhdGFzb3VyY2VzGAEgAygLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIkIKEEdldFNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiRQoRR2V0U291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSJ2ChFTeW5jU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIeCgxhY2Nlc3NfdG9rZW4YAyABKAlCCLpIBXIDGIAgEhEKCXJlY29ubmVjdBgEIAEoCCIkChJTeW5jU291cmNlUmVzcG9uc2USDgoGam9iX2lkGAEgASgJImoKFEdldFNvdXJjZVN5bmNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgZqb2JfaWQYAyABKAlCC7pICNgBAXIDsAEBIpUBChJTb3VyY2VTeW5jRGVsaXZlcnkSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARItCgVzdGF0ZRgCIAEoDjIWLnNhYXMuam9icy52MS5Kb2JTdGF0ZUIGukgDyAEBEjYKCWV4ZWN1dGlvbhgDIAEoCzIjLnNhYXMuam9icy52MS5Kb2JFeGVjdXRpb25SZWZlcmVuY2UiiwEKEVNvdXJjZVN5bmNDaGFuZ2VzEg0KBWZpbGVzGAEgASgNEg0KBWFkZGVkGAIgASgNEhAKCG1vZGlmaWVkGAMgASgNEg8KB2RlbGV0ZWQYBCABKA0SEwoLc3BsaXRfa25vd24YBSABKAgSEAoIc25hcHNob3QYBiABKAgSDgoGY29tbWl0GAcgASgJIq0BChFTb3VyY2VTeW5jRmFpbHVyZRI5CgZyZWFzb24YASABKA4yKS5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNGYWlsdXJlUmVhc29uEgwKBGNvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCRIQCghyZXRyeWluZxgEIAEoCBIsCghyZXRyeV9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAQKElNvdXJjZVN5bmNQcm9ncmVzcxIwCgVwaGFzZRgBIAEoDjIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY1BoYXNlEjQKB3RyaWdnZXIYAiABKA4yIy5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNUcmlnZ2VyEi0KCXF1ZXVlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoLZmV0Y2hpbmdfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi8KC2NvbXBpbGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1oYW5kZWRfb2ZmX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIvCgtmaW5pc2hlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoHY2hhbmdlcxgIIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0NoYW5nZXMSNAoHZmFpbHVyZRgJIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0ZhaWx1cmUSDwoHYXR0ZW1wdBgKIAEoDRIUCgxtYXhfYXR0ZW1wdHMYCyABKA0i0gEKFUdldFNvdXJjZVN5bmNSZXNwb25zZRIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBEi0KBXN0YXRlGAIgASgOMhYuc2Fhcy5qb2JzLnYxLkpvYlN0YXRlQga6SAPIAQESOAoKZGVsaXZlcmllcxgDIAMoCzIkLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0RlbGl2ZXJ5EjYKCHByb2dyZXNzGAQgASgLMiQuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VTeW5jUHJvZ3Jlc3MiRQoTRGVsZXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASIWChREZWxldGVTb3VyY2VSZXNwb25zZSJWChNHaXRIdWJBcHBSZXBvc2l0b3J5EgwKBHJlcG8YASABKAkSFgoOZGVmYXVsdF9icmFuY2gYAiABKAkSGQoRYWxyZWFkeV9jb25uZWN0ZWQYAyABKAgiNgoaQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJxChtCZWdpbkdpdEh1YkFwcFNldHVwUmVzcG9uc2USEwoLaW5zdGFsbF91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAinAEKHUNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEY/wESLAoPaW5zdGFsbGF0aW9uX2lkGAMgASgJQhO6SBByDhABGCAyCF5bMC05XSskEhgKBGNvZGUYBCABKAlCCrpIB3IFEAEY/wEidgoeQ29tcGxldGVHaXRIdWJBcHBTZXR1cFJlc3BvbnNlEhcKD2luc3RhbGxhdGlvbl9pZBgBIAEoCRI7CgxyZXBvc2l0b3JpZXMYAiADKAsyJS5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkFwcFJlcG9zaXRvcnkiUQofTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASJUCiBNaWdyYXRlR2l0SHViU291cmNlVG9BcHBSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsQBChVEYXRhc291cmNlQWNjb3VudExpbmsSCgoCaWQYASABKAkSDgoGb3JnX2lkGAIgASgJEg8KB3VzZXJfaWQYAyABKAkSEQoJY29ubmVjdG9yGAQgASgJEhsKE3Byb3ZpZGVyX2FjY291bnRfaWQYBSABKAkSHgoWcHJvdmlkZXJfYWNjb3VudF9sb2dpbhgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK3AQoWRGF0YXNvdXJjZUdyb3VwQmluZGluZxIKCgJpZBgBIAEoCRIOCgZvcmdfaWQYAiABKAkSEQoJY29ubmVjdG9yGAMgASgJEhkKEXByb3ZpZGVyX2dyb3VwX2lkGAQgASgJEg8KB3RlYW1faWQYBSABKAkSEgoKY3JlYXRlZF9ieRgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKUAgoYRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRIOCgZkb21haW4YAyABKAkSOAoGc3RhdHVzGAQgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRG9tYWluU3RhdHVzEhcKD3R4dF9yZWNvcmRfbmFtZRgFIAEoCRIYChB0eHRfcmVjb3JkX3ZhbHVlGAYgASgJEi8KC3ZlcmlmaWVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjcmVhdGVkX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIzChdEYXRhc291cmNlRGlyZWN0b3J5VGVhbRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJIqYBCiFCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIeCgxyZWRpcmVjdF91cmkYAyABKAlCCLpIBXIDGIAQEhEKCXNvdXJjZV9pZBgEIAEoCSJ6CiJCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEhUKDWF1dGhvcml6ZV91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAidQokQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEYgEASGAoEY29kZRgDIAEoCUIKukgHcgUQARj/ASJeCiVDb21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEjUKBGxpbmsYASABKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VBY2NvdW50TGluayI/CiNMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBIl4KJExpc3RNeURhdGFzb3VyY2VBY2NvdW50TGlua3NSZXNwb25zZRI2CgVsaW5rcxgBIAMoCzInLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUFjY291bnRMaW5rIlQKIkRlbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiJQojRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rUmVzcG9uc2UiOQodR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASKLAgoeR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlEjYKBWxpbmtzGAEgAygLMicuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQWNjb3VudExpbmsSOgoIYmluZGluZ3MYAiADKAsyKC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VHcm91cEJpbmRpbmcSOwoHZG9tYWlucxgDIAMoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEjgKBXRlYW1zGAQgAygLMikuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRGlyZWN0b3J5VGVhbSKuAQoaQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIlChFwcm92aWRlcl9ncm91cF9pZBgDIAEoCUIKukgHcgUQARj/ARIZCgd0ZWFtX2lkGAQgASgJQgi6SAVyA7ABASJYChtCaW5kRGF0YXNvdXJjZUdyb3VwUmVzcG9uc2USOQoHYmluZGluZxgBIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUdyb3VwQmluZGluZyJOChxVbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIh8KHVVuYmluZERhdGFzb3VyY2VHcm91cFJlc3BvbnNlIlQKHENsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIaCgZkb21haW4YAiABKAlCCrpIB3IFEAMY/QEiWwodQ2xhaW1EYXRhc291cmNlRG9tYWluUmVzcG9uc2USOgoGZG9tYWluGAEgASgLMiouc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlVmVyaWZpZWREb21haW4iTwodVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiXAoeVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlEjoKBmRvbWFpbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluIk8KHURlbGV0ZURhdGFzb3VyY2VEb21haW5SZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIiAKHkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSKeAgoQU291cmNlRGVsZWdhdGlvbhIKCgJpZBgBIAEoCRIRCglzb3VyY2VfaWQYAiABKAkSFAoMcHJpbmNpcGFsX2lkGAMgASgJEg4KBm1vZHVsZRgEIAEoCRIPCgdiaW5kaW5nGAUgASgJEi4KCmNyZWF0ZWRfYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnJldm9rZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEkAKCnJldm9jYXRpb24YCCABKA4yLC5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb25SZXZvY2F0aW9uEhIKCnJldm9rZWRfYnkYCSABKAkigQEKHExpc3RTb3VyY2VEZWxlZ2F0aW9uc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIgCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBSACIAQESFwoPaW5jbHVkZV9yZXZva2VkGAMgASgIQgwKCl9zb3VyY2VfaWQiWAodTGlzdFNvdXJjZURlbGVnYXRpb25zUmVzcG9uc2USNwoLZGVsZWdhdGlvbnMYASADKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iTwodUmV2b2tlU291cmNlRGVsZWdhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiWAoeUmV2b2tlU291cmNlRGVsZWdhdGlvblJlc3BvbnNlEjYKCmRlbGVnYXRpb24YASABKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iMgoPVHJpZ2dlcklkZW50aXR5Eg4KBnNvdXJjZRgBIAEoCRIPCgdiaW5kaW5nGAIgASgJIoQBChdEZWNsYXJlZFRyaWdnZXJTY2hlZHVsZRIMCgRjcm9uGAEgASgJEhAKCHRpbWV6b25lGAIgASgJEhIKCm1pc3NlZF9ydW4YAyABKAkSDwoHb3ZlcmxhcBgEIAEoCRIQCghkZWFkbGluZRgFIAEoAxISCgppbnB1dF9qc29uGAYgASgJIucCChpUcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRIRCglyZWZlcmVuY2UYASABKAkSFQoNZGVsZWdhdGlvbl9pZBgCIAEoCRIOCgZtb2R1bGUYAyABKAkSDwoHYmluZGluZxgEIAEoCRIQCghhdWRpZW5jZRgFIAEoCRIOCgZ0ZW5hbnQYBiABKAkSGgoSb3duZXJfcHJpbmNpcGFsX2lkGAcgASgJEg4KBnNjb3BlcxgIIAMoCRIOCgZhY3RpdmUYCSABKAgSLgoKY3JlYXRlZF9hdBgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKcmV2b2tlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASQAoKcmV2b2NhdGlvbhgMIAEoDjIsLnNhYXMuYWNjb3VudHMudjEuU291cmNlRGVsZWdhdGlvblJldm9jYXRpb24ivgEKE1RyaWdnZXJDaGlsZENvbnRleHQSFQoNZGVsZWdhdGlvbl9pZBgBIAEoCRIOCgZtb2R1bGUYAiABKAkSDwoHYmluZGluZxgDIAEoCRIQCghhdWRpZW5jZRgEIAEoCRIOCgZzY29wZXMYBSADKAkSDgoGbG9va3VwGAYgASgIEi0KCW1pbnRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGcmVjb3JkGAggASgJIs0CChhTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb24SDwoHcmVsZWFzZRgBIAEoCRIRCglvcGVyYXRpb24YAiABKAkSOwoIc2NoZWR1bGUYAyABKAsyKS5zYWFzLmFjY291bnRzLnYxLkRlY2xhcmVkVHJpZ2dlclNjaGVkdWxlEjMKCGlkZW50aXR5GAQgASgLMiEuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VySWRlbnRpdHkSDgoGZGlnZXN0GAUgASgJEjYKEmxhc3Rfb2NjdXJyZW5jZV9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNgoSbmV4dF9vY2N1cnJlbmNlX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChN1bmRlY2xhcmFibGVfcmVhc29uGAggASgJIlYKHURlbGVnYXRlU291cmNlVHJpZ2dlcnNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABASJjCh5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVzcG9uc2USQQoLZGVsZWdhdGlvbnMYASADKAsyLC5zYWFzLmFjY291bnRzLnYxLlRyaWdnZXJEZWxlZ2F0aW9uUmVmZXJlbmNlIlsKIkdldFNvdXJjZVRyaWdnZXJEZWNsYXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBIuIBCiNHZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZRI/CgtkZWNsYXJhdGlvbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuU291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEkEKC2RlbGVnYXRpb25zGAIgAygLMiwuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRI3CghjaGlsZHJlbhgDIAMoCzIlLnNhYXMuYWNjb3VudHMudjEuVHJpZ2dlckNoaWxkQ29udGV4dCJuChZSZWNvbmNpbGVTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIdCgllZmZlY3RfaWQYAyABKAlCCrpIB3IFEAEYgAEiTAoXUmVjb25jaWxlU291cmNlUmVzcG9uc2USEQoJZWZmZWN0X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIOCgZqb2JfaWQYAyABKAkiPQocTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBIdCgllZmZlY3RfaWQYASABKAlCCrpIB3IFEAEYgAEi8QIKD1NvdXJjZU9wZXJhdGlvbhIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg4KBm1ldGhvZBgDIAEoCRIMCgRwYXRoGAQgASgJEg0KBXF1ZXJ5GAUgAygJEi0KDGlucHV0X3NjaGVtYRgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSLgoNb3V0cHV0X3NjaGVtYRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSOAoGZWZmZWN0GAggASgOMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24uRWZmZWN0EhgKEG1heF9vdXRwdXRfYnl0ZXMYCSABKA0SDgoGZGlnZXN0GAogASgJIksKBkVmZmVjdBIWChJFRkZFQ1RfVU5TUEVDSUZJRUQQABIUChBFRkZFQ1RfUkVBRF9PTkxZEAESEwoPRUZGRUNUX01VVEFUSU9OEAIijgEKHkRlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQESNQoKb3BlcmF0aW9ucxgDIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlgKH0RlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVzcG9uc2USNQoKb3BlcmF0aW9ucxgBIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlQKG0xpc3RTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQEiVQocTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXNwb25zZRI1CgpvcGVyYXRpb25zGAEgAygLMiEuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24irgIKHEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBEjAKCW9wZXJhdGlvbhgDIAEoCUIdukgachgyFl5bYS16XVthLXowLTlfXXswLDYzfSQSHQoKaW5wdXRfanNvbhgEIAEoCUIJukgGcgQogIAEEhsKCWVmZmVjdF9pZBgFIAEoCUIIukgFcgMogAESSQobZXhwZWN0ZWRfZGVjbGFyYXRpb25fZGlnZXN0GAYgASgJQh+6SBxyGjIYXihzaGEyNTY6WzAtOWEtZl17NjR9KT8kSACIAQFCHgocX2V4cGVjdGVkX2RlY2xhcmF0aW9uX2RpZ2VzdCJ/ChZTb3VyY2VPcGVyYXRpb25SZWNlaXB0EhEKCWVmZmVjdF9pZBgBIAEoCRIUCgxjb21taXR0ZWRfYXQYAiABKAkSDgoGc3RhdHVzGAMgASgJEhcKD3Byb3ZpZGVyX3N0YXR1cxgEIAEoDRITCgtvdXRwdXRfanNvbhgFIAEoCSJvCh1JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZRITCgtvdXRwdXRfanNvbhgBIAEoCRI5CgdyZWNlaXB0GAIgASgLMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb25SZWNlaXB0IkMKIkxvb2t1cEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSHQoJZWZmZWN0X2lkGAEgASgJQgq6SAdyBRABKIABInkKI1BydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgllZmZlY3RfaWQYAyABKAlCCLpIBXIDKIABIlsKJFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZRIRCgllZmZlY3RfaWQYASABKAkSEAoIcmVjZWlwdHMYAiABKAMSDgoGc3RhdHVzGAMgASgJIkoKKUxvb2t1cFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0Eh0KCWVmZmVjdF9pZBgBIAEoCUIKukgHcgUQASiAASq3AQoSRGF0YXNvdXJjZVByb3ZpZGVyEiMKH0RBVEFTT1VSQ0VfUFJPVklERVJfVU5TUEVDSUZJRUQQABIeChpEQVRBU09VUkNFX1BST1ZJREVSX0dJVEhVQhABEhsKF0RBVEFTT1VSQ0VfUFJPVklERVJfQVBJEAISHwobREFUQVNPVVJDRV9QUk9WSURFUl9DUkFXTEVSEAMSHgoaREFUQVNPVVJDRV9QUk9WSURFUl9VUExPQUQQBCqRAQoQRGF0YXNvdXJjZVN0YXR1cxIhCh1EQVRBU09VUkNFX1NUQVRVU19VTlNQRUNJRklFRBAAEhwKGERBVEFTT1VSQ0VfU1RBVFVTX0FDVElWRRABEhwKGERBVEFTT1VSQ0VfU1RBVFVTX1BBVVNFRBACEh4KGkRBVEFTT1VSQ0VfU1RBVFVTX0RFR1JBREVEEAMqvAEKFkRhdGFzb3VyY2VMaXZlRGVsaXZlcnkSKAokREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX1VOU1BFQ0lGSUVEEAASIQodREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX05PTkUQARIrCidEQVRBU09VUkNFX0xJVkVfREVMSVZFUllfU09VUkNFX1dFQkhPT0sQAhIoCiREQVRBU09VUkNFX0xJVkVfREVMSVZFUllfQVBQX1dFQkhPT0sQAyrWAQoRQXBpQ3JlZGVudGlhbEtpbmQSIwofQVBJX0NSRURFTlRJQUxfS0lORF9VTlNQRUNJRklFRBAAEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfQkVBUkVSEAESHQoZQVBJX0NSRURFTlRJQUxfS0lORF9CQVNJQxACEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfSEVBREVSEAMSHQoZQVBJX0NSRURFTlRJQUxfS0lORF9RVUVSWRAEEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfT0FVVEgyEAUqpgIKHERhdGFzb3VyY2VDb25uZWN0b3JJbnRlcmZhY2USLgoqREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1VOU1BFQ0lGSUVEEAASKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX0ZJTEVTEAESKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1BBR0VTEAISKgomREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1JFQ09SRFMQAxIrCidEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfTUVTU0FHRVMQBBIpCiVEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfRVZFTlRTEAUq7AEKGERhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRIqCiZEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9VTlNQRUNJRklFRBAAEiMKH0RBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX05PTkUQARImCiJEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9PUkdfQVBQEAISKQolREFUQVNPVVJDRV9DUkVERU5USUFMX01PREVfVVNFUl9PQVVUSBADEiwKKERBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX1NUQVRJQ19TRUNSRVQQBCqXAQoWRGF0YXNvdXJjZVJlYWRlcnNNb2RlbBIoCiREQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfVU5TUEVDSUZJRUQQABIqCiZEQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfU09VUkNFX1NDT1BFRBABEicKI0RBVEFTT1VSQ0VfUkVBREVSU19NT0RFTF9UUkFOU0xBVEVEEAIq7gEKD1NvdXJjZVN5bmNQaGFzZRIhCh1TT1VSQ0VfU1lOQ19QSEFTRV9VTlNQRUNJRklFRBAAEhwKGFNPVVJDRV9TWU5DX1BIQVNFX1FVRVVFRBABEh4KGlNPVVJDRV9TWU5DX1BIQVNFX0ZFVENISU5HEAISHgoaU09VUkNFX1NZTkNfUEhBU0VfQ09NUElMRUQQAxIgChxTT1VSQ0VfU1lOQ19QSEFTRV9IQU5ERURfT0ZGEAQSGgoWU09VUkNFX1NZTkNfUEhBU0VfRE9ORRAFEhwKGFNPVVJDRV9TWU5DX1BIQVNFX0ZBSUxFRBAGKqYDChdTb3VyY2VTeW5jRmFpbHVyZVJlYXNvbhIqCiZTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEisKJ1NPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX1JBVEVfTElNSVRFRBABEikKJVNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX0NSRURFTlRJQUwQAhIsCihTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9BQ0NFU1NfREVOSUVEEAMSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fTk9UX0ZPVU5EEAQSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fVE9PX0xBUkdFEAUSLworU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fSE9TVF9VTkFWQUlMQUJMRRAGEiQKIFNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX09USEVSEAcSLgoqU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fREVMSVZFUllfRkFJTEVEEAgqwgEKEVNvdXJjZVN5bmNUcmlnZ2VyEiMKH1NPVVJDRV9TWU5DX1RSSUdHRVJfVU5TUEVDSUZJRUQQABIeChpTT1VSQ0VfU1lOQ19UUklHR0VSX01BTlVBTBABEiEKHVNPVVJDRV9TWU5DX1RSSUdHRVJfU0NIRURVTEVEEAISHwobU09VUkNFX1NZTkNfVFJJR0dFUl9XRUJIT09LEAMSJAogU09VUkNFX1NZTkNfVFJJR0dFUl9SRUNPTkZJR1VSRUQQBCqPAQoWRGF0YXNvdXJjZURvbWFpblN0YXR1cxIoCiREQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIkCiBEQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfUEVORElORxABEiUKIURBVEFTT1VSQ0VfRE9NQUlOX1NUQVRVU19WRVJJRklFRBACKpUDChpTb3VyY2VEZWxlZ2F0aW9uUmV2b2NhdGlvbhIsCihTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VOU1BFQ0lGSUVEEAASKAokU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVZPS0VEEAESKQolU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVBMQUNFRBACEi8KK1NPVVJDRV9ERUxFR0FUSU9OX1JFVk9DQVRJT05fU09VUkNFX0RFTEVURUQQAxIvCitTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX01FTUJFUl9SRU1PVkVEEAQSMAosU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9QRVJNSVNTSU9OX0xPU1QQBRIuCipTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VTRVJfSU5BQ1RJVkUQBhIwCixTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX0JJTkRJTkdfQ0hBTkdFRBAHMrE5ChFEYXRhc291cmNlU2VydmljZRK5AwocUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI1LnNhYXMuYWNjb3VudHMudjEuUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSKpAsLzGGwIAhADGhFkYXRhc291cmNlOmludm9rZSIRZGF0YXNvdXJjZTppbnZva2UqDwoJc291cmNlX2lkEAQYAzABOiMKH3NhYXMuZGF0YXNvdXJjZS5yZWNlaXB0cy5wcnVuZWQQAkADSARQA1gDYAHa8xi0AQoCCDwSAwjYBBgFIgIIAioLVU5BVkFJTEFCTEUqElJFU09VUkNFX0VYSEFVU1RFRCoHQUJPUlRFRDIPc2Fhcy1kYXRhc291cmNlSkYvc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlU2VydmljZS9Mb29rdXBQcnVuZVNvdXJjZU9wZXJhdGlvblJlY2VpcHRzUIAgWIAgYAFyGAoGc291cmNlEgZpbnZva2USBHJlYWQYARLmAQoiTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI7LnNhYXMuYWNjb3VudHMudjEuTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSJLwvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUANYA2ABEvwDChVJbnZva2VTb3VyY2VPcGVyYXRpb24SLi5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlc3BvbnNlIoEDwvMYbggCEAMaEWRhdGFzb3VyY2U6aW52b2tlIhFkYXRhc291cmNlOmludm9rZSoPCglzb3VyY2VfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEARAA0gEUARYBGAB2vMYrwEKAgg8EgMI2AQYBSICCAIqC1VOQVZBSUxBQkxFKhJSRVNPVVJDRV9FWEhBVVNURUQqB0FCT1JURUQyD3NhYXMtZGF0YXNvdXJjZUo/L3NhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVNlcnZpY2UvTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uUICABFiAgEBgAXIYCgZzb3VyY2USBmludm9rZRIEcmVhZBgBgtPkkwJVOgEqIlAvdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zL3tvcGVyYXRpb259Omludm9rZRKHAgobTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5Mb29rdXBJbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKAAcLzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ADWARgAYLT5JMCLxItL3YxL2RhdGFzb3VyY2Utb3BlcmF0aW9uLXJlY2VpcHRzL3tlZmZlY3RfaWR9EoUCChRMaXN0U291cmNlT3BlcmF0aW9ucxItLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0Gi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIo0BwvMYRAgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKgwKBm9yZ19pZBACGAEwAToCEAFAAUgDUANYA2ABgtPkkwI/Ej0vdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zEpMCChdEZWNsYXJlU291cmNlT3BlcmF0aW9ucxIwLnNhYXMuYWNjb3VudHMudjEuRGVjbGFyZVNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0GjEuc2Fhcy5hY2NvdW50cy52MS5EZWNsYXJlU291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIpIBwvMYRggCEAQqDAoGb3JnX2lkEAIYATABOiYKInNhYXMuZGF0YXNvdXJjZS5vcGVyYXRpb24uZGVjbGFyZWQQAkABSARQA1gDYAGC0+STAkI6ASoiPS92MS9vcmdhbml6YXRpb25zL3tvcmdfaWR9L2RhdGFzb3VyY2VzL3tzb3VyY2VfaWR9L29wZXJhdGlvbnMSrAEKD0FkZEdpdEh1YlNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVzcG9uc2UiRMLzGEAIAhAEKgwKBm9yZ19pZBACGAEwATogChxzYWFzLmRhdGFzb3VyY2Uuc291cmNlLmFkZGVkEAJAAUgEUARYA2ABEpoBCglBZGRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlc3BvbnNlIkTC8xhACAIQBCoMCgZvcmdfaWQQAhgBMAE6IAocc2Fhcy5kYXRhc291cmNlLnNvdXJjZS5hZGRlZBACQAFIBFAEWANgARKlAQoMVXBkYXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UudXBkYXRlZBACQAFIBFACWANgARKPAQoUR2V0RGF0YXNvdXJjZUNhdGFsb2cSLS5zYWFzLmFjY291bnRzLnYxLkdldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdBouLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZUNhdGFsb2dSZXNwb25zZSIYwvMYFAgCEAEwAToCEAFAAUgDUAJYAmABEoIBCgtMaXN0U291cmNlcxIkLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZXNSZXF1ZXN0GiUuc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARJ8CglHZXRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKeAQoKU3luY1NvdXJjZRIjLnNhYXMuYWNjb3VudHMudjEuU3luY1NvdXJjZVJlcXVlc3QaJC5zYWFzLmFjY291bnRzLnYxLlN5bmNTb3VyY2VSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5zb3VyY2Uuc3luY2VkEAJAAUgEUARYAmABEogBCg1HZXRTb3VyY2VTeW5jEiYuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VTeW5jUmVxdWVzdBonLnNhYXMuYWNjb3VudHMudjEuR2V0U291cmNlU3luY1Jlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKlAQoMRGVsZXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UucmVtb3ZlZBACQAFIBFACWAJgARLEAQoTQmVnaW5HaXRIdWJBcHBTZXR1cBIsLnNhYXMuYWNjb3VudHMudjEuQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJlZ2luR2l0SHViQXBwU2V0dXBSZXNwb25zZSJQwvMYTAgCEAQqDAoGb3JnX2lkEAIYATABOiwKKHNhYXMuZGF0YXNvdXJjZS5naXRodWJfYXBwLnNldHVwX3N0YXJ0ZWQQAkABSARQAlgEYAESzwEKFkNvbXBsZXRlR2l0SHViQXBwU2V0dXASLy5zYWFzLmFjY291bnRzLnYxLkNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZUdpdEh1YkFwcFNldHVwUmVzcG9uc2UiUsLzGE4IAhAEKgwKBm9yZ19pZBACGAEwATouCipzYWFzLmRhdGFzb3VyY2UuZ2l0aHViX2FwcC5zZXR1cF9jb21wbGV0ZWQQAkABSARQBFgDYAESzQEKGE1pZ3JhdGVHaXRIdWJTb3VyY2VUb0FwcBIxLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBoyLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuY3JlZGVudGlhbC51cGRhdGVkEAJAAUgEUAJYA2ABEtUBChpCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGluaxIzLnNhYXMuYWNjb3VudHMudjEuQmVnaW5EYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjQuc2Fhcy5hY2NvdW50cy52MS5CZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkzC8xhICAIQAyoMCgZvcmdfaWQQAhgBMAE6KAokc2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua19zdGFydGVkEAJAAUgEUAJYBGABEtgBCh1Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGluaxI2LnNhYXMuYWNjb3VudHMudjEuQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0Gjcuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkbC8xhCCAIQAyoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua2VkEAJAAUgEUARYA2ABErUBChxMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzEjUuc2Fhcy5hY2NvdW50cy52MS5MaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBo2LnNhYXMuYWNjb3VudHMudjEuTGlzdE15RGF0YXNvdXJjZUFjY291bnRMaW5rc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARLUAQobRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rEjQuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXNwb25zZSJIwvMYRAgCEAMqDAoGb3JnX2lkEAIYATABOiQKIHNhYXMuZGF0YXNvdXJjZS5hY2NvdW50X3VubGlua2VkEAJAAUgEUAJYA2ABEqMBChZHZXREYXRhc291cmNlRGlyZWN0b3J5Ei8uc2Fhcy5hY2NvdW50cy52MS5HZXREYXRhc291cmNlRGlyZWN0b3J5UmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARK3AQoTQmluZERhdGFzb3VyY2VHcm91cBIsLnNhYXMuYWNjb3VudHMudjEuQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJDwvMYPwgCEAQqDAoGb3JnX2lkEAIYATABOh8KG3NhYXMuZGF0YXNvdXJjZS5ncm91cF9ib3VuZBACQAFIBFACWANgARK/AQoVVW5iaW5kRGF0YXNvdXJjZUdyb3VwEi4uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5ncm91cF91bmJvdW5kEAJAAUgEUAJYA2ABEsABChVDbGFpbURhdGFzb3VyY2VEb21haW4SLi5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkbC8xhCCAIQBCoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmRvbWFpbl9jbGFpbWVkEAJAAUgEUAJYA2ABEsQBChZWZXJpZnlEYXRhc291cmNlRG9tYWluEi8uc2Fhcy5hY2NvdW50cy52MS5WZXJpZnlEYXRhc291cmNlRG9tYWluUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkfC8xhDCAIQBCoMCgZvcmdfaWQQAhgBMAE6Iwofc2Fhcy5kYXRhc291cmNlLmRvbWFpbl92ZXJpZmllZBACQAFIBFACWANgARLDAQoWRGVsZXRlRGF0YXNvdXJjZURvbWFpbhIvLnNhYXMuYWNjb3VudHMudjEuRGVsZXRlRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaMC5zYWFzLmFjY291bnRzLnYxLkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5kb21haW5fcmVtb3ZlZBACQAFIBFACWANgARKgAQoVTGlzdFNvdXJjZURlbGVnYXRpb25zEi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESxwEKFlJldm9rZVNvdXJjZURlbGVnYXRpb24SLy5zYWFzLmFjY291bnRzLnYxLlJldm9rZVNvdXJjZURlbGVnYXRpb25SZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5SZXZva2VTb3VyY2VEZWxlZ2F0aW9uUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuZGVsZWdhdGlvbi5yZXZva2VkEAJAAUgEUAJYA2ABEusBChZEZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzEi8uc2Fhcy5hY2NvdW50cy52MS5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuRGVsZWdhdGVTb3VyY2VUcmlnZ2Vyc1Jlc3BvbnNlIm7C8xhqCAIQBCoMCgZvcmdfaWQQAhgBMAE6Sgoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24uY3JlYXRlZAoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24ucmV2b2tlZBACQAFIBFACWANgARKyAQobR2V0U291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESgwMKD1JlY29uY2lsZVNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UimgLC8xhqCAIQAxoRZGF0YXNvdXJjZTppbnZva2UiEWRhdGFzb3VyY2U6aW52b2tlKg8KCXNvdXJjZV9pZBAEGAMwATohCh1zYWFzLmRhdGFzb3VyY2Uuc291cmNlLnN5bmNlZBACQANIBFACWAJgAdrzGKcBCgIIPBIDCNgEGAUiAggCKgtVTkFWQUlMQUJMRSoSUkVTT1VSQ0VfRVhIQVVTVEVEKgdBQk9SVEVEMg9zYWFzLWRhdGFzb3VyY2VKOS9zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTZXJ2aWNlL0xvb2t1cFJlY29uY2lsZVNvdXJjZVCAIFiAIGABchgKBnNvdXJjZRIGaW52b2tlEgRyZWFkGAESvwEKFUxvb2t1cFJlY29uY2lsZVNvdXJjZRIuLnNhYXMuYWNjb3VudHMudjEuTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UiS8LzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ACWAJgAUK3AQoUY29tLnNhYXMuYWNjb3VudHMudjFCD0RhdGFzb3VyY2VQcm90b1ABWixhY2NvdW50cy9wa2cvZ2VuL3NhYXMvYWNjb3VudHMvdjE7YWNjb3VudHN2MaICA1NBWKoCEFNhYXMuQWNjb3VudHMuVjHKAhBTYWFzXEFjY291bnRzXFYx4gIcU2Fhc1xBY2NvdW50c1xWMVxHUEJNZXRhZGF0YeoCElNhYXM6OkFjY291bnRzOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_codefly_runnable_v0_options, file_google_api_annotations, file_google_protobuf_duration, file_google_protobuf_struct, file_google_protobuf_timestamp, file_saas_jobs_v1_jobs, file_saas_policy_v1_options]); + fileDesc("CiFzYWFzL2FjY291bnRzL3YxL2RhdGFzb3VyY2UucHJvdG8SEHNhYXMuYWNjb3VudHMudjEiXgoWR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIMCgRyZXBvGAEgASgJEg0KBXBhdGhzGAIgAygJEg4KBmJyYW5jaBgDIAEoCRIXCg9maWxlX2V4dGVuc2lvbnMYBCADKAki9AEKD0FwaU9BdXRoMkNvbmZpZxI2CgVncmFudBgEIAEoDjInLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnLkdyYW50EhEKCXRva2VuX3VybBgBIAEoCRIRCgljbGllbnRfaWQYAiABKAkSDgoGc2NvcGVzGAMgAygJInMKBUdyYW50EhUKEUdSQU5UX1VOU1BFQ0lGSUVEEAASFwoTR1JBTlRfUkVGUkVTSF9UT0tFThABEhwKGEdSQU5UX0NMSUVOVF9DUkVERU5USUFMUxACEhwKGEdSQU5UX0FVVEhPUklaQVRJT05fQ09ERRADIuoBChNBcGlEYXRhc291cmNlQ29uZmlnEhAKCGJhc2VfdXJsGAEgASgJEhUKDXJlc291cmNlX3BhdGgYAiABKAkSPAoPY3JlZGVudGlhbF9raW5kGAMgASgOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIZChFjcmVkZW50aWFsX2hlYWRlchgEIAEoCRIeChZjcmVkZW50aWFsX3F1ZXJ5X3BhcmFtGAUgASgJEjEKBm9hdXRoMhgGIAEoCzIhLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnIkEKF0NyYXdsZXJEYXRhc291cmNlQ29uZmlnEhMKC3NpdGVtYXBfdXJsGAEgASgJEhEKCW1heF9wYWdlcxgCIAEoDSKrAgoWVXBsb2FkRGF0YXNvdXJjZUNvbmZpZxIQCghlbmRwb2ludBgBIAEoCRIOCgZyZWdpb24YAiABKAkSDgoGYnVja2V0GAMgASgJEg4KBnByZWZpeBgEIAEoCRIVCg1hY2Nlc3Nfa2V5X2lkGAUgASgJEhMKC21heF9vYmplY3RzGAYgASgNEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACEkkKD2ZpbGVfZXh0ZW5zaW9ucxgJIAMoCUIwukgtkgEqECAiJnIkEAIYITIeXlwuW0EtWmEtejAtOV1bQS1aYS16MC05Ll8tXSokIoMHCgpEYXRhc291cmNlEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRI2Cghwcm92aWRlchgDIAEoDjIkLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyEjgKBmdpdGh1YhgFIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIyCgZzdGF0dXMYBiABKA4yIi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTdGF0dXMSGgoSd2ViaG9va19jb25maWd1cmVkGAcgASgIEi4KCmNyZWF0ZWRfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDmxhc3Rfc3luY2VkX2F0GAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgNhcGkYCyABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWcSOgoHY3Jhd2xlchgMIAEoCzIpLnNhYXMuYWNjb3VudHMudjEuQ3Jhd2xlckRhdGFzb3VyY2VDb25maWcSOAoGdXBsb2FkGA0gASgLMiguc2Fhcy5hY2NvdW50cy52MS5VcGxvYWREYXRhc291cmNlQ29uZmlnEhgKEGJvdW5kYXJ5X25vZGVfaWQYDiABKAkSNAoQbGFzdF9pbmdlc3RlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHAoUbGFzdF9pbmdlc3RlZF9jb21taXQYECABKAkSFQoNc3RhdHVzX3JlYXNvbhgRIAEoCRIWCg5ib3VuZGFyeV9sYWJlbBgSIAEoCRISCgpjb25mb3JtYW50GBMgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgUIAEoCRI/Cg1saXZlX2RlbGl2ZXJ5GBUgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlTGl2ZURlbGl2ZXJ5EjUKEnJlY29uY2lsZV9pbnRlcnZhbBgWIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkoECAQQBVIRdGFyZ2V0X2NvbGxlY3Rpb24isgMKFkFkZEdpdEh1YlNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI7CgRyZXBvGAIgASgJQi26SCpyKBADGP8BMiFeW0EtWmEtejAtOV8uLV0rL1tBLVphLXowLTlfLi1dKyQSIAoFcGF0aHMYAyADKAlCEbpIDpIBCxBAIgdyBRABGIAEEhgKBmJyYW5jaBgEIAEoCUIIukgFcgMY/wESJAoQYm91bmRhcnlfbm9kZV9pZBgIIAEoCUIIukgFcgOwAQFIABImChBjb2xsZWN0aW9uX2xhYmVsGAkgASgJQgq6SAdyBRABGP8BSAASHgoMYWNjZXNzX3Rva2VuGAYgASgJQgi6SAVyAxiACBIgCg53ZWJob29rX3NlY3JldBgHIAEoCUIIukgFcgMYgAgSSQoPZmlsZV9leHRlbnNpb25zGAogAygJQjC6SC2SASoQICImciQQAhghMh5eXC5bQS1aYS16MC05XVtBLVphLXowLTkuXy1dKiRCEQoIYm91bmRhcnkSBbpIAggBSgQIBRAGUhF0YXJnZXRfY29sbGVjdGlvbiJLChdBZGRHaXRIdWJTb3VyY2VSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsgEChBBZGRTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESQgoIcHJvdmlkZXIYAiABKA4yJC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VQcm92aWRlckIKukgHggEEEAEgABI6CgZnaXRodWIYBCABKAsyKC5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkRhdGFzb3VyY2VDb25maWdIABI0CgNhcGkYBSABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWdIABI8CgdjcmF3bGVyGAggASgLMikuc2Fhcy5hY2NvdW50cy52MS5DcmF3bGVyRGF0YXNvdXJjZUNvbmZpZ0gAEjoKBnVwbG9hZBgJIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuVXBsb2FkRGF0YXNvdXJjZUNvbmZpZ0gAEiQKEGJvdW5kYXJ5X25vZGVfaWQYDCABKAlCCLpIBXIDsAEBSAESJgoQY29sbGVjdGlvbl9sYWJlbBgNIAEoCUIKukgHcgUQARj/AUgBEhwKCmNyZWRlbnRpYWwYBiABKAlCCLpIBXIDGIAgEiAKDndlYmhvb2tfc2VjcmV0GAcgASgJQgi6SAVyAxiACBImChRvYXV0aDJfY2xpZW50X3NlY3JldBgKIAEoCUIIukgFcgMYgAhCCAoGY29uZmlnQhEKCGJvdW5kYXJ5EgW6SAIIAUoECAMQBFIRdGFyZ2V0X2NvbGxlY3Rpb24iRQoRQWRkU291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSLkAgoTVXBkYXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIYCgZicmFuY2gYAyABKAlCCLpIBXIDGP8BEiAKBXBhdGhzGAQgAygJQhG6SA6SAQsQQCIHcgUQARiABBJJCg9maWxlX2V4dGVuc2lvbnMYBSADKAlCMLpILZIBKhAgIiZyJBACGCEyHl5cLltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJBI8CghleHBlY3RlZBgGIAEoCzIiLnNhYXMuYWNjb3VudHMudjEuU291cmNlRmV0Y2hTY29wZUIGukgDyAEBEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACIs8BChBTb3VyY2VGZXRjaFNjb3BlEhgKBmJyYW5jaBgBIAEoCUIIukgFcgMY/wESIAoFcGF0aHMYAiADKAlCEbpIDpIBCxBAIgdyBRABGIAEEikKD2ZpbGVfZXh0ZW5zaW9ucxgDIAMoCUIQukgNkgEKECAiBnIEEAEYIRIpChBpbmNsdWRlX3BhdHRlcm5zGAQgAygJQg+6SAySAQkQECIFcgMYgAISKQoQZXhjbHVkZV9wYXR0ZXJucxgFIAMoCUIPukgMkgEJEBAiBXIDGIACIlgKFFVwZGF0ZVNvdXJjZVJlc3BvbnNlEjAKCmRhdGFzb3VyY2UYASABKAsyHC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2USDgoGam9iX2lkGAIgASgJIloKFURhdGFzb3VyY2VDb25maWdGaWVsZBILCgNrZXkYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEgwKBGhlbHAYAyABKAkSEAoIcmVxdWlyZWQYBCABKAgixAEKGURhdGFzb3VyY2VDb25uZWN0b3JCdWRnZXQSGgoSbWF4X2l0ZW1zX3Blcl9jYWxsGAEgASgNEhoKEm1heF9ieXRlc19wZXJfY2FsbBgCIAEoAxIWCg5tYXhfaXRlbV9ieXRlcxgDIAEoAxIdChVvcGVyYXRpb25zX3Blcl93aW5kb3cYBCABKA0SFgoOd2luZG93X3NlY29uZHMYBSABKAMSIAoYYmFja2dyb3VuZF9zaGFyZV9wZXJjZW50GAYgASgNIqoGChxEYXRhc291cmNlUHJvdmlkZXJEZXNjcmlwdG9yEjYKCHByb3ZpZGVyGAEgASgOMiQuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUHJvdmlkZXISFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEj4KDWNvbmZpZ19maWVsZHMYBCADKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDb25maWdGaWVsZBIYChBzdXBwb3J0c193ZWJob29rGAUgASgIEkcKGnN1cHBvcnRlZF9jcmVkZW50aWFsX2tpbmRzGAYgAygOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIRCgljb25uZWN0b3IYByABKAkSQQoJaW50ZXJmYWNlGAggASgOMi4uc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQ29ubmVjdG9ySW50ZXJmYWNlEkQKEGNyZWRlbnRpYWxfbW9kZXMYCSADKA4yKi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRI/Cg1yZWFkZXJzX21vZGVsGAogASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUmVhZGVyc01vZGVsEjsKBmJ1ZGdldBgLIAEoCzIrLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUNvbm5lY3RvckJ1ZGdldBISCgpjb25mb3JtYW50GAwgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgNIAEoCRIbChNhY2NlcHRzX25ld19zb3VyY2VzGA4gASgIEiAKGGxpdmVfZGVsaXZlcnlfY29uZmlndXJlZBgPIAEoCBIaChJhY2NlcHRzX29wZXJhdGlvbnMYECABKAgSFgoOb3BlcmF0aW9uc19nYXAYESABKAkSGwoTb2F1dGhfYXV0aG9yaXplX3VybBgSIAEoCRIXCg9vYXV0aF90b2tlbl91cmwYEyABKAkSFAoMb2F1dGhfc2NvcGVzGBQgAygJIh0KG0dldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdCJhChxHZXREYXRhc291cmNlQ2F0YWxvZ1Jlc3BvbnNlEkEKCXByb3ZpZGVycxgBIAMoCzIuLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyRGVzY3JpcHRvciIuChJMaXN0U291cmNlc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJIChNMaXN0U291cmNlc1Jlc3BvbnNlEjEKC2RhdGFzb3VyY2VzGAEgAygLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIkIKEEdldFNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiRQoRR2V0U291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSJ2ChFTeW5jU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIeCgxhY2Nlc3NfdG9rZW4YAyABKAlCCLpIBXIDGIAgEhEKCXJlY29ubmVjdBgEIAEoCCIkChJTeW5jU291cmNlUmVzcG9uc2USDgoGam9iX2lkGAEgASgJImoKFEdldFNvdXJjZVN5bmNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgZqb2JfaWQYAyABKAlCC7pICNgBAXIDsAEBIpUBChJTb3VyY2VTeW5jRGVsaXZlcnkSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARItCgVzdGF0ZRgCIAEoDjIWLnNhYXMuam9icy52MS5Kb2JTdGF0ZUIGukgDyAEBEjYKCWV4ZWN1dGlvbhgDIAEoCzIjLnNhYXMuam9icy52MS5Kb2JFeGVjdXRpb25SZWZlcmVuY2UiiwEKEVNvdXJjZVN5bmNDaGFuZ2VzEg0KBWZpbGVzGAEgASgNEg0KBWFkZGVkGAIgASgNEhAKCG1vZGlmaWVkGAMgASgNEg8KB2RlbGV0ZWQYBCABKA0SEwoLc3BsaXRfa25vd24YBSABKAgSEAoIc25hcHNob3QYBiABKAgSDgoGY29tbWl0GAcgASgJIq0BChFTb3VyY2VTeW5jRmFpbHVyZRI5CgZyZWFzb24YASABKA4yKS5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNGYWlsdXJlUmVhc29uEgwKBGNvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCRIQCghyZXRyeWluZxgEIAEoCBIsCghyZXRyeV9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAQKElNvdXJjZVN5bmNQcm9ncmVzcxIwCgVwaGFzZRgBIAEoDjIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY1BoYXNlEjQKB3RyaWdnZXIYAiABKA4yIy5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNUcmlnZ2VyEi0KCXF1ZXVlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoLZmV0Y2hpbmdfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi8KC2NvbXBpbGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1oYW5kZWRfb2ZmX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIvCgtmaW5pc2hlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoHY2hhbmdlcxgIIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0NoYW5nZXMSNAoHZmFpbHVyZRgJIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0ZhaWx1cmUSDwoHYXR0ZW1wdBgKIAEoDRIUCgxtYXhfYXR0ZW1wdHMYCyABKA0i0gEKFUdldFNvdXJjZVN5bmNSZXNwb25zZRIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBEi0KBXN0YXRlGAIgASgOMhYuc2Fhcy5qb2JzLnYxLkpvYlN0YXRlQga6SAPIAQESOAoKZGVsaXZlcmllcxgDIAMoCzIkLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0RlbGl2ZXJ5EjYKCHByb2dyZXNzGAQgASgLMiQuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VTeW5jUHJvZ3Jlc3MiRQoTRGVsZXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASIWChREZWxldGVTb3VyY2VSZXNwb25zZSJWChNHaXRIdWJBcHBSZXBvc2l0b3J5EgwKBHJlcG8YASABKAkSFgoOZGVmYXVsdF9icmFuY2gYAiABKAkSGQoRYWxyZWFkeV9jb25uZWN0ZWQYAyABKAgiNgoaQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJxChtCZWdpbkdpdEh1YkFwcFNldHVwUmVzcG9uc2USEwoLaW5zdGFsbF91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAinAEKHUNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEY/wESLAoPaW5zdGFsbGF0aW9uX2lkGAMgASgJQhO6SBByDhABGCAyCF5bMC05XSskEhgKBGNvZGUYBCABKAlCCrpIB3IFEAEY/wEidgoeQ29tcGxldGVHaXRIdWJBcHBTZXR1cFJlc3BvbnNlEhcKD2luc3RhbGxhdGlvbl9pZBgBIAEoCRI7CgxyZXBvc2l0b3JpZXMYAiADKAsyJS5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkFwcFJlcG9zaXRvcnkiUQofTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASJUCiBNaWdyYXRlR2l0SHViU291cmNlVG9BcHBSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsQBChVEYXRhc291cmNlQWNjb3VudExpbmsSCgoCaWQYASABKAkSDgoGb3JnX2lkGAIgASgJEg8KB3VzZXJfaWQYAyABKAkSEQoJY29ubmVjdG9yGAQgASgJEhsKE3Byb3ZpZGVyX2FjY291bnRfaWQYBSABKAkSHgoWcHJvdmlkZXJfYWNjb3VudF9sb2dpbhgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK3AQoWRGF0YXNvdXJjZUdyb3VwQmluZGluZxIKCgJpZBgBIAEoCRIOCgZvcmdfaWQYAiABKAkSEQoJY29ubmVjdG9yGAMgASgJEhkKEXByb3ZpZGVyX2dyb3VwX2lkGAQgASgJEg8KB3RlYW1faWQYBSABKAkSEgoKY3JlYXRlZF9ieRgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKUAgoYRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRIOCgZkb21haW4YAyABKAkSOAoGc3RhdHVzGAQgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRG9tYWluU3RhdHVzEhcKD3R4dF9yZWNvcmRfbmFtZRgFIAEoCRIYChB0eHRfcmVjb3JkX3ZhbHVlGAYgASgJEi8KC3ZlcmlmaWVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjcmVhdGVkX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIzChdEYXRhc291cmNlRGlyZWN0b3J5VGVhbRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJIqYBCiFCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIeCgxyZWRpcmVjdF91cmkYAyABKAlCCLpIBXIDGIAQEhEKCXNvdXJjZV9pZBgEIAEoCSJ6CiJCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEhUKDWF1dGhvcml6ZV91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAidQokQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEYgEASGAoEY29kZRgDIAEoCUIKukgHcgUQARj/ASJeCiVDb21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEjUKBGxpbmsYASABKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VBY2NvdW50TGluayI/CiNMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBIl4KJExpc3RNeURhdGFzb3VyY2VBY2NvdW50TGlua3NSZXNwb25zZRI2CgVsaW5rcxgBIAMoCzInLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUFjY291bnRMaW5rIlQKIkRlbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiJQojRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rUmVzcG9uc2UiOQodR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASKLAgoeR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlEjYKBWxpbmtzGAEgAygLMicuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQWNjb3VudExpbmsSOgoIYmluZGluZ3MYAiADKAsyKC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VHcm91cEJpbmRpbmcSOwoHZG9tYWlucxgDIAMoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEjgKBXRlYW1zGAQgAygLMikuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRGlyZWN0b3J5VGVhbSKuAQoaQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIlChFwcm92aWRlcl9ncm91cF9pZBgDIAEoCUIKukgHcgUQARj/ARIZCgd0ZWFtX2lkGAQgASgJQgi6SAVyA7ABASJYChtCaW5kRGF0YXNvdXJjZUdyb3VwUmVzcG9uc2USOQoHYmluZGluZxgBIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUdyb3VwQmluZGluZyJOChxVbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIh8KHVVuYmluZERhdGFzb3VyY2VHcm91cFJlc3BvbnNlIlQKHENsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIaCgZkb21haW4YAiABKAlCCrpIB3IFEAMY/QEiWwodQ2xhaW1EYXRhc291cmNlRG9tYWluUmVzcG9uc2USOgoGZG9tYWluGAEgASgLMiouc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlVmVyaWZpZWREb21haW4iTwodVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiXAoeVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlEjoKBmRvbWFpbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluIk8KHURlbGV0ZURhdGFzb3VyY2VEb21haW5SZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIiAKHkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSKeAgoQU291cmNlRGVsZWdhdGlvbhIKCgJpZBgBIAEoCRIRCglzb3VyY2VfaWQYAiABKAkSFAoMcHJpbmNpcGFsX2lkGAMgASgJEg4KBm1vZHVsZRgEIAEoCRIPCgdiaW5kaW5nGAUgASgJEi4KCmNyZWF0ZWRfYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnJldm9rZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEkAKCnJldm9jYXRpb24YCCABKA4yLC5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb25SZXZvY2F0aW9uEhIKCnJldm9rZWRfYnkYCSABKAkigQEKHExpc3RTb3VyY2VEZWxlZ2F0aW9uc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIgCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBSACIAQESFwoPaW5jbHVkZV9yZXZva2VkGAMgASgIQgwKCl9zb3VyY2VfaWQiWAodTGlzdFNvdXJjZURlbGVnYXRpb25zUmVzcG9uc2USNwoLZGVsZWdhdGlvbnMYASADKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iTwodUmV2b2tlU291cmNlRGVsZWdhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiWAoeUmV2b2tlU291cmNlRGVsZWdhdGlvblJlc3BvbnNlEjYKCmRlbGVnYXRpb24YASABKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iMgoPVHJpZ2dlcklkZW50aXR5Eg4KBnNvdXJjZRgBIAEoCRIPCgdiaW5kaW5nGAIgASgJIoQBChdEZWNsYXJlZFRyaWdnZXJTY2hlZHVsZRIMCgRjcm9uGAEgASgJEhAKCHRpbWV6b25lGAIgASgJEhIKCm1pc3NlZF9ydW4YAyABKAkSDwoHb3ZlcmxhcBgEIAEoCRIQCghkZWFkbGluZRgFIAEoAxISCgppbnB1dF9qc29uGAYgASgJIucCChpUcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRIRCglyZWZlcmVuY2UYASABKAkSFQoNZGVsZWdhdGlvbl9pZBgCIAEoCRIOCgZtb2R1bGUYAyABKAkSDwoHYmluZGluZxgEIAEoCRIQCghhdWRpZW5jZRgFIAEoCRIOCgZ0ZW5hbnQYBiABKAkSGgoSb3duZXJfcHJpbmNpcGFsX2lkGAcgASgJEg4KBnNjb3BlcxgIIAMoCRIOCgZhY3RpdmUYCSABKAgSLgoKY3JlYXRlZF9hdBgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKcmV2b2tlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASQAoKcmV2b2NhdGlvbhgMIAEoDjIsLnNhYXMuYWNjb3VudHMudjEuU291cmNlRGVsZWdhdGlvblJldm9jYXRpb24ivgEKE1RyaWdnZXJDaGlsZENvbnRleHQSFQoNZGVsZWdhdGlvbl9pZBgBIAEoCRIOCgZtb2R1bGUYAiABKAkSDwoHYmluZGluZxgDIAEoCRIQCghhdWRpZW5jZRgEIAEoCRIOCgZzY29wZXMYBSADKAkSDgoGbG9va3VwGAYgASgIEi0KCW1pbnRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGcmVjb3JkGAggASgJIs0CChhTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb24SDwoHcmVsZWFzZRgBIAEoCRIRCglvcGVyYXRpb24YAiABKAkSOwoIc2NoZWR1bGUYAyABKAsyKS5zYWFzLmFjY291bnRzLnYxLkRlY2xhcmVkVHJpZ2dlclNjaGVkdWxlEjMKCGlkZW50aXR5GAQgASgLMiEuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VySWRlbnRpdHkSDgoGZGlnZXN0GAUgASgJEjYKEmxhc3Rfb2NjdXJyZW5jZV9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNgoSbmV4dF9vY2N1cnJlbmNlX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChN1bmRlY2xhcmFibGVfcmVhc29uGAggASgJIlYKHURlbGVnYXRlU291cmNlVHJpZ2dlcnNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABASJjCh5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVzcG9uc2USQQoLZGVsZWdhdGlvbnMYASADKAsyLC5zYWFzLmFjY291bnRzLnYxLlRyaWdnZXJEZWxlZ2F0aW9uUmVmZXJlbmNlIlsKIkdldFNvdXJjZVRyaWdnZXJEZWNsYXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBIuIBCiNHZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZRI/CgtkZWNsYXJhdGlvbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuU291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEkEKC2RlbGVnYXRpb25zGAIgAygLMiwuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRI3CghjaGlsZHJlbhgDIAMoCzIlLnNhYXMuYWNjb3VudHMudjEuVHJpZ2dlckNoaWxkQ29udGV4dCJuChZSZWNvbmNpbGVTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIdCgllZmZlY3RfaWQYAyABKAlCCrpIB3IFEAEYgAEiTAoXUmVjb25jaWxlU291cmNlUmVzcG9uc2USEQoJZWZmZWN0X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIOCgZqb2JfaWQYAyABKAkiPQocTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBIdCgllZmZlY3RfaWQYASABKAlCCrpIB3IFEAEYgAEi8QIKD1NvdXJjZU9wZXJhdGlvbhIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg4KBm1ldGhvZBgDIAEoCRIMCgRwYXRoGAQgASgJEg0KBXF1ZXJ5GAUgAygJEi0KDGlucHV0X3NjaGVtYRgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSLgoNb3V0cHV0X3NjaGVtYRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSOAoGZWZmZWN0GAggASgOMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24uRWZmZWN0EhgKEG1heF9vdXRwdXRfYnl0ZXMYCSABKA0SDgoGZGlnZXN0GAogASgJIksKBkVmZmVjdBIWChJFRkZFQ1RfVU5TUEVDSUZJRUQQABIUChBFRkZFQ1RfUkVBRF9PTkxZEAESEwoPRUZGRUNUX01VVEFUSU9OEAIijgEKHkRlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQESNQoKb3BlcmF0aW9ucxgDIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlgKH0RlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVzcG9uc2USNQoKb3BlcmF0aW9ucxgBIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlQKG0xpc3RTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQEiVQocTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXNwb25zZRI1CgpvcGVyYXRpb25zGAEgAygLMiEuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24irgIKHEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBEjAKCW9wZXJhdGlvbhgDIAEoCUIdukgachgyFl5bYS16XVthLXowLTlfXXswLDYzfSQSHQoKaW5wdXRfanNvbhgEIAEoCUIJukgGcgQogIAEEhsKCWVmZmVjdF9pZBgFIAEoCUIIukgFcgMogAESSQobZXhwZWN0ZWRfZGVjbGFyYXRpb25fZGlnZXN0GAYgASgJQh+6SBxyGjIYXihzaGEyNTY6WzAtOWEtZl17NjR9KT8kSACIAQFCHgocX2V4cGVjdGVkX2RlY2xhcmF0aW9uX2RpZ2VzdCJ/ChZTb3VyY2VPcGVyYXRpb25SZWNlaXB0EhEKCWVmZmVjdF9pZBgBIAEoCRIUCgxjb21taXR0ZWRfYXQYAiABKAkSDgoGc3RhdHVzGAMgASgJEhcKD3Byb3ZpZGVyX3N0YXR1cxgEIAEoDRITCgtvdXRwdXRfanNvbhgFIAEoCSJvCh1JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZRITCgtvdXRwdXRfanNvbhgBIAEoCRI5CgdyZWNlaXB0GAIgASgLMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb25SZWNlaXB0IkMKIkxvb2t1cEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSHQoJZWZmZWN0X2lkGAEgASgJQgq6SAdyBRABKIABInkKI1BydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgllZmZlY3RfaWQYAyABKAlCCLpIBXIDKIABIlsKJFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZRIRCgllZmZlY3RfaWQYASABKAkSEAoIcmVjZWlwdHMYAiABKAMSDgoGc3RhdHVzGAMgASgJIkoKKUxvb2t1cFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0Eh0KCWVmZmVjdF9pZBgBIAEoCUIKukgHcgUQASiAASq3AQoSRGF0YXNvdXJjZVByb3ZpZGVyEiMKH0RBVEFTT1VSQ0VfUFJPVklERVJfVU5TUEVDSUZJRUQQABIeChpEQVRBU09VUkNFX1BST1ZJREVSX0dJVEhVQhABEhsKF0RBVEFTT1VSQ0VfUFJPVklERVJfQVBJEAISHwobREFUQVNPVVJDRV9QUk9WSURFUl9DUkFXTEVSEAMSHgoaREFUQVNPVVJDRV9QUk9WSURFUl9VUExPQUQQBCqRAQoQRGF0YXNvdXJjZVN0YXR1cxIhCh1EQVRBU09VUkNFX1NUQVRVU19VTlNQRUNJRklFRBAAEhwKGERBVEFTT1VSQ0VfU1RBVFVTX0FDVElWRRABEhwKGERBVEFTT1VSQ0VfU1RBVFVTX1BBVVNFRBACEh4KGkRBVEFTT1VSQ0VfU1RBVFVTX0RFR1JBREVEEAMqvAEKFkRhdGFzb3VyY2VMaXZlRGVsaXZlcnkSKAokREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX1VOU1BFQ0lGSUVEEAASIQodREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX05PTkUQARIrCidEQVRBU09VUkNFX0xJVkVfREVMSVZFUllfU09VUkNFX1dFQkhPT0sQAhIoCiREQVRBU09VUkNFX0xJVkVfREVMSVZFUllfQVBQX1dFQkhPT0sQAyrWAQoRQXBpQ3JlZGVudGlhbEtpbmQSIwofQVBJX0NSRURFTlRJQUxfS0lORF9VTlNQRUNJRklFRBAAEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfQkVBUkVSEAESHQoZQVBJX0NSRURFTlRJQUxfS0lORF9CQVNJQxACEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfSEVBREVSEAMSHQoZQVBJX0NSRURFTlRJQUxfS0lORF9RVUVSWRAEEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfT0FVVEgyEAUqpgIKHERhdGFzb3VyY2VDb25uZWN0b3JJbnRlcmZhY2USLgoqREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1VOU1BFQ0lGSUVEEAASKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX0ZJTEVTEAESKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1BBR0VTEAISKgomREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1JFQ09SRFMQAxIrCidEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfTUVTU0FHRVMQBBIpCiVEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfRVZFTlRTEAUq7AEKGERhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRIqCiZEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9VTlNQRUNJRklFRBAAEiMKH0RBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX05PTkUQARImCiJEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9PUkdfQVBQEAISKQolREFUQVNPVVJDRV9DUkVERU5USUFMX01PREVfVVNFUl9PQVVUSBADEiwKKERBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX1NUQVRJQ19TRUNSRVQQBCqXAQoWRGF0YXNvdXJjZVJlYWRlcnNNb2RlbBIoCiREQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfVU5TUEVDSUZJRUQQABIqCiZEQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfU09VUkNFX1NDT1BFRBABEicKI0RBVEFTT1VSQ0VfUkVBREVSU19NT0RFTF9UUkFOU0xBVEVEEAIq7gEKD1NvdXJjZVN5bmNQaGFzZRIhCh1TT1VSQ0VfU1lOQ19QSEFTRV9VTlNQRUNJRklFRBAAEhwKGFNPVVJDRV9TWU5DX1BIQVNFX1FVRVVFRBABEh4KGlNPVVJDRV9TWU5DX1BIQVNFX0ZFVENISU5HEAISHgoaU09VUkNFX1NZTkNfUEhBU0VfQ09NUElMRUQQAxIgChxTT1VSQ0VfU1lOQ19QSEFTRV9IQU5ERURfT0ZGEAQSGgoWU09VUkNFX1NZTkNfUEhBU0VfRE9ORRAFEhwKGFNPVVJDRV9TWU5DX1BIQVNFX0ZBSUxFRBAGKqYDChdTb3VyY2VTeW5jRmFpbHVyZVJlYXNvbhIqCiZTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEisKJ1NPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX1JBVEVfTElNSVRFRBABEikKJVNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX0NSRURFTlRJQUwQAhIsCihTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9BQ0NFU1NfREVOSUVEEAMSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fTk9UX0ZPVU5EEAQSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fVE9PX0xBUkdFEAUSLworU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fSE9TVF9VTkFWQUlMQUJMRRAGEiQKIFNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX09USEVSEAcSLgoqU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fREVMSVZFUllfRkFJTEVEEAgqwgEKEVNvdXJjZVN5bmNUcmlnZ2VyEiMKH1NPVVJDRV9TWU5DX1RSSUdHRVJfVU5TUEVDSUZJRUQQABIeChpTT1VSQ0VfU1lOQ19UUklHR0VSX01BTlVBTBABEiEKHVNPVVJDRV9TWU5DX1RSSUdHRVJfU0NIRURVTEVEEAISHwobU09VUkNFX1NZTkNfVFJJR0dFUl9XRUJIT09LEAMSJAogU09VUkNFX1NZTkNfVFJJR0dFUl9SRUNPTkZJR1VSRUQQBCqPAQoWRGF0YXNvdXJjZURvbWFpblN0YXR1cxIoCiREQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIkCiBEQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfUEVORElORxABEiUKIURBVEFTT1VSQ0VfRE9NQUlOX1NUQVRVU19WRVJJRklFRBACKpUDChpTb3VyY2VEZWxlZ2F0aW9uUmV2b2NhdGlvbhIsCihTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VOU1BFQ0lGSUVEEAASKAokU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVZPS0VEEAESKQolU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVBMQUNFRBACEi8KK1NPVVJDRV9ERUxFR0FUSU9OX1JFVk9DQVRJT05fU09VUkNFX0RFTEVURUQQAxIvCitTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX01FTUJFUl9SRU1PVkVEEAQSMAosU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9QRVJNSVNTSU9OX0xPU1QQBRIuCipTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VTRVJfSU5BQ1RJVkUQBhIwCixTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX0JJTkRJTkdfQ0hBTkdFRBAHMrM7ChFEYXRhc291cmNlU2VydmljZRK5AwocUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI1LnNhYXMuYWNjb3VudHMudjEuUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSKpAsLzGGwIAhADGhFkYXRhc291cmNlOmludm9rZSIRZGF0YXNvdXJjZTppbnZva2UqDwoJc291cmNlX2lkEAQYAzABOiMKH3NhYXMuZGF0YXNvdXJjZS5yZWNlaXB0cy5wcnVuZWQQAkADSARQA1gDYAHa8xi0AQoCCDwSAwjYBBgFIgIIAioLVU5BVkFJTEFCTEUqElJFU09VUkNFX0VYSEFVU1RFRCoHQUJPUlRFRDIPc2Fhcy1kYXRhc291cmNlSkYvc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlU2VydmljZS9Mb29rdXBQcnVuZVNvdXJjZU9wZXJhdGlvblJlY2VpcHRzUIAgWIAgYAFyGAoGc291cmNlEgZpbnZva2USBHJlYWQYARLmAQoiTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI7LnNhYXMuYWNjb3VudHMudjEuTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSJLwvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUANYA2ABEvwDChVJbnZva2VTb3VyY2VPcGVyYXRpb24SLi5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlc3BvbnNlIoEDwvMYbggCEAMaEWRhdGFzb3VyY2U6aW52b2tlIhFkYXRhc291cmNlOmludm9rZSoPCglzb3VyY2VfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEARAA0gEUARYBGAB2vMYrwEKAgg8EgMI2AQYBSICCAIqC1VOQVZBSUxBQkxFKhJSRVNPVVJDRV9FWEhBVVNURUQqB0FCT1JURUQyD3NhYXMtZGF0YXNvdXJjZUo/L3NhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVNlcnZpY2UvTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uUICABFiAgEBgAXIYCgZzb3VyY2USBmludm9rZRIEcmVhZBgBgtPkkwJVOgEqIlAvdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zL3tvcGVyYXRpb259Omludm9rZRKHAgobTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5Mb29rdXBJbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKAAcLzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ADWARgAYLT5JMCLxItL3YxL2RhdGFzb3VyY2Utb3BlcmF0aW9uLXJlY2VpcHRzL3tlZmZlY3RfaWR9Ev8BChxWZXJpZnlTb3VyY2VPcGVyYXRpb25SZWNlaXB0Ei4uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSJ+wvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUARYBGABgtPkkwItOgEqIigvdjEvZGF0YXNvdXJjZS1vcGVyYXRpb24tcmVjZWlwdHMvdmVyaWZ5EoUCChRMaXN0U291cmNlT3BlcmF0aW9ucxItLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0Gi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIo0BwvMYRAgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKgwKBm9yZ19pZBACGAEwAToCEAFAAUgDUANYA2ABgtPkkwI/Ej0vdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zEpMCChdEZWNsYXJlU291cmNlT3BlcmF0aW9ucxIwLnNhYXMuYWNjb3VudHMudjEuRGVjbGFyZVNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0GjEuc2Fhcy5hY2NvdW50cy52MS5EZWNsYXJlU291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIpIBwvMYRggCEAQqDAoGb3JnX2lkEAIYATABOiYKInNhYXMuZGF0YXNvdXJjZS5vcGVyYXRpb24uZGVjbGFyZWQQAkABSARQA1gDYAGC0+STAkI6ASoiPS92MS9vcmdhbml6YXRpb25zL3tvcmdfaWR9L2RhdGFzb3VyY2VzL3tzb3VyY2VfaWR9L29wZXJhdGlvbnMSrAEKD0FkZEdpdEh1YlNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVzcG9uc2UiRMLzGEAIAhAEKgwKBm9yZ19pZBACGAEwATogChxzYWFzLmRhdGFzb3VyY2Uuc291cmNlLmFkZGVkEAJAAUgEUARYA2ABEpoBCglBZGRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlc3BvbnNlIkTC8xhACAIQBCoMCgZvcmdfaWQQAhgBMAE6IAocc2Fhcy5kYXRhc291cmNlLnNvdXJjZS5hZGRlZBACQAFIBFAEWANgARKlAQoMVXBkYXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UudXBkYXRlZBACQAFIBFACWANgARKPAQoUR2V0RGF0YXNvdXJjZUNhdGFsb2cSLS5zYWFzLmFjY291bnRzLnYxLkdldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdBouLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZUNhdGFsb2dSZXNwb25zZSIYwvMYFAgCEAEwAToCEAFAAUgDUAJYAmABEoIBCgtMaXN0U291cmNlcxIkLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZXNSZXF1ZXN0GiUuc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARJ8CglHZXRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKeAQoKU3luY1NvdXJjZRIjLnNhYXMuYWNjb3VudHMudjEuU3luY1NvdXJjZVJlcXVlc3QaJC5zYWFzLmFjY291bnRzLnYxLlN5bmNTb3VyY2VSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5zb3VyY2Uuc3luY2VkEAJAAUgEUARYAmABEogBCg1HZXRTb3VyY2VTeW5jEiYuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VTeW5jUmVxdWVzdBonLnNhYXMuYWNjb3VudHMudjEuR2V0U291cmNlU3luY1Jlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKlAQoMRGVsZXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UucmVtb3ZlZBACQAFIBFACWAJgARLEAQoTQmVnaW5HaXRIdWJBcHBTZXR1cBIsLnNhYXMuYWNjb3VudHMudjEuQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJlZ2luR2l0SHViQXBwU2V0dXBSZXNwb25zZSJQwvMYTAgCEAQqDAoGb3JnX2lkEAIYATABOiwKKHNhYXMuZGF0YXNvdXJjZS5naXRodWJfYXBwLnNldHVwX3N0YXJ0ZWQQAkABSARQAlgEYAESzwEKFkNvbXBsZXRlR2l0SHViQXBwU2V0dXASLy5zYWFzLmFjY291bnRzLnYxLkNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZUdpdEh1YkFwcFNldHVwUmVzcG9uc2UiUsLzGE4IAhAEKgwKBm9yZ19pZBACGAEwATouCipzYWFzLmRhdGFzb3VyY2UuZ2l0aHViX2FwcC5zZXR1cF9jb21wbGV0ZWQQAkABSARQBFgDYAESzQEKGE1pZ3JhdGVHaXRIdWJTb3VyY2VUb0FwcBIxLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBoyLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuY3JlZGVudGlhbC51cGRhdGVkEAJAAUgEUAJYA2ABEtUBChpCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGluaxIzLnNhYXMuYWNjb3VudHMudjEuQmVnaW5EYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjQuc2Fhcy5hY2NvdW50cy52MS5CZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkzC8xhICAIQAyoMCgZvcmdfaWQQAhgBMAE6KAokc2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua19zdGFydGVkEAJAAUgEUAJYBGABEtgBCh1Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGluaxI2LnNhYXMuYWNjb3VudHMudjEuQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0Gjcuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkbC8xhCCAIQAyoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua2VkEAJAAUgEUARYA2ABErUBChxMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzEjUuc2Fhcy5hY2NvdW50cy52MS5MaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBo2LnNhYXMuYWNjb3VudHMudjEuTGlzdE15RGF0YXNvdXJjZUFjY291bnRMaW5rc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARLUAQobRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rEjQuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXNwb25zZSJIwvMYRAgCEAMqDAoGb3JnX2lkEAIYATABOiQKIHNhYXMuZGF0YXNvdXJjZS5hY2NvdW50X3VubGlua2VkEAJAAUgEUAJYA2ABEqMBChZHZXREYXRhc291cmNlRGlyZWN0b3J5Ei8uc2Fhcy5hY2NvdW50cy52MS5HZXREYXRhc291cmNlRGlyZWN0b3J5UmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARK3AQoTQmluZERhdGFzb3VyY2VHcm91cBIsLnNhYXMuYWNjb3VudHMudjEuQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJDwvMYPwgCEAQqDAoGb3JnX2lkEAIYATABOh8KG3NhYXMuZGF0YXNvdXJjZS5ncm91cF9ib3VuZBACQAFIBFACWANgARK/AQoVVW5iaW5kRGF0YXNvdXJjZUdyb3VwEi4uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5ncm91cF91bmJvdW5kEAJAAUgEUAJYA2ABEsABChVDbGFpbURhdGFzb3VyY2VEb21haW4SLi5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkbC8xhCCAIQBCoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmRvbWFpbl9jbGFpbWVkEAJAAUgEUAJYA2ABEsQBChZWZXJpZnlEYXRhc291cmNlRG9tYWluEi8uc2Fhcy5hY2NvdW50cy52MS5WZXJpZnlEYXRhc291cmNlRG9tYWluUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkfC8xhDCAIQBCoMCgZvcmdfaWQQAhgBMAE6Iwofc2Fhcy5kYXRhc291cmNlLmRvbWFpbl92ZXJpZmllZBACQAFIBFACWANgARLDAQoWRGVsZXRlRGF0YXNvdXJjZURvbWFpbhIvLnNhYXMuYWNjb3VudHMudjEuRGVsZXRlRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaMC5zYWFzLmFjY291bnRzLnYxLkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5kb21haW5fcmVtb3ZlZBACQAFIBFACWANgARKgAQoVTGlzdFNvdXJjZURlbGVnYXRpb25zEi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESxwEKFlJldm9rZVNvdXJjZURlbGVnYXRpb24SLy5zYWFzLmFjY291bnRzLnYxLlJldm9rZVNvdXJjZURlbGVnYXRpb25SZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5SZXZva2VTb3VyY2VEZWxlZ2F0aW9uUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuZGVsZWdhdGlvbi5yZXZva2VkEAJAAUgEUAJYA2ABEusBChZEZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzEi8uc2Fhcy5hY2NvdW50cy52MS5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuRGVsZWdhdGVTb3VyY2VUcmlnZ2Vyc1Jlc3BvbnNlIm7C8xhqCAIQBCoMCgZvcmdfaWQQAhgBMAE6Sgoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24uY3JlYXRlZAoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24ucmV2b2tlZBACQAFIBFACWANgARKyAQobR2V0U291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESgwMKD1JlY29uY2lsZVNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UimgLC8xhqCAIQAxoRZGF0YXNvdXJjZTppbnZva2UiEWRhdGFzb3VyY2U6aW52b2tlKg8KCXNvdXJjZV9pZBAEGAMwATohCh1zYWFzLmRhdGFzb3VyY2Uuc291cmNlLnN5bmNlZBACQANIBFACWAJgAdrzGKcBCgIIPBIDCNgEGAUiAggCKgtVTkFWQUlMQUJMRSoSUkVTT1VSQ0VfRVhIQVVTVEVEKgdBQk9SVEVEMg9zYWFzLWRhdGFzb3VyY2VKOS9zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTZXJ2aWNlL0xvb2t1cFJlY29uY2lsZVNvdXJjZVCAIFiAIGABchgKBnNvdXJjZRIGaW52b2tlEgRyZWFkGAESvwEKFUxvb2t1cFJlY29uY2lsZVNvdXJjZRIuLnNhYXMuYWNjb3VudHMudjEuTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UiS8LzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ACWAJgAUK3AQoUY29tLnNhYXMuYWNjb3VudHMudjFCD0RhdGFzb3VyY2VQcm90b1ABWixhY2NvdW50cy9wa2cvZ2VuL3NhYXMvYWNjb3VudHMvdjE7YWNjb3VudHN2MaICA1NBWKoCEFNhYXMuQWNjb3VudHMuVjHKAhBTYWFzXEFjY291bnRzXFYx4gIcU2Fhc1xBY2NvdW50c1xWMVxHUEJNZXRhZGF0YeoCElNhYXM6OkFjY291bnRzOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_codefly_runnable_v0_options, file_google_api_annotations, file_google_protobuf_duration, file_google_protobuf_struct, file_google_protobuf_timestamp, file_saas_jobs_v1_jobs, file_saas_policy_v1_options]); /** * GitHubDatasourceConfig is the public, non-secret configuration of a GitHub @@ -4227,6 +4227,21 @@ export const DatasourceService: GenService<{ input: typeof LookupInvokeSourceOperationRequestSchema; output: typeof InvokeSourceOperationResponseSchema; }, + /** + * VerifySourceOperationReceipt conditionally reads retained output using the + * exact original Invoke request, including a nonempty declaration precondition. + * Committed means the normalized request and admitted declaration match the + * stored attempt. Unknown remains unresolved; this method never redispatches. + * Current actor, tenant and stored-source read authority apply before comparison. + * This is independent of the paired Runnable Lookup contract above. + * + * @generated from rpc saas.accounts.v1.DatasourceService.VerifySourceOperationReceipt + */ + verifySourceOperationReceipt: { + methodKind: "unary"; + input: typeof InvokeSourceOperationRequestSchema; + output: typeof InvokeSourceOperationResponseSchema; + }, /** * ListSourceOperations reads the currently admitted declarations under source authority. * From 46471a65f9260f074e00990d634c6252c060b9ab Mon Sep 17 00:00:00 2001 From: Gael <338191059+gael-obin@users.noreply.github.com> Date: Tue, 3 Nov 2026 00:10:41 -0500 Subject: [PATCH 2/3] fix(accounts): declare receipt refusal audit and refresh generated clients --- .../source-read-sdk/library.codefly.yaml | 2 +- module/CALLABLE_SOURCES.md | 4 ++++ .../api/accounts/authority/contract.binpb | Bin 1313006 -> 1313202 bytes .../proto/saas/accounts/v1/datasource.proto | 7 ++++++- .../api/accounts/connect/contract.binpb | Bin 1313006 -> 1313202 bytes .../proto/saas/accounts/v1/datasource.proto | 7 ++++++- module/contracts/api/catalog.codefly.json | 4 ++-- module/module.package.codefly.yaml | 4 ++-- module/services/accounts/AUTHZ_MATRIX.md | 2 +- .../adapters/source_operation_verify_test.go | 18 ++++++++++++++++++ .../accountsv1connect/datasource.connect.go | 4 ++++ .../pkg/gen/saas/accounts/v1/datasource.pb.go | 9 +++++---- .../saas/accounts/v1/datasource_grpc.pb.go | 4 ++++ .../accounts/generated/authz-methods.json | 8 +++++--- .../generated/openapi-raw/api.swagger.json | 2 +- .../accounts/generated/service-catalog.json | 6 ++++-- .../accounts/openapi/api.swagger.json | 2 +- .../proto/saas/accounts/v1/datasource.proto | 7 ++++++- .../auth-gateway/code/authz_catalog_gen.go | 2 +- .../generated/contract/catalog.codefly.json | 2 +- .../generated/contract/contract.binpb | Bin 613221 -> 613417 bytes .../saas-sdk/generated/library.codefly.yaml | 2 +- .../src/gen/saas/accounts/v1/datasource_pb.ts | 4 +++- .../src/gen/saas/accounts/v1/datasource_pb.ts | 4 +++- 24 files changed, 79 insertions(+), 25 deletions(-) diff --git a/libraries/source-read-sdk/library.codefly.yaml b/libraries/source-read-sdk/library.codefly.yaml index 161cdad77..900bbe397 100644 --- a/libraries/source-read-sdk/library.codefly.yaml +++ b/libraries/source-read-sdk/library.codefly.yaml @@ -12,7 +12,7 @@ sources: module: saas-starter service: accounts endpoint: authority - contract-digest: sha256:606e52170c2e55688ce163eb1d54c347f0d19ac40915d7fb6252f2034b787c0e + contract-digest: sha256:9aaed4fe30672e6c11675034ae204cec14ecbb299d68a3898b65780a88f80657 services: - ModuleCapabilitiesService generated-by: diff --git a/module/CALLABLE_SOURCES.md b/module/CALLABLE_SOURCES.md index bb1d905a1..e74f8880e 100644 --- a/module/CALLABLE_SOURCES.md +++ b/module/CALLABLE_SOURCES.md @@ -93,6 +93,10 @@ request bound. Matching headers are allowed; conflicting or empty carriers refus Under the verified tenant, the original actor must still hold read authority to the **stored** source, including current delegation, membership, boundary and personal-source checks. Supplied source metadata never grants authority. +The method declares failure-only audit for the existing source-scope/delegation +refusal event (`saas.datasource.operation.invoked`); successful receipt reads +emit no new invocation event. This metadata does not turn verification into a +source mutation or add audit records for every validation or lookup failure. Only after those checks, the host compares the admitted declaration digest and the complete normalized request with the permanent attempt's SDK request digest. diff --git a/module/contracts/api/accounts/authority/contract.binpb b/module/contracts/api/accounts/authority/contract.binpb index b142c4957625704a1ab653026d96cab1eb670ae0..8910e49e90b7f761380144f9f24cc6869a80ff25 100644 GIT binary patch delta 10279 zcmZA7d6X5^odCz4RNk#mu3KfUS7lWOuew(D?v^XZi`VkKa}~Y*RN1w>s-m)2uCjNo>ucq` zdgQ6$-ubHXieCA~-P9fViZ`mFaXIm{71{)ensn!_F8)oX2}V@?mzoXnKa zovTL`N-@&0rlYkW`4z|tq&dnF_t%fm(b0~0h}*|ig^i>+#u4|{&rD=v9nm(^B^6jOtt8V6z_%}8CD%~)w)iVJZ2B&X!D`b`$&S5J0I9;n}&5^28Uh{x+k zjivdnBOa|EWu!U95f9goENR|1)e(=>&unQnjb=u zvQU||njZpXcnEX!L!bymKvF za-H*CdzSakzf>8u>}a{s(&6?C;W|gOPFMv-yv}L!MEVlw>ztov2*E{A0o*yEa zAL|`!1J92*#Pj*U5&xYOR-9pee5mJ#YHg!q?*9Wn8WBI5jgGaS9}Q)AG@JCJp$Hw_ z?1+C#>YgGc{*fcLvpA&?-w}N=!fq1oa!MZO{y1sTMPc$Y)cnZ56(J>*X z2v1>;ehL)fDeP@0uo`7h8|m_fMG;yaLov>cccMlH#ZVjX@pG6N zD+|I|E^kE{bYzyxTTupTvs`RN@u?vLwOZF)!fKgVt=6@cuo`7ho2}I-Ld$bpabL2y zPz0X2t_a&E6qKnYVxG$z24$d_uLndCC>FT9CsPE9g-n5QV%>wpq6Sw%VzH9=1wmL+ zEH8A8kD}=l?B~Pft_YHPvCxg>uDmyW35exxho=$<3lJ+@b2CF&F~kbj+RPA?0b-?w zpa?Cma&g{?&oLCK@~Ly1h_zfk6vJm-)IY)&x?YRWI}rImi%qZ zHnKcdL!qWfB{WM<{A8@1WM7vYC)#WwG#vr!3ye8S;+3NC|WP@j$ zYaU`AJLcKuT8Eg2GVpBIJQShj9h!$C#j_K$>l5ao7(Bbx?1~So6shXjqpc`|)m}Yh zieR-*TTuk7{o0BmSRJT$W2qVhunsD$h4Gs0V8?QeD^br$_JZ)JEBvHh9Q5O;8>EME z2R=vLho4N!$AQl=*SyR=IJK#h+A-I<%s!OC=eYKv2rZw`s}DuW=QH@6Vjqg(b6T%H z6w&H)#x3cPpv57YJgZk9%7FHj9y>)qJFizCihy>3*X&0P%Aj^p+foFyOA76LjOJp; za*csr^z7UAx$wFxvWc3Dj$C(}JdnPG+I9D_=Mps+YByYSfS2xcZmf30wFY?UPDdHk zzR_wFq2+J28bwO&Ce&`R8pTk%t*eS6RaJL%RZ#|@yBdfh0R2smoFV}IT~`%F@agCA zp60eps;a*SpqFV1dQ#MQ#-yn8yY_Fw8jrU$58bHocuVuZQ{(ZL=7DFBXHH}uFXkEK zSreIuGVl!ccuS)QEf4W{OQT5f4D~`W(o45Aior9=<1LLMDylIaZ)tIeCdYcbrBMd6 zaeC+!!EC(82LXy;_Lir&G|GTB!QBAwHifA?LF^7QOjx+ zLv6NJqlnbzMq{U8d7r1D=siF!&`=ZsYN3Xr2vCa{%Ag2Ni#`4ulp;7SQBIpvvx5WWk7phqfvyG*J?D16xuqJ+6G3W7-$S-;{CO@5>WDTClv zEl3drw`oC&Ah_L2&zz4Nl!0(ZgF8XEQxRT^38fVKJmV|~Pa4sOO|6!7GiKPoEC}~` zqD=xO(WQM}+y6{o!f&7Vvx>w|!f(H4o?$=es`Y=rXPsd`%HVfE`%#3J4{AS(l;0uv z9c4d?;de~?QAB4MC4O1>o%f!vO#HI&yWp93 z*e@IVUGS_s>_-{=E^0rD(DEgZk6#oizsvBu#(osT@4EJ*i2T0sO43im;t)-KtNkd0 z-*;MpBKUo;{V0Op5B2;gL;c;-Q`n*+8M1I4g^0`>_M)o<@3f!5y(dSygN_?vN3)- zWetiTHnzcy5PQ>ySOsmUO{JLN8?yoSa_)cdiR|-#>0DkF9VoM8R5Z_iE}Y==$EHm& zyb1n2&n9q90XM;av2Oy`6mXGm)-qhv7%uXyT85(xa1%8gMQC}FhNDQqP4+`Eh2ba$ z+*Ab@A8aX7N04bg|5-#Cz^3bQQv|U0eBLK10@w^c-A)aP05-GUjcwH+AT~>h4UcQA znH2MU;{%ZWH5Xkgvsy(p^X)%|^L)`Rp=pL5&GXxLPG3T5p8rDcM5-C2=KJP)mTDGD z&G)VKEJYcl7HBDo(DFhpMUj$P1gT{#MKPq7>k^}gN^GTH@-GQr9HPlpy51-Q-)gNu z5%|{VdZP$@?=xQqgEIK7ZEz>})+xTJF<*0h;O86rqOyhdlyIZZ`)YIaW24XeYIC4% z^m$)x4zx|axtGzJ$7q{;YcHcw2DHr@jUu%Ckrqk!pa0Y4MG<^HVIPAc@a(R4V|v2fqkLYW3E4u51HSQ9w0DvHyYPU|XSEjS z#sQztYAwKXz~{4C3-BED&2!AtBIY^hTj!XEGVmPIJQShj!Wk5UA;7-)kS!MQnGHZ!F z&o};t8Tmpk+WTv(Y1Dg(-8sDAi&n`LY>5tC@XP)!eF?n_{?o4}GqNT0F8bzO)}!a5 zGV3nuQ3kzBT8|>Md|B&Jr1Y*p?>g&I480p#k0R3h*5^Mu;}A{W)OwUb?|W@P5%hl0 zdK5wL7VC8|D1+YZ26sa5j?x<$&&X12d4cg(bb6^hBJ3Y9S}FR`KVY;{p!E+JtrTbj z0&{$j?v(T)fXb}#LAp~?2DE_z@01jwa2fS@k1hg>$Z<`bWZETS40v!y>fc9pCJApPX0NTJ9t(6oL17kt- z&T@M|I5FU5tQGn(G2msa70@OIyo|L1+N8jo&uFdUc{(Yu<}(^)K%1=5C_>9`Ycz@! z+B-oLF^$nE2HNy!=?Z+^F(WAHn9NLiN3CWvH4|lEs?~#~2u!mz6GdQ}!%PN6P@3D| zMkviwN_}Z!;us+o2gc^0ur!~GI<~i(MfsKX%i&_}RfY~N)?Q`sTCBaw;I$+$H?db) z?6oAYHnA6F@LH<9C_>B2v=>FnYdO5?*o$I#t&Uz?1+VvYSs`Kep+)*cwdR^jvHW zrtN`wn3-C~OxpwNFf&mGrX8AzBDB0yGf||Nc402=W+sZkv`5Xw`0z!M^4S~k;fpf( z?9;=f2tNA*K73IGp99*5BKRDvcVkWs0ziip(A5~I4ZgPujB6;U&vC#Xdmk$5>}q>| zctTfH8+7S}uBbMkI-x774X8c~%&SaA-_xqhy2@0Pf$DQjMG;y)sj2uI-Y2P)sC-b2l<9&`G2})`UhpX*xiJ$qV1AC3 z{0Dmc78-t2^0H4EFvm+?_9+79TauT3ihwymrpvxT5ip|$Hv)5_1m@iM|6Gc5Qp}Xb z%DTxL><5f+rsOk!4jq{(`OKe#-Au`6{v7OP;fs8>quN%PwSw&^gI%q*qX;d})^-#r zyE!rx3)qfg*ez6c@dTwvP0&S>Cn#kATCB%O5rCFRo}d%~XsHIG2tdo~-AG#{gqACz zOT|=f?QpJ^#*Mn8o9&B*;TFkXaJNH8wn+YhyB&bGNdAJm9e}ptn*auC7q4JjrFE2n zCWwXsMH8H$zei$URZN?I^f? zk`HI}j`G~E3yv~)9#jPJ|6@=D&qKQ4D1zr0h7Vin zxvZt{L!@;bF6rQq6#(XV)M*D+mlLvCd+rS00`+I=LDak2#MPfmzmzF(nW8u;#h3Lc zkb>e&eKSNZEemb$dvChgBwG>_3i?i3 zL$c}eL>Y$uy{;gN(DDzuf+$iIbPH1~{ZA_jRR!HvGc2wk$`sojeD0J@moZAg)<4Tr zks?((1F}37DMRTD%<@`A5geer{C2d`s4lT zozcu^db&riw50LLOJkp`t1qdy>PzeG`m%aaUtV8P-+o!H{blP+q2OH3{nyV*mKFx} zb2gRPcS~|LNj$`@NnUu&`S+4PC71gTUjA@t&KB(~TZ$o`^|n`9y{)wHry=fZB}v0D_lbCj zCwk_*T$y@{CG8>JJ&$BBOV!ICy_gI1cd>_|o;}WuPoXq7o z+R`58iEsbERxa(=JrNY`ZG>k}j!cLmK z+TW!5Ww@5pJbNkQmnj3)oTUmsCVh&~pKkOiVP7+hJ|(3;)96!E`m>BaHKjk>6RoL! zJBupt=NWvYSnJO>`t&~NFEIL)puf=QQ-b~?53G6!QG)*BHXA~JiF((6626e4;90wI zcl@%p{|nD2`MyqN^6E(Ur*Xj(T~lj;6EAq(9?o9kN))^w{x&rgFkRuHV?7 zb5`;Fp(8HZN>BVtdWCeu{qe53Kh)kl^GIS02OrScM7x2;~qLv(bwKXk<|w|N!!rK;3$Io>m>lyEt= zd!ldgyKp()H#X zciBr^g#F$>{3N{y=ihU3tm{8y#(3?@BW8Vv_(G;k?QtMO{CuzMCDexaeIHHL+Cy!qZ%_2I1+2YR z8|pg~{cHiF2DM>6FJP3g=huC{K`AM<;eM59@b${n&Y}#p(SA~L$r~Be>(u1Z1oEg4IPQKwr@l2nWYWf}|W|+yg2dc5?}9{& zlK2ThI8rR|t#xqtZtaf;y!^`3e|Yt!=aZKc_mOykFQRm~I5^$~zPvYk35f-M?|!L- z1Br#cy_O{$EwRvd*0KaONGviEl(6T;J|2JcV+|!WdY1UHSk9w|GJpy`Kh{uEqh^J% zq6Vv##)=ZG-Zcu8V71CvQG(U#q76H%lK|Elh4mz1xl(NKt$oRRZ(=ds;PaH^;xIP& zJSDl{+2He(kyp80yp_OM|2*7>B*BzInXz!zaUUOXJf z0YA!~%{}-W@E>?29X=j>4*K>v_VKjOLEkyYKGfiI$oNpgo)4SJhm!I+0-vMoLm57w zC?EZJK#8X8<9D+zx7zE=0ok0Z{KD$U#ng6o!hKN z4QgK)HA>j?Wurz(sa=8ERaT=6wQFWnQBtGox*1i}0Cd9uQ3B9k%$ZXH&|l4{q6D9t zMH^-}-7N+53%cn7De3}id{QyReI~98cts0v7#vohK0?jip za2kVbMWY6uK>@F5l(6T)0k3G36ij4icN;IfO1iZZIh+U2hczL4+ zvxb0|H%c%Y9q{r-31(x0YJ;{xuy`A=D-X_B>V#wc4b>na66>p!Swgql7(AHfofV+S@^; zXl6CaP@9(gbF*6+&j>2Mliqyv9W}OQ8YgOSnr)mY!D)_hq6DY8>|{{_Q%k_Vr&0n_ zt76)eJ_bZmEDfw}L2308JO(U&%IQ$J*6j8wiI)bVCN+w1OiP2V-^pHrY-#Z5^C?*b zvSoq2mB}Jawk&YAG8r|Hy<^BIVb9AA86`zlz(8BYWRyX++6**GG|<)t6%VI?I%1dW z3?MZCZZLq90JzZrQUc(nAe+4&vZz6DbDJ$8xJ3zG(SlNnoq=@%fXA(5U6s?h@Zt>j zXC?8@Ky*vNBo1k3(EYpFOZe>!9v_hUN%-vw?Bnc*6BCuxmj*LK4Qq|dm#JBoH!+reQd}mf$XRmbCe+VNt+EJ zc1(%Aqv!j)6sH2~2E=BR)b@Mf#R0$X|6DTcX(ykE+3xuGR3NfnZSpw1Q$de@DO?_K zr-CQ`kiz8wcRH}IGhAN7oerGq3`Y%cXAB%A?D=fKPhFH0+&K)q3k*jYa2E|6C4&1R zsK`DO(-FJ8Y!s>{NH>FfAIo0C?`H7yf2V$x@Vgb*4PmxIRBFFlfzuFX zD+D$8-8O!du;)9*kCO7ci@9!an5__$;a8u8Etu@fW5auX zkSbL{X>9n^tEo~Il*Wa2Gb>eTrE#It%u3Xt)EM$QN(p-&AMz-pq?9Ivv6#q8l%X^! z*=;F%I;OQuB$JX4D{?5<7%K26GJgdR{Gq?j36 zD>0z{w>G&_<8(X28@jyR6hA+Metfwns2 z)w3he)`a#BM(e22)`ZRuMxzF_wFZq6_Pj3S$23X`ZGBiNHZvM!plwN_g_!8Knh{0c z0m(LVVw6DgXEUNGf#f|Vu_!@gdz%d*^1c%JCEakHq}Ux=Co!IWT-$HJ?|;+(xmTWh zIhno?f2Y_T^7B|HoW$;spT|0ZXLrcYW1YaWC$v9ho=%!)Pw0HgJk-Fm*YHrnp7$9Z zN{Z)$uu2?a9?IZ393}(jg!%Zxu;PJq7}2-XUHFk1M$}+-)SNmcn0;b~5ha)%GiH=v zcD&7oFgu~leobbbF-e^ct-mBSi``$vr$f;tz1KS9FiwXx|Cqf5)9LX0&!)FtXE2=! z?HkNQzecF$++ZeZU^;7nTax(E``Zctzfzw@-L0_EyZ-jFi`{3 zSLSRff$3|*LWWy5orTCT+ ztHu%CGGf&byJf_xA$B{oM@QM>N59Ui=8TTA#g7`q?ievj*z;W@MoEd)MX{)lvc-=w z#9oVdvZ6$j)zFBSLLIToVG%Ed)WA19;-!!h_(nv$6jB1;$S9lZdt21tH>%B+@N0cKa2$;hPgY%k))?_*)dgtdBYPI3bXXw-l< zA>y@=688K?#FG^zg_Z#AEk>gZw8;jI5}{3rD*C3krjFR5TTEMGa^(+H485nF{Syx;Ja2Xo;+~iND-^C2lchH8_kGV^#yR7GqWev)0I7!)7(w ztTl4huo*R&%`;|{u;=;4jFK{20J9}*Mj2*HjTt2}d&dkk9kI*h#*7-wR+uxV1hbXK zj1tV=WwYKEHJGhxvn9+{E3-fAfz}lt{YBOX$-;uWE#4UMeAX4mu`%NLtSitqMm(Q& z1=^;_-p6QNHQJ`g*~e(qfVSD7QNo_L7&J->Z7a~WGa6-}y|2*p--#)yd2C0-4_(yY zv(uah?4S$k~tP4rQO81NSuo+a{a2$ut zpy~#n!)8!*gU^x3{+xZfX`dsJ^EvxagU^S?hZ6Suk@2CVd_ImU#c}qb44)H8xC)Q% zC!_RFi0v%;j$%4xh7mO|oiS%i2~20rFroyebB2i$n9jG^5K5mZrLQXJ)+_Ih*;QH- z3N5SLm+ZJs@`TkL2T~__!s-sEI>{4OcQ_5iGq}uVd3x?u%^5GVS)Ll421%ZC@2@T(2(eO5eG^3#1S4rHq2 zr~6t^PL=$0Ukl16{C%D&YxR(8lFmY=q=s{BHk6dG=V^wLlA@dr%Gpdw8I*Grr3Rv; z#@bxTw| zF8xHX0yG*z+dI{{urw{TIe& z0QE{OD5`(M*rG0({%a96n%tz=&X82q+-AlkB^r}EB|o_7h#$Sn3_ohn-J?M8PZu%9 z8a43lO~+rBz`M`z(!0R>fw>5jF#Ptbo#{UsDy4(?M5Rb+mHM>npmZ)mNniFJHd+ao z4#~LFJ;l*NJS;o(O#g03Z^UIdqApU=wl?1Op$w~;3Hwt_A4zenhzS);$BR9Ye7x}l zJ_@2YKBN9Qihc|L&P(xR@lOW8XA(=A{^t~W7XUt2vr|z5zyCz4RNk#mu3KfUS7lWOuew(D?v^XZi`VkKa}~Y*RN1w>s-m)2uCjNo>ucq` zdgQ6$-ubHXieCA~-P9fViZ`mFaXIm{71{)ensn!_F8)oX2}V@?mzoXnKa zovTL`N-@&0rlYkW`4z|tq&dnF_t%fm(b0~0h}*|ig^i>+#u4|{&rD=v9nm(^B^6jOtt8V6z_%}8CD%~)w)iVJZ2B&X!D`b`$&S5J0I9;n}&5^28Uh{x+k zjivdnBOa|EWu!U95f9goENR|1)e(=>&unQnjb=u zvQU||njZpXcnEX!L!bymKvF za-H*CdzSakzf>8u>}a{s(&6?C;W|gOPFMv-yv}L!MEVlw>ztov2*E{A0o*yEa zAL|`!1J92*#Pj*U5&xYOR-9pee5mJ#YHg!q?*9Wn8WBI5jgGaS9}Q)AG@JCJp$Hw_ z?1+C#>YgGc{*fcLvpA&?-w}N=!fq1oa!MZO{y1sTMPc$Y)cnZ56(J>*X z2v1>;ehL)fDeP@0uo`7h8|m_fMG;yaLov>cccMlH#ZVjX@pG6N zD+|I|E^kE{bYzyxTTupTvs`RN@u?vLwOZF)!fKgVt=6@cuo`7ho2}I-Ld$bpabL2y zPz0X2t_a&E6qKnYVxG$z24$d_uLndCC>FT9CsPE9g-n5QV%>wpq6Sw%VzH9=1wmL+ zEH8A8kD}=l?B~Pft_YHPvCxg>uDmyW35exxho=$<3lJ+@b2CF&F~kbj+RPA?0b-?w zpa?Cma&g{?&oLCK@~Ly1h_zfk6vJm-)IY)&x?YRWI}rImi%qZ zHnKcdL!qWfB{WM<{A8@1WM7vYC)#WwG#vr!3ye8S;+3NC|WP@j$ zYaU`AJLcKuT8Eg2GVpBIJQShj9h!$C#j_K$>l5ao7(Bbx?1~So6shXjqpc`|)m}Yh zieR-*TTuk7{o0BmSRJT$W2qVhunsD$h4Gs0V8?QeD^br$_JZ)JEBvHh9Q5O;8>EME z2R=vLho4N!$AQl=*SyR=IJK#h+A-I<%s!OC=eYKv2rZw`s}DuW=QH@6Vjqg(b6T%H z6w&H)#x3cPpv57YJgZk9%7FHj9y>)qJFizCihy>3*X&0P%Aj^p+foFyOA76LjOJp; za*csr^z7UAx$wFxvWc3Dj$C(}JdnPG+I9D_=Mps+YByYSfS2xcZmf30wFY?UPDdHk zzR_wFq2+J28bwO&Ce&`R8pTk%t*eS6RaJL%RZ#|@yBdfh0R2smoFV}IT~`%F@agCA zp60eps;a*SpqFV1dQ#MQ#-yn8yY_Fw8jrU$58bHocuVuZQ{(ZL=7DFBXHH}uFXkEK zSreIuGVl!ccuS)QEf4W{OQT5f4D~`W(o45Aior9=<1LLMDylIaZ)tIeCdYcbrBMd6 zaeC+!!EC(82LXy;_Lir&G|GTB!QBAwHifA?LF^7QOjx+ zLv6NJqlnbzMq{U8d7r1D=siF!&`=ZsYN3Xr2vCa{%Ag2Ni#`4ulp;7SQBIpvvx5WWk7phqfvyG*J?D16xuqJ+6G3W7-$S-;{CO@5>WDTClv zEl3drw`oC&Ah_L2&zz4Nl!0(ZgF8XEQxRT^38fVKJmV|~Pa4sOO|6!7GiKPoEC}~` zqD=xO(WQM}+y6{o!f&7Vvx>w|!f(H4o?$=es`Y=rXPsd`%HVfE`%#3J4{AS(l;0uv z9c4d?;de~?QAB4MC4O1>o%f!vO#HI&yWp93 z*e@IVUGS_s>_-{=E^0rD(DEgZk6#oizsvBu#(osT@4EJ*i2T0sO43im;t)-KtNkd0 z-*;MpBKUo;{V0Op5B2;gL;c;-Q`n*+8M1I4g^0`>_M)o<@3f!5y(dSygN_?vN3)- zWetiTHnzcy5PQ>ySOsmUO{JLN8?yoSa_)cdiR|-#>0DkF9VoM8R5Z_iE}Y==$EHm& zyb1n2&n9q90XM;av2Oy`6mXGm)-qhv7%uXyT85(xa1%8gMQC}FhNDQqP4+`Eh2ba$ z+*Ab@A8aX7N04bg|5-#Cz^3bQQv|U0eBLK10@w^c-A)aP05-GUjcwH+AT~>h4UcQA znH2MU;{%ZWH5Xkgvsy(p^X)%|^L)`Rp=pL5&GXxLPG3T5p8rDcM5-C2=KJP)mTDGD z&G)VKEJYcl7HBDo(DFhpMUj$P1gT{#MKPq7>k^}gN^GTH@-GQr9HPlpy51-Q-)gNu z5%|{VdZP$@?=xQqgEIK7ZEz>})+xTJF<*0h;O86rqOyhdlyIZZ`)YIaW24XeYIC4% z^m$)x4zx|axtGzJ$7q{;YcHcw2DHr@jUu%Ckrqk!pa0Y4MG<^HVIPAc@a(R4V|v2fqkLYW3E4u51HSQ9w0DvHyYPU|XSEjS z#sQztYAwKXz~{4C3-BED&2!AtBIY^hTj!XEGVmPIJQShj!Wk5UA;7-)kS!MQnGHZ!F z&o};t8Tmpk+WTv(Y1Dg(-8sDAi&n`LY>5tC@XP)!eF?n_{?o4}GqNT0F8bzO)}!a5 zGV3nuQ3kzBT8|>Md|B&Jr1Y*p?>g&I480p#k0R3h*5^Mu;}A{W)OwUb?|W@P5%hl0 zdK5wL7VC8|D1+YZ26sa5j?x<$&&X12d4cg(bb6^hBJ3Y9S}FR`KVY;{p!E+JtrTbj z0&{$j?v(T)fXb}#LAp~?2DE_z@01jwa2fS@k1hg>$Z<`bWZETS40v!y>fc9pCJApPX0NTJ9t(6oL17kt- z&T@M|I5FU5tQGn(G2msa70@OIyo|L1+N8jo&uFdUc{(Yu<}(^)K%1=5C_>9`Ycz@! z+B-oLF^$nE2HNy!=?Z+^F(WAHn9NLiN3CWvH4|lEs?~#~2u!mz6GdQ}!%PN6P@3D| zMkviwN_}Z!;us+o2gc^0ur!~GI<~i(MfsKX%i&_}RfY~N)?Q`sTCBaw;I$+$H?db) z?6oAYHnA6F@LH<9C_>B2v=>FnYdO5?*o$I#t&Uz?1+VvYSs`Kep+)*cwdR^jvHW zrtN`wn3-C~OxpwNFf&mGrX8AzBDB0yGf||Nc402=W+sZkv`5Xw`0z!M^4S~k;fpf( z?9;=f2tNA*K73IGp99*5BKRDvcVkWs0ziip(A5~I4ZgPujB6;U&vC#Xdmk$5>}q>| zctTfH8+7S}uBbMkI-x774X8c~%&SaA-_xqhy2@0Pf$DQjMG;y)sj2uI-Y2P)sC-b2l<9&`G2})`UhpX*xiJ$qV1AC3 z{0Dmc78-t2^0H4EFvm+?_9+79TauT3ihwymrpvxT5ip|$Hv)5_1m@iM|6Gc5Qp}Xb z%DTxL><5f+rsOk!4jq{(`OKe#-Au`6{v7OP;fs8>quN%PwSw&^gI%q*qX;d})^-#r zyE!rx3)qfg*ez6c@dTwvP0&S>Cn#kATCB%O5rCFRo}d%~XsHIG2tdo~-AG#{gqACz zOT|=f?QpJ^#*Mn8o9&B*;TFkXaJNH8wn+YhyB&bGNdAJm9e}ptn*auC7q4JjrFE2n zCWwXsMH8H$zei$URZN?I^f? zk`HI}j`G~E3yv~)9#jPJ|6@=D&qKQ4D1zr0h7Vin zxvZt{L!@;bF6rQq6#(XV)M*D+mlLvCd+rS00`+I=LDak2#MPfmzmzF(nW8u;#h3Lc zkb>e&eKSNZEemb$dvChgBwG>_3i?i3 zL$c}eL>Y$uy{;gN(DDzuf+$iIbPH1~{ZA_jRR!HvGc2wk$`sojeD0J@moZAg)<4Tr zks?((1F}37DMRTD%<@`A5geer{C2d`s4lT zozcu^db&riw50LLOJkp`t1qdy>PzeG`m%aaUtV8P-+o!H{blP+q2OH3{nyV*mKFx} zb2gRPcS~|LNj$`@NnUu&`S+4PC71gTUjA@t&KB(~TZ$o`^|n`9y{)wHry=fZB}v0D_lbCj zCwk_*T$y@{CG8>JJ&$BBOV!ICy_gI1cd>_|o;}WuPoXq7o z+R`58iEsbERxa(=JrNY`ZG>k}j!cLmK z+TW!5Ww@5pJbNkQmnj3)oTUmsCVh&~pKkOiVP7+hJ|(3;)96!E`m>BaHKjk>6RoL! zJBupt=NWvYSnJO>`t&~NFEIL)puf=QQ-b~?53G6!QG)*BHXA~JiF((6626e4;90wI zcl@%p{|nD2`MyqN^6E(Ur*Xj(T~lj;6EAq(9?o9kN))^w{x&rgFkRuHV?7 zb5`;Fp(8HZN>BVtdWCeu{qe53Kh)kl^GIS02OrScM7x2;~qLv(bwKXk<|w|N!!rK;3$Io>m>lyEt= zd!ldgyKp()H#X zciBr^g#F$>{3N{y=ihU3tm{8y#(3?@BW8Vv_(G;k?QtMO{CuzMCDexaeIHHL+Cy!qZ%_2I1+2YR z8|pg~{cHiF2DM>6FJP3g=huC{K`AM<;eM59@b${n&Y}#p(SA~L$r~Be>(u1Z1oEg4IPQKwr@l2nWYWf}|W|+yg2dc5?}9{& zlK2ThI8rR|t#xqtZtaf;y!^`3e|Yt!=aZKc_mOykFQRm~I5^$~zPvYk35f-M?|!L- z1Br#cy_O{$EwRvd*0KaONGviEl(6T;J|2JcV+|!WdY1UHSk9w|GJpy`Kh{uEqh^J% zq6Vv##)=ZG-Zcu8V71CvQG(U#q76H%lK|Elh4mz1xl(NKt$oRRZ(=ds;PaH^;xIP& zJSDl{+2He(kyp80yp_OM|2*7>B*BzInXz!zaUUOXJf z0YA!~%{}-W@E>?29X=j>4*K>v_VKjOLEkyYKGfiI$oNpgo)4SJhm!I+0-vMoLm57w zC?EZJK#8X8<9D+zx7zE=0ok0Z{KD$U#ng6o!hKN z4QgK)HA>j?Wurz(sa=8ERaT=6wQFWnQBtGox*1i}0Cd9uQ3B9k%$ZXH&|l4{q6D9t zMH^-}-7N+53%cn7De3}id{QyReI~98cts0v7#vohK0?jip za2kVbMWY6uK>@F5l(6T)0k3G36ij4icN;IfO1iZZIh+U2hczL4+ zvxb0|H%c%Y9q{r-31(x0YJ;{xuy`A=D-X_B>V#wc4b>na66>p!Swgql7(AHfofV+S@^; zXl6CaP@9(gbF*6+&j>2Mliqyv9W}OQ8YgOSnr)mY!D)_hq6DY8>|{{_Q%k_Vr&0n_ zt76)eJ_bZmEDfw}L2308JO(U&%IQ$J*6j8wiI)bVCN+w1OiP2V-^pHrY-#Z5^C?*b zvSoq2mB}Jawk&YAG8r|Hy<^BIVb9AA86`zlz(8BYWRyX++6**GG|<)t6%VI?I%1dW z3?MZCZZLq90JzZrQUc(nAe+4&vZz6DbDJ$8xJ3zG(SlNnoq=@%fXA(5U6s?h@Zt>j zXC?8@Ky*vNBo1k3(EYpFOZe>!9v_hUN%-vw?Bnc*6BCuxmj*LK4Qq|dm#JBoH!+reQd}mf$XRmbCe+VNt+EJ zc1(%Aqv!j)6sH2~2E=BR)b@Mf#R0$X|6DTcX(ykE+3xuGR3NfnZSpw1Q$de@DO?_K zr-CQ`kiz8wcRH}IGhAN7oerGq3`Y%cXAB%A?D=fKPhFH0+&K)q3k*jYa2E|6C4&1R zsK`DO(-FJ8Y!s>{NH>FfAIo0C?`H7yf2V$x@Vgb*4PmxIRBFFlfzuFX zD+D$8-8O!du;)9*kCO7ci@9!an5__$;a8u8Etu@fW5auX zkSbL{X>9n^tEo~Il*Wa2Gb>eTrE#It%u3Xt)EM$QN(p-&AMz-pq?9Ivv6#q8l%X^! z*=;F%I;OQuB$JX4D{?5<7%K26GJgdR{Gq?j36 zD>0z{w>G&_<8(X28@jyR6hA+Metfwns2 z)w3he)`a#BM(e22)`ZRuMxzF_wFZq6_Pj3S$23X`ZGBiNHZvM!plwN_g_!8Knh{0c z0m(LVVw6DgXEUNGf#f|Vu_!@gdz%d*^1c%JCEakHq}Ux=Co!IWT-$HJ?|;+(xmTWh zIhno?f2Y_T^7B|HoW$;spT|0ZXLrcYW1YaWC$v9ho=%!)Pw0HgJk-Fm*YHrnp7$9Z zN{Z)$uu2?a9?IZ393}(jg!%Zxu;PJq7}2-XUHFk1M$}+-)SNmcn0;b~5ha)%GiH=v zcD&7oFgu~leobbbF-e^ct-mBSi``$vr$f;tz1KS9FiwXx|Cqf5)9LX0&!)FtXE2=! z?HkNQzecF$++ZeZU^;7nTax(E``Zctzfzw@-L0_EyZ-jFi`{3 zSLSRff$3|*LWWy5orTCT+ ztHu%CGGf&byJf_xA$B{oM@QM>N59Ui=8TTA#g7`q?ievj*z;W@MoEd)MX{)lvc-=w z#9oVdvZ6$j)zFBSLLIToVG%Ed)WA19;-!!h_(nv$6jB1;$S9lZdt21tH>%B+@N0cKa2$;hPgY%k))?_*)dgtdBYPI3bXXw-l< zA>y@=688K?#FG^zg_Z#AEk>gZw8;jI5}{3rD*C3krjFR5TTEMGa^(+H485nF{Syx;Ja2Xo;+~iND-^C2lchH8_kGV^#yR7GqWev)0I7!)7(w ztTl4huo*R&%`;|{u;=;4jFK{20J9}*Mj2*HjTt2}d&dkk9kI*h#*7-wR+uxV1hbXK zj1tV=WwYKEHJGhxvn9+{E3-fAfz}lt{YBOX$-;uWE#4UMeAX4mu`%NLtSitqMm(Q& z1=^;_-p6QNHQJ`g*~e(qfVSD7QNo_L7&J->Z7a~WGa6-}y|2*p--#)yd2C0-4_(yY zv(uah?4S$k~tP4rQO81NSuo+a{a2$ut zpy~#n!)8!*gU^x3{+xZfX`dsJ^EvxagU^S?hZ6Suk@2CVd_ImU#c}qb44)H8xC)Q% zC!_RFi0v%;j$%4xh7mO|oiS%i2~20rFroyebB2i$n9jG^5K5mZrLQXJ)+_Ih*;QH- z3N5SLm+ZJs@`TkL2T~__!s-sEI>{4OcQ_5iGq}uVd3x?u%^5GVS)Ll421%ZC@2@T(2(eO5eG^3#1S4rHq2 zr~6t^PL=$0Ukl16{C%D&YxR(8lFmY=q=s{BHk6dG=V^wLlA@dr%Gpdw8I*Grr3Rv; z#@bxTw| zF8xHX0yG*z+dI{{urw{TIe& z0QE{OD5`(M*rG0({%a96n%tz=&X82q+-AlkB^r}EB|o_7h#$Sn3_ohn-J?M8PZu%9 z8a43lO~+rBz`M`z(!0R>fw>5jF#Ptbo#{UsDy4(?M5Rb+mHM>npmZ)mNniFJHd+ao z4#~LFJ;l*NJS;o(O#g03Z^UIdqApU=wl?1Op$w~;3Hwt_A4zenhzS);$BR9Ye7x}l zJ_@2YKBN9Qihc|L&P(xR@lOW8XA(=A{^t~W7XUt2vr|z5zyipj3*u)&6r7MbjEXXCduSP0u8js zp*>CGnf#FyOQRtBA{Q73L}`!)WTzVer9oMZLbC}7BFMfBi=b?p-}}5(&wJB<-f!P} zyXsSK)myi3pIF^%K~t}xbtQFHU1^jzY5>QnGS{LCujas%qiJ;wbKiQ4O22dC|sPJ$rY|o$n+{HZM3Ik9_X0e z`B_;uBg@*fdF|Cl8#0ZLHaHtPmAuw?XQT6!S8?3V+MDC? zoq;9sbJas?`c~dQxNr4KmHC>={zC@$d2w*Q^7mD>`PzY%`N}_34X&*kG$7xRVmYFW(0*23FSOs|LMX z-M3F|RrR2JbxpqSz&?WpRMNmTm9>4U233~#Q(IJ4y;NJ+zsq?x9_5LiSub0rcHENo zDDUpa(wC*`xpbGTdv-2FWtVbr;6@auPiIGS&p`}U-QII{$I;T zdyFT7qS3~A_M8~Q$*eC=d7ANfJ1W(+@ycyAnOzu}38i&MF@|Ky1Wi&IwGvpjKsadM^IYqlpIC~j?~{iY`#$_}KtR3=5e zXRRr$-0cjA>pfACoSQQ2M!nbhC+SO^s(SD7e@|b+f1YRePsT0NCkn}}OpZk-3^LEl z_e)Mm8BXwg&u-!~Ql?;3bDPu|iRqM3#3^~loDxbHYk@f>l+-C{FsFo?IwcFuDWRrL z$s$iIO-@N0iz?2@GWAA1uaM&LrAmLf=ikQ%h8=|d3ZqY(LVu;vrv&{~idD}mO3+{3 zYD3^Rs&~Ce_(F%4A{rY~_4)_FhgpKuCr zuJ`N>e7%U|dRgze8~A$B5$EfDPyAzYth(WP`M_K+YP4q0-fgZIq0dgU=kDg~g&I!I zMsso~VMjN4;xCiyfRaN0&=Xr3ohs0`nah9@T?RWm=V98r!i{~78-HxB0D2G3!6$~2 z63)S=p7?PBP6_8=r#T0da1M60+7RcUMZIft37v$D6bC%(0#3rJlKkWS`u)7B_UXci z{Z3PSz!U8gdNnT&cpZL}zQmb0;QjPh$(hK&?x1I%=ZT%sbO$~6JkwDF-62Cq2_t`Q z=qM?=!(J@DWIM{RJ7(-Ck=<9G^FVTDb;OV-3?MZCo-z)U0C?H}QUc%^zJ>I*s6p^- zt1TgTP6?jXf{qlIJ!@oP-~s1Md|6E?eY2mR8?Cm4 z+Mkr#C5zOuSgw3)S>un6IMpR_z0d1a7CTb!^LmwqTD_0;N zrL0B`YV(a6C5-%zFM1_68cN_<;EOn2JE*B!M1#*u2Q^SEGzUZp6pMUbxG8~RF;n0; zvF1SH-B#~{#1bX(D}r#PSW)U*9~Ry?>ijZZ;fpAlFD`atg)i?(Ujkx<-}{LK!Ue=i z-`>O!u7+6YyPFt-8X#5~2uc`vwU37){jftxO`k?gpS3)FD8px+nm&4IrKEV)8y;%l zdEf9*0?!BLz$t-egW;hBp5~$r?@|W=pN-1rS@LNs#b)2yKkb#b%#x zNo}FC+2>nQTj*@@?R~7%R_ko>-F>V>4LVzm4ke7d&FD~4I@_W13F}aX&ZkC)lG52} zbf`gRmpMpE&}lI`l%TWQ=um>ro}vva5}mzDXR*Fzdswi1>tbQRac5C{&=+AcT|Df^ zK|e|#*gg0h^zVNxnLQqS4*B*4_QAuPdVo9RyBFAp8hk!CK9n%>VRQ4Lq)cZDtiU0NpV_lmPUdIdVz>`rgbc zO7IyP@RH`I*W9oGK>tG5Tp-2Bz?xBb?3DA{7e)rWq6OHEkpZu00eD6RyrKo*c_px? zGf$v-UJ2ak%tH-4uLiuLQNqZh3MHqVTs%4u)#2}Lb zUc;zCX^J^mN>G{_@XAjKO0Nfc4f`oR)KLS|w1DsLlrW77N@!$K)$1=jMQv|^%_ zFEr20 z_-+Cy+Vr-l0dPscA6Y2@aH#^^qyZx-ngZ+N#^{{$L`mEfh%O0JgdJ%Lx;~P=gj!SZ zRNq7`g4&wE-oa{-R$CLeJ6Mex)ZQ~{lrZvIqee-ot%KSIR-+8HW}`-l)HVgqqluc1 z81h4-Mh$A4jT$AWZ82(;ptdzI51iDXwyo8cP}{E5E^9R@MN43vY#e&Qd8s6B2}HMq zNn%G@g6@BpzJyv!@DEjqnuOZ!z&^ohFje>b-GO_8)u=&jk5Qw9k@p%kN=j`X)DE&5 zWvCr8YLrOraFBd1Y=g1zi`6adh*6^kwWH?PDM9T^qecm8$BO0}HK-kLwI$TPQfjO8 zJwGSKnZUYJ=z7Un8J`J6`e7!A{Wuf!cp^c|0qsoi%jyIz2eh++eVfs88trW0-expv zKs#s9C}HID0Y7F@QfL=|cA3#A1MP}IqeN(52TuB@FFHG@VCXy2Garv$Wb4H_k& z-6%q%2DF>z0;L4BTMDgFqqUP_XlP9>e0SMd9S;q~-HB2=?8ngXo~P57KpPr9_lE?n z9ngk__LMMPC);VXVWB%EOxH1h#|*@yev=y+W3&yKuSQH5c0A>31}0;^!j|jq6V}{t+oW(NeMh}g}fY60?*rF`pM6t1f97> z8>UaJ^@?YVo>Lv9Xb7$M3(sG3UW*$-(IWxrfcudp-Mf z&^`-8cRl-1gU=%4LkS}ZMH`1h`;HDR!gDdH_oiMIpl@1Ble>?$ z(3(SDC_4geV`%SUw2m5WW9aT;G-^QGWY8#KN{Am^oNVP&#gA5hW;nl_>o+9$2Y?=|rn7F^f(r zrT-wMyRepp)^}lP#WVRr{6eOE;rBP4C*!lB=$u@1cVUOlhF$(9eF?9#;m@8=uED$D zbuP5;uos;P)!aMmMGao(jTa@1e8Eg7N@_Y?#B{pCdX%Ae)#yC~>My`wa8luQ3A8B@&_-yq z&QeT|tVL02#o&D5*Kgyy)8%*Y1=aM3Z(*IWN7Ey|g>?qs^oVa^oxwLFvKKO6XMK&% zh}?zDM-6;44Id?p{71t_N%6fA{e^gw`6z>Lj^U$3d~X+;zr!Uy*ND;2AU4k&HzkP8 zH)50^_700#lmND%)rJ6TP+&vo8to#*lE~TwuS$HA^kQXg<&%AC3(tM;^pBSqvo1KY zCC01^%$69lE-+gf*&Erci#A&txf|Jx8qAg%GfEhFxiO=p%vQjxktjU;BBD42i z?^B+O*BUbV5y;k?Bc}wi_YD~(kbPjtD1mH4s|`WctjMWGQG?hvBSr}$Z#QC; zl-Lejq@S`FWr*!mV*2Tel3FNtMf~(d4OA`Wh$(?;cf?O$lt8t|P*DQa-l7fj>L6gX zPgz~kR^9N0RAgO-)fXlC!mxT=kY8HmyW_)Va&^Nl9X6Az8>kMO$<+;1Mx zP_4%|_^e7ZUNv_mt5U<^&NHf%F!Fq(N=d1{1Jy;WN*St)m8!O)q%PZcC11AGV70^? zF(p_nm3-M!0@X4@MF~{Pi#DW{6;>;h)%grfyB>J(me$qAy0RLc%$x*D&^@3A(_bnor9=1&Op(%B`Zh$mSD>U%dk-6}1WcdHxYOOm(Ly{d zJM>JxSEM)MG#pVUsc2gpZ~H=q70iV36w^^DzA9ou1=ERQPb432Jc&OY(HnoO{-=t5 z4FE1m@oe#L2Ed;so=x??uh6>ya7o>$iV^@Wt6wokuL}6ztn1PmU1-;?{LT2f+FXC} z-xDX|y5vXOo;a-Q@@MH^uY1Dn8{C_6=}oPto?YKacT_IDsZqnBe`{tJC5(K-%q~i5 zcHPA6O8+y9qMBW|)TGg~i<)A)jXzE0(wiSuuno)cWlBk1ro(f5nNq_<8j<5$8YM8+ i<F$ZssS z@8k-#$)9#PwaJia`Db%~N!Cuyf46vlWB%`Y7M30;FXUx;w{9ax4{6O8hqOBDdgVqI z2W)hn^eQ{b3byEG*;0)1te3sAnyqEU|Jmh?%q3&@I6sU>d17F}E0n9JSkfNl-Suep zuuMJt$Nww@`llFSv}cd=M4_@!p`LCp-PSfxMR%N6UXXxrOb zwDF!jJH~Lb;Ls~qPAZdPyywowXi@qr&~nnA;E8)n6ApBuC+_3%@vO3L(w^jryGxsm zHrW&X3svc{;d$lVq?qD~>0X`&jMaG{3u(_#&&52PGlPm36p7?rc>Mre(sNhwouVTy+B=^3r}PTxhCAh5bEl}$+B|#5vwVq!zC>-FyMyl(YPdqH z%@v}A16|{ZucmhZB_+Ss6B}8cD&#jMO$VH+c#G#e%*T`72U|VoD=8yA8~*PZMoRGC z=7|SOp9TN-jXymL{@c5}5dQ7zSzB^+0rGh%_IlQ-WN?SGIo|7u9;vdrANP9IU&|f> zeXsZJr&9DhnD%-0Nmj~hrG1`zl9i}IX}?jTgpm&zB}z)E!;8g7%tRSXAFBykS#Yst zQOf5qy$^fN*HbhdG2{`0Mh$4k%(+tn+NTDM63~wG;xS173aE84+hx z`Fwv;gW7bT_bEzHo8j~QNeOB%_+pU0We4fs3bmxmE1~wH548&x-Jk_*RKB⪼OT0 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 azLFO=N)R1Z$@euShz>8dR9B36^8Wxnm>VDf diff --git a/module/services/frontend/code/packages/saas-sdk/generated/library.codefly.yaml b/module/services/frontend/code/packages/saas-sdk/generated/library.codefly.yaml index 96346ce8e..c3a871623 100644 --- a/module/services/frontend/code/packages/saas-sdk/generated/library.codefly.yaml +++ b/module/services/frontend/code/packages/saas-sdk/generated/library.codefly.yaml @@ -12,7 +12,7 @@ sources: module: saas-starter service: accounts endpoint: connect - contract-digest: sha256:7e1acbb32e08f5a5a41c5da10fb73b4436c4cb53c991af657d7d80a2648e862e + contract-digest: sha256:9aaed4fe30672e6c11675034ae204cec14ecbb299d68a3898b65780a88f80657 services: - AccessibleScopeService - AuditService diff --git a/module/services/frontend/code/packages/saas-sdk/generated/typescript/src/gen/saas/accounts/v1/datasource_pb.ts b/module/services/frontend/code/packages/saas-sdk/generated/typescript/src/gen/saas/accounts/v1/datasource_pb.ts index b74c9a599..e737e403f 100644 --- a/module/services/frontend/code/packages/saas-sdk/generated/typescript/src/gen/saas/accounts/v1/datasource_pb.ts +++ b/module/services/frontend/code/packages/saas-sdk/generated/typescript/src/gen/saas/accounts/v1/datasource_pb.ts @@ -18,7 +18,7 @@ import type { JsonObject, Message } from "@bufbuild/protobuf"; * Describes the file saas/accounts/v1/datasource.proto. */ export const file_saas_accounts_v1_datasource: GenFile = /*@__PURE__*/ - fileDesc("CiFzYWFzL2FjY291bnRzL3YxL2RhdGFzb3VyY2UucHJvdG8SEHNhYXMuYWNjb3VudHMudjEiXgoWR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIMCgRyZXBvGAEgASgJEg0KBXBhdGhzGAIgAygJEg4KBmJyYW5jaBgDIAEoCRIXCg9maWxlX2V4dGVuc2lvbnMYBCADKAki9AEKD0FwaU9BdXRoMkNvbmZpZxI2CgVncmFudBgEIAEoDjInLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnLkdyYW50EhEKCXRva2VuX3VybBgBIAEoCRIRCgljbGllbnRfaWQYAiABKAkSDgoGc2NvcGVzGAMgAygJInMKBUdyYW50EhUKEUdSQU5UX1VOU1BFQ0lGSUVEEAASFwoTR1JBTlRfUkVGUkVTSF9UT0tFThABEhwKGEdSQU5UX0NMSUVOVF9DUkVERU5USUFMUxACEhwKGEdSQU5UX0FVVEhPUklaQVRJT05fQ09ERRADIuoBChNBcGlEYXRhc291cmNlQ29uZmlnEhAKCGJhc2VfdXJsGAEgASgJEhUKDXJlc291cmNlX3BhdGgYAiABKAkSPAoPY3JlZGVudGlhbF9raW5kGAMgASgOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIZChFjcmVkZW50aWFsX2hlYWRlchgEIAEoCRIeChZjcmVkZW50aWFsX3F1ZXJ5X3BhcmFtGAUgASgJEjEKBm9hdXRoMhgGIAEoCzIhLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnIkEKF0NyYXdsZXJEYXRhc291cmNlQ29uZmlnEhMKC3NpdGVtYXBfdXJsGAEgASgJEhEKCW1heF9wYWdlcxgCIAEoDSKrAgoWVXBsb2FkRGF0YXNvdXJjZUNvbmZpZxIQCghlbmRwb2ludBgBIAEoCRIOCgZyZWdpb24YAiABKAkSDgoGYnVja2V0GAMgASgJEg4KBnByZWZpeBgEIAEoCRIVCg1hY2Nlc3Nfa2V5X2lkGAUgASgJEhMKC21heF9vYmplY3RzGAYgASgNEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACEkkKD2ZpbGVfZXh0ZW5zaW9ucxgJIAMoCUIwukgtkgEqECAiJnIkEAIYITIeXlwuW0EtWmEtejAtOV1bQS1aYS16MC05Ll8tXSokIoMHCgpEYXRhc291cmNlEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRI2Cghwcm92aWRlchgDIAEoDjIkLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyEjgKBmdpdGh1YhgFIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIyCgZzdGF0dXMYBiABKA4yIi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTdGF0dXMSGgoSd2ViaG9va19jb25maWd1cmVkGAcgASgIEi4KCmNyZWF0ZWRfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDmxhc3Rfc3luY2VkX2F0GAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgNhcGkYCyABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWcSOgoHY3Jhd2xlchgMIAEoCzIpLnNhYXMuYWNjb3VudHMudjEuQ3Jhd2xlckRhdGFzb3VyY2VDb25maWcSOAoGdXBsb2FkGA0gASgLMiguc2Fhcy5hY2NvdW50cy52MS5VcGxvYWREYXRhc291cmNlQ29uZmlnEhgKEGJvdW5kYXJ5X25vZGVfaWQYDiABKAkSNAoQbGFzdF9pbmdlc3RlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHAoUbGFzdF9pbmdlc3RlZF9jb21taXQYECABKAkSFQoNc3RhdHVzX3JlYXNvbhgRIAEoCRIWCg5ib3VuZGFyeV9sYWJlbBgSIAEoCRISCgpjb25mb3JtYW50GBMgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgUIAEoCRI/Cg1saXZlX2RlbGl2ZXJ5GBUgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlTGl2ZURlbGl2ZXJ5EjUKEnJlY29uY2lsZV9pbnRlcnZhbBgWIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkoECAQQBVIRdGFyZ2V0X2NvbGxlY3Rpb24isgMKFkFkZEdpdEh1YlNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI7CgRyZXBvGAIgASgJQi26SCpyKBADGP8BMiFeW0EtWmEtejAtOV8uLV0rL1tBLVphLXowLTlfLi1dKyQSIAoFcGF0aHMYAyADKAlCEbpIDpIBCxBAIgdyBRABGIAEEhgKBmJyYW5jaBgEIAEoCUIIukgFcgMY/wESJAoQYm91bmRhcnlfbm9kZV9pZBgIIAEoCUIIukgFcgOwAQFIABImChBjb2xsZWN0aW9uX2xhYmVsGAkgASgJQgq6SAdyBRABGP8BSAASHgoMYWNjZXNzX3Rva2VuGAYgASgJQgi6SAVyAxiACBIgCg53ZWJob29rX3NlY3JldBgHIAEoCUIIukgFcgMYgAgSSQoPZmlsZV9leHRlbnNpb25zGAogAygJQjC6SC2SASoQICImciQQAhghMh5eXC5bQS1aYS16MC05XVtBLVphLXowLTkuXy1dKiRCEQoIYm91bmRhcnkSBbpIAggBSgQIBRAGUhF0YXJnZXRfY29sbGVjdGlvbiJLChdBZGRHaXRIdWJTb3VyY2VSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsgEChBBZGRTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESQgoIcHJvdmlkZXIYAiABKA4yJC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VQcm92aWRlckIKukgHggEEEAEgABI6CgZnaXRodWIYBCABKAsyKC5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkRhdGFzb3VyY2VDb25maWdIABI0CgNhcGkYBSABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWdIABI8CgdjcmF3bGVyGAggASgLMikuc2Fhcy5hY2NvdW50cy52MS5DcmF3bGVyRGF0YXNvdXJjZUNvbmZpZ0gAEjoKBnVwbG9hZBgJIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuVXBsb2FkRGF0YXNvdXJjZUNvbmZpZ0gAEiQKEGJvdW5kYXJ5X25vZGVfaWQYDCABKAlCCLpIBXIDsAEBSAESJgoQY29sbGVjdGlvbl9sYWJlbBgNIAEoCUIKukgHcgUQARj/AUgBEhwKCmNyZWRlbnRpYWwYBiABKAlCCLpIBXIDGIAgEiAKDndlYmhvb2tfc2VjcmV0GAcgASgJQgi6SAVyAxiACBImChRvYXV0aDJfY2xpZW50X3NlY3JldBgKIAEoCUIIukgFcgMYgAhCCAoGY29uZmlnQhEKCGJvdW5kYXJ5EgW6SAIIAUoECAMQBFIRdGFyZ2V0X2NvbGxlY3Rpb24iRQoRQWRkU291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSLkAgoTVXBkYXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIYCgZicmFuY2gYAyABKAlCCLpIBXIDGP8BEiAKBXBhdGhzGAQgAygJQhG6SA6SAQsQQCIHcgUQARiABBJJCg9maWxlX2V4dGVuc2lvbnMYBSADKAlCMLpILZIBKhAgIiZyJBACGCEyHl5cLltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJBI8CghleHBlY3RlZBgGIAEoCzIiLnNhYXMuYWNjb3VudHMudjEuU291cmNlRmV0Y2hTY29wZUIGukgDyAEBEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACIs8BChBTb3VyY2VGZXRjaFNjb3BlEhgKBmJyYW5jaBgBIAEoCUIIukgFcgMY/wESIAoFcGF0aHMYAiADKAlCEbpIDpIBCxBAIgdyBRABGIAEEikKD2ZpbGVfZXh0ZW5zaW9ucxgDIAMoCUIQukgNkgEKECAiBnIEEAEYIRIpChBpbmNsdWRlX3BhdHRlcm5zGAQgAygJQg+6SAySAQkQECIFcgMYgAISKQoQZXhjbHVkZV9wYXR0ZXJucxgFIAMoCUIPukgMkgEJEBAiBXIDGIACIlgKFFVwZGF0ZVNvdXJjZVJlc3BvbnNlEjAKCmRhdGFzb3VyY2UYASABKAsyHC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2USDgoGam9iX2lkGAIgASgJIloKFURhdGFzb3VyY2VDb25maWdGaWVsZBILCgNrZXkYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEgwKBGhlbHAYAyABKAkSEAoIcmVxdWlyZWQYBCABKAgixAEKGURhdGFzb3VyY2VDb25uZWN0b3JCdWRnZXQSGgoSbWF4X2l0ZW1zX3Blcl9jYWxsGAEgASgNEhoKEm1heF9ieXRlc19wZXJfY2FsbBgCIAEoAxIWCg5tYXhfaXRlbV9ieXRlcxgDIAEoAxIdChVvcGVyYXRpb25zX3Blcl93aW5kb3cYBCABKA0SFgoOd2luZG93X3NlY29uZHMYBSABKAMSIAoYYmFja2dyb3VuZF9zaGFyZV9wZXJjZW50GAYgASgNIqoGChxEYXRhc291cmNlUHJvdmlkZXJEZXNjcmlwdG9yEjYKCHByb3ZpZGVyGAEgASgOMiQuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUHJvdmlkZXISFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEj4KDWNvbmZpZ19maWVsZHMYBCADKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDb25maWdGaWVsZBIYChBzdXBwb3J0c193ZWJob29rGAUgASgIEkcKGnN1cHBvcnRlZF9jcmVkZW50aWFsX2tpbmRzGAYgAygOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIRCgljb25uZWN0b3IYByABKAkSQQoJaW50ZXJmYWNlGAggASgOMi4uc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQ29ubmVjdG9ySW50ZXJmYWNlEkQKEGNyZWRlbnRpYWxfbW9kZXMYCSADKA4yKi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRI/Cg1yZWFkZXJzX21vZGVsGAogASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUmVhZGVyc01vZGVsEjsKBmJ1ZGdldBgLIAEoCzIrLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUNvbm5lY3RvckJ1ZGdldBISCgpjb25mb3JtYW50GAwgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgNIAEoCRIbChNhY2NlcHRzX25ld19zb3VyY2VzGA4gASgIEiAKGGxpdmVfZGVsaXZlcnlfY29uZmlndXJlZBgPIAEoCBIaChJhY2NlcHRzX29wZXJhdGlvbnMYECABKAgSFgoOb3BlcmF0aW9uc19nYXAYESABKAkSGwoTb2F1dGhfYXV0aG9yaXplX3VybBgSIAEoCRIXCg9vYXV0aF90b2tlbl91cmwYEyABKAkSFAoMb2F1dGhfc2NvcGVzGBQgAygJIh0KG0dldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdCJhChxHZXREYXRhc291cmNlQ2F0YWxvZ1Jlc3BvbnNlEkEKCXByb3ZpZGVycxgBIAMoCzIuLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyRGVzY3JpcHRvciIuChJMaXN0U291cmNlc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJIChNMaXN0U291cmNlc1Jlc3BvbnNlEjEKC2RhdGFzb3VyY2VzGAEgAygLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIkIKEEdldFNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiRQoRR2V0U291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSJ2ChFTeW5jU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIeCgxhY2Nlc3NfdG9rZW4YAyABKAlCCLpIBXIDGIAgEhEKCXJlY29ubmVjdBgEIAEoCCIkChJTeW5jU291cmNlUmVzcG9uc2USDgoGam9iX2lkGAEgASgJImoKFEdldFNvdXJjZVN5bmNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgZqb2JfaWQYAyABKAlCC7pICNgBAXIDsAEBIpUBChJTb3VyY2VTeW5jRGVsaXZlcnkSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARItCgVzdGF0ZRgCIAEoDjIWLnNhYXMuam9icy52MS5Kb2JTdGF0ZUIGukgDyAEBEjYKCWV4ZWN1dGlvbhgDIAEoCzIjLnNhYXMuam9icy52MS5Kb2JFeGVjdXRpb25SZWZlcmVuY2UiiwEKEVNvdXJjZVN5bmNDaGFuZ2VzEg0KBWZpbGVzGAEgASgNEg0KBWFkZGVkGAIgASgNEhAKCG1vZGlmaWVkGAMgASgNEg8KB2RlbGV0ZWQYBCABKA0SEwoLc3BsaXRfa25vd24YBSABKAgSEAoIc25hcHNob3QYBiABKAgSDgoGY29tbWl0GAcgASgJIq0BChFTb3VyY2VTeW5jRmFpbHVyZRI5CgZyZWFzb24YASABKA4yKS5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNGYWlsdXJlUmVhc29uEgwKBGNvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCRIQCghyZXRyeWluZxgEIAEoCBIsCghyZXRyeV9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAQKElNvdXJjZVN5bmNQcm9ncmVzcxIwCgVwaGFzZRgBIAEoDjIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY1BoYXNlEjQKB3RyaWdnZXIYAiABKA4yIy5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNUcmlnZ2VyEi0KCXF1ZXVlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoLZmV0Y2hpbmdfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi8KC2NvbXBpbGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1oYW5kZWRfb2ZmX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIvCgtmaW5pc2hlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoHY2hhbmdlcxgIIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0NoYW5nZXMSNAoHZmFpbHVyZRgJIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0ZhaWx1cmUSDwoHYXR0ZW1wdBgKIAEoDRIUCgxtYXhfYXR0ZW1wdHMYCyABKA0i0gEKFUdldFNvdXJjZVN5bmNSZXNwb25zZRIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBEi0KBXN0YXRlGAIgASgOMhYuc2Fhcy5qb2JzLnYxLkpvYlN0YXRlQga6SAPIAQESOAoKZGVsaXZlcmllcxgDIAMoCzIkLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0RlbGl2ZXJ5EjYKCHByb2dyZXNzGAQgASgLMiQuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VTeW5jUHJvZ3Jlc3MiRQoTRGVsZXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASIWChREZWxldGVTb3VyY2VSZXNwb25zZSJWChNHaXRIdWJBcHBSZXBvc2l0b3J5EgwKBHJlcG8YASABKAkSFgoOZGVmYXVsdF9icmFuY2gYAiABKAkSGQoRYWxyZWFkeV9jb25uZWN0ZWQYAyABKAgiNgoaQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJxChtCZWdpbkdpdEh1YkFwcFNldHVwUmVzcG9uc2USEwoLaW5zdGFsbF91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAinAEKHUNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEY/wESLAoPaW5zdGFsbGF0aW9uX2lkGAMgASgJQhO6SBByDhABGCAyCF5bMC05XSskEhgKBGNvZGUYBCABKAlCCrpIB3IFEAEY/wEidgoeQ29tcGxldGVHaXRIdWJBcHBTZXR1cFJlc3BvbnNlEhcKD2luc3RhbGxhdGlvbl9pZBgBIAEoCRI7CgxyZXBvc2l0b3JpZXMYAiADKAsyJS5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkFwcFJlcG9zaXRvcnkiUQofTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASJUCiBNaWdyYXRlR2l0SHViU291cmNlVG9BcHBSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsQBChVEYXRhc291cmNlQWNjb3VudExpbmsSCgoCaWQYASABKAkSDgoGb3JnX2lkGAIgASgJEg8KB3VzZXJfaWQYAyABKAkSEQoJY29ubmVjdG9yGAQgASgJEhsKE3Byb3ZpZGVyX2FjY291bnRfaWQYBSABKAkSHgoWcHJvdmlkZXJfYWNjb3VudF9sb2dpbhgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK3AQoWRGF0YXNvdXJjZUdyb3VwQmluZGluZxIKCgJpZBgBIAEoCRIOCgZvcmdfaWQYAiABKAkSEQoJY29ubmVjdG9yGAMgASgJEhkKEXByb3ZpZGVyX2dyb3VwX2lkGAQgASgJEg8KB3RlYW1faWQYBSABKAkSEgoKY3JlYXRlZF9ieRgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKUAgoYRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRIOCgZkb21haW4YAyABKAkSOAoGc3RhdHVzGAQgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRG9tYWluU3RhdHVzEhcKD3R4dF9yZWNvcmRfbmFtZRgFIAEoCRIYChB0eHRfcmVjb3JkX3ZhbHVlGAYgASgJEi8KC3ZlcmlmaWVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjcmVhdGVkX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIzChdEYXRhc291cmNlRGlyZWN0b3J5VGVhbRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJIqYBCiFCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIeCgxyZWRpcmVjdF91cmkYAyABKAlCCLpIBXIDGIAQEhEKCXNvdXJjZV9pZBgEIAEoCSJ6CiJCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEhUKDWF1dGhvcml6ZV91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAidQokQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEYgEASGAoEY29kZRgDIAEoCUIKukgHcgUQARj/ASJeCiVDb21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEjUKBGxpbmsYASABKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VBY2NvdW50TGluayI/CiNMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBIl4KJExpc3RNeURhdGFzb3VyY2VBY2NvdW50TGlua3NSZXNwb25zZRI2CgVsaW5rcxgBIAMoCzInLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUFjY291bnRMaW5rIlQKIkRlbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiJQojRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rUmVzcG9uc2UiOQodR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASKLAgoeR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlEjYKBWxpbmtzGAEgAygLMicuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQWNjb3VudExpbmsSOgoIYmluZGluZ3MYAiADKAsyKC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VHcm91cEJpbmRpbmcSOwoHZG9tYWlucxgDIAMoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEjgKBXRlYW1zGAQgAygLMikuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRGlyZWN0b3J5VGVhbSKuAQoaQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIlChFwcm92aWRlcl9ncm91cF9pZBgDIAEoCUIKukgHcgUQARj/ARIZCgd0ZWFtX2lkGAQgASgJQgi6SAVyA7ABASJYChtCaW5kRGF0YXNvdXJjZUdyb3VwUmVzcG9uc2USOQoHYmluZGluZxgBIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUdyb3VwQmluZGluZyJOChxVbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIh8KHVVuYmluZERhdGFzb3VyY2VHcm91cFJlc3BvbnNlIlQKHENsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIaCgZkb21haW4YAiABKAlCCrpIB3IFEAMY/QEiWwodQ2xhaW1EYXRhc291cmNlRG9tYWluUmVzcG9uc2USOgoGZG9tYWluGAEgASgLMiouc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlVmVyaWZpZWREb21haW4iTwodVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiXAoeVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlEjoKBmRvbWFpbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluIk8KHURlbGV0ZURhdGFzb3VyY2VEb21haW5SZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIiAKHkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSKeAgoQU291cmNlRGVsZWdhdGlvbhIKCgJpZBgBIAEoCRIRCglzb3VyY2VfaWQYAiABKAkSFAoMcHJpbmNpcGFsX2lkGAMgASgJEg4KBm1vZHVsZRgEIAEoCRIPCgdiaW5kaW5nGAUgASgJEi4KCmNyZWF0ZWRfYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnJldm9rZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEkAKCnJldm9jYXRpb24YCCABKA4yLC5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb25SZXZvY2F0aW9uEhIKCnJldm9rZWRfYnkYCSABKAkigQEKHExpc3RTb3VyY2VEZWxlZ2F0aW9uc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIgCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBSACIAQESFwoPaW5jbHVkZV9yZXZva2VkGAMgASgIQgwKCl9zb3VyY2VfaWQiWAodTGlzdFNvdXJjZURlbGVnYXRpb25zUmVzcG9uc2USNwoLZGVsZWdhdGlvbnMYASADKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iTwodUmV2b2tlU291cmNlRGVsZWdhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiWAoeUmV2b2tlU291cmNlRGVsZWdhdGlvblJlc3BvbnNlEjYKCmRlbGVnYXRpb24YASABKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iMgoPVHJpZ2dlcklkZW50aXR5Eg4KBnNvdXJjZRgBIAEoCRIPCgdiaW5kaW5nGAIgASgJIoQBChdEZWNsYXJlZFRyaWdnZXJTY2hlZHVsZRIMCgRjcm9uGAEgASgJEhAKCHRpbWV6b25lGAIgASgJEhIKCm1pc3NlZF9ydW4YAyABKAkSDwoHb3ZlcmxhcBgEIAEoCRIQCghkZWFkbGluZRgFIAEoAxISCgppbnB1dF9qc29uGAYgASgJIucCChpUcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRIRCglyZWZlcmVuY2UYASABKAkSFQoNZGVsZWdhdGlvbl9pZBgCIAEoCRIOCgZtb2R1bGUYAyABKAkSDwoHYmluZGluZxgEIAEoCRIQCghhdWRpZW5jZRgFIAEoCRIOCgZ0ZW5hbnQYBiABKAkSGgoSb3duZXJfcHJpbmNpcGFsX2lkGAcgASgJEg4KBnNjb3BlcxgIIAMoCRIOCgZhY3RpdmUYCSABKAgSLgoKY3JlYXRlZF9hdBgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKcmV2b2tlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASQAoKcmV2b2NhdGlvbhgMIAEoDjIsLnNhYXMuYWNjb3VudHMudjEuU291cmNlRGVsZWdhdGlvblJldm9jYXRpb24ivgEKE1RyaWdnZXJDaGlsZENvbnRleHQSFQoNZGVsZWdhdGlvbl9pZBgBIAEoCRIOCgZtb2R1bGUYAiABKAkSDwoHYmluZGluZxgDIAEoCRIQCghhdWRpZW5jZRgEIAEoCRIOCgZzY29wZXMYBSADKAkSDgoGbG9va3VwGAYgASgIEi0KCW1pbnRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGcmVjb3JkGAggASgJIs0CChhTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb24SDwoHcmVsZWFzZRgBIAEoCRIRCglvcGVyYXRpb24YAiABKAkSOwoIc2NoZWR1bGUYAyABKAsyKS5zYWFzLmFjY291bnRzLnYxLkRlY2xhcmVkVHJpZ2dlclNjaGVkdWxlEjMKCGlkZW50aXR5GAQgASgLMiEuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VySWRlbnRpdHkSDgoGZGlnZXN0GAUgASgJEjYKEmxhc3Rfb2NjdXJyZW5jZV9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNgoSbmV4dF9vY2N1cnJlbmNlX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChN1bmRlY2xhcmFibGVfcmVhc29uGAggASgJIlYKHURlbGVnYXRlU291cmNlVHJpZ2dlcnNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABASJjCh5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVzcG9uc2USQQoLZGVsZWdhdGlvbnMYASADKAsyLC5zYWFzLmFjY291bnRzLnYxLlRyaWdnZXJEZWxlZ2F0aW9uUmVmZXJlbmNlIlsKIkdldFNvdXJjZVRyaWdnZXJEZWNsYXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBIuIBCiNHZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZRI/CgtkZWNsYXJhdGlvbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuU291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEkEKC2RlbGVnYXRpb25zGAIgAygLMiwuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRI3CghjaGlsZHJlbhgDIAMoCzIlLnNhYXMuYWNjb3VudHMudjEuVHJpZ2dlckNoaWxkQ29udGV4dCJuChZSZWNvbmNpbGVTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIdCgllZmZlY3RfaWQYAyABKAlCCrpIB3IFEAEYgAEiTAoXUmVjb25jaWxlU291cmNlUmVzcG9uc2USEQoJZWZmZWN0X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIOCgZqb2JfaWQYAyABKAkiPQocTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBIdCgllZmZlY3RfaWQYASABKAlCCrpIB3IFEAEYgAEi8QIKD1NvdXJjZU9wZXJhdGlvbhIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg4KBm1ldGhvZBgDIAEoCRIMCgRwYXRoGAQgASgJEg0KBXF1ZXJ5GAUgAygJEi0KDGlucHV0X3NjaGVtYRgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSLgoNb3V0cHV0X3NjaGVtYRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSOAoGZWZmZWN0GAggASgOMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24uRWZmZWN0EhgKEG1heF9vdXRwdXRfYnl0ZXMYCSABKA0SDgoGZGlnZXN0GAogASgJIksKBkVmZmVjdBIWChJFRkZFQ1RfVU5TUEVDSUZJRUQQABIUChBFRkZFQ1RfUkVBRF9PTkxZEAESEwoPRUZGRUNUX01VVEFUSU9OEAIijgEKHkRlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQESNQoKb3BlcmF0aW9ucxgDIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlgKH0RlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVzcG9uc2USNQoKb3BlcmF0aW9ucxgBIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlQKG0xpc3RTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQEiVQocTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXNwb25zZRI1CgpvcGVyYXRpb25zGAEgAygLMiEuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24irgIKHEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBEjAKCW9wZXJhdGlvbhgDIAEoCUIdukgachgyFl5bYS16XVthLXowLTlfXXswLDYzfSQSHQoKaW5wdXRfanNvbhgEIAEoCUIJukgGcgQogIAEEhsKCWVmZmVjdF9pZBgFIAEoCUIIukgFcgMogAESSQobZXhwZWN0ZWRfZGVjbGFyYXRpb25fZGlnZXN0GAYgASgJQh+6SBxyGjIYXihzaGEyNTY6WzAtOWEtZl17NjR9KT8kSACIAQFCHgocX2V4cGVjdGVkX2RlY2xhcmF0aW9uX2RpZ2VzdCJ/ChZTb3VyY2VPcGVyYXRpb25SZWNlaXB0EhEKCWVmZmVjdF9pZBgBIAEoCRIUCgxjb21taXR0ZWRfYXQYAiABKAkSDgoGc3RhdHVzGAMgASgJEhcKD3Byb3ZpZGVyX3N0YXR1cxgEIAEoDRITCgtvdXRwdXRfanNvbhgFIAEoCSJvCh1JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZRITCgtvdXRwdXRfanNvbhgBIAEoCRI5CgdyZWNlaXB0GAIgASgLMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb25SZWNlaXB0IkMKIkxvb2t1cEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSHQoJZWZmZWN0X2lkGAEgASgJQgq6SAdyBRABKIABInkKI1BydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgllZmZlY3RfaWQYAyABKAlCCLpIBXIDKIABIlsKJFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZRIRCgllZmZlY3RfaWQYASABKAkSEAoIcmVjZWlwdHMYAiABKAMSDgoGc3RhdHVzGAMgASgJIkoKKUxvb2t1cFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0Eh0KCWVmZmVjdF9pZBgBIAEoCUIKukgHcgUQASiAASq3AQoSRGF0YXNvdXJjZVByb3ZpZGVyEiMKH0RBVEFTT1VSQ0VfUFJPVklERVJfVU5TUEVDSUZJRUQQABIeChpEQVRBU09VUkNFX1BST1ZJREVSX0dJVEhVQhABEhsKF0RBVEFTT1VSQ0VfUFJPVklERVJfQVBJEAISHwobREFUQVNPVVJDRV9QUk9WSURFUl9DUkFXTEVSEAMSHgoaREFUQVNPVVJDRV9QUk9WSURFUl9VUExPQUQQBCqRAQoQRGF0YXNvdXJjZVN0YXR1cxIhCh1EQVRBU09VUkNFX1NUQVRVU19VTlNQRUNJRklFRBAAEhwKGERBVEFTT1VSQ0VfU1RBVFVTX0FDVElWRRABEhwKGERBVEFTT1VSQ0VfU1RBVFVTX1BBVVNFRBACEh4KGkRBVEFTT1VSQ0VfU1RBVFVTX0RFR1JBREVEEAMqvAEKFkRhdGFzb3VyY2VMaXZlRGVsaXZlcnkSKAokREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX1VOU1BFQ0lGSUVEEAASIQodREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX05PTkUQARIrCidEQVRBU09VUkNFX0xJVkVfREVMSVZFUllfU09VUkNFX1dFQkhPT0sQAhIoCiREQVRBU09VUkNFX0xJVkVfREVMSVZFUllfQVBQX1dFQkhPT0sQAyrWAQoRQXBpQ3JlZGVudGlhbEtpbmQSIwofQVBJX0NSRURFTlRJQUxfS0lORF9VTlNQRUNJRklFRBAAEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfQkVBUkVSEAESHQoZQVBJX0NSRURFTlRJQUxfS0lORF9CQVNJQxACEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfSEVBREVSEAMSHQoZQVBJX0NSRURFTlRJQUxfS0lORF9RVUVSWRAEEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfT0FVVEgyEAUqpgIKHERhdGFzb3VyY2VDb25uZWN0b3JJbnRlcmZhY2USLgoqREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1VOU1BFQ0lGSUVEEAASKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX0ZJTEVTEAESKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1BBR0VTEAISKgomREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1JFQ09SRFMQAxIrCidEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfTUVTU0FHRVMQBBIpCiVEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfRVZFTlRTEAUq7AEKGERhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRIqCiZEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9VTlNQRUNJRklFRBAAEiMKH0RBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX05PTkUQARImCiJEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9PUkdfQVBQEAISKQolREFUQVNPVVJDRV9DUkVERU5USUFMX01PREVfVVNFUl9PQVVUSBADEiwKKERBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX1NUQVRJQ19TRUNSRVQQBCqXAQoWRGF0YXNvdXJjZVJlYWRlcnNNb2RlbBIoCiREQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfVU5TUEVDSUZJRUQQABIqCiZEQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfU09VUkNFX1NDT1BFRBABEicKI0RBVEFTT1VSQ0VfUkVBREVSU19NT0RFTF9UUkFOU0xBVEVEEAIq7gEKD1NvdXJjZVN5bmNQaGFzZRIhCh1TT1VSQ0VfU1lOQ19QSEFTRV9VTlNQRUNJRklFRBAAEhwKGFNPVVJDRV9TWU5DX1BIQVNFX1FVRVVFRBABEh4KGlNPVVJDRV9TWU5DX1BIQVNFX0ZFVENISU5HEAISHgoaU09VUkNFX1NZTkNfUEhBU0VfQ09NUElMRUQQAxIgChxTT1VSQ0VfU1lOQ19QSEFTRV9IQU5ERURfT0ZGEAQSGgoWU09VUkNFX1NZTkNfUEhBU0VfRE9ORRAFEhwKGFNPVVJDRV9TWU5DX1BIQVNFX0ZBSUxFRBAGKqYDChdTb3VyY2VTeW5jRmFpbHVyZVJlYXNvbhIqCiZTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEisKJ1NPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX1JBVEVfTElNSVRFRBABEikKJVNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX0NSRURFTlRJQUwQAhIsCihTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9BQ0NFU1NfREVOSUVEEAMSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fTk9UX0ZPVU5EEAQSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fVE9PX0xBUkdFEAUSLworU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fSE9TVF9VTkFWQUlMQUJMRRAGEiQKIFNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX09USEVSEAcSLgoqU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fREVMSVZFUllfRkFJTEVEEAgqwgEKEVNvdXJjZVN5bmNUcmlnZ2VyEiMKH1NPVVJDRV9TWU5DX1RSSUdHRVJfVU5TUEVDSUZJRUQQABIeChpTT1VSQ0VfU1lOQ19UUklHR0VSX01BTlVBTBABEiEKHVNPVVJDRV9TWU5DX1RSSUdHRVJfU0NIRURVTEVEEAISHwobU09VUkNFX1NZTkNfVFJJR0dFUl9XRUJIT09LEAMSJAogU09VUkNFX1NZTkNfVFJJR0dFUl9SRUNPTkZJR1VSRUQQBCqPAQoWRGF0YXNvdXJjZURvbWFpblN0YXR1cxIoCiREQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIkCiBEQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfUEVORElORxABEiUKIURBVEFTT1VSQ0VfRE9NQUlOX1NUQVRVU19WRVJJRklFRBACKpUDChpTb3VyY2VEZWxlZ2F0aW9uUmV2b2NhdGlvbhIsCihTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VOU1BFQ0lGSUVEEAASKAokU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVZPS0VEEAESKQolU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVBMQUNFRBACEi8KK1NPVVJDRV9ERUxFR0FUSU9OX1JFVk9DQVRJT05fU09VUkNFX0RFTEVURUQQAxIvCitTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX01FTUJFUl9SRU1PVkVEEAQSMAosU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9QRVJNSVNTSU9OX0xPU1QQBRIuCipTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VTRVJfSU5BQ1RJVkUQBhIwCixTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX0JJTkRJTkdfQ0hBTkdFRBAHMrM7ChFEYXRhc291cmNlU2VydmljZRK5AwocUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI1LnNhYXMuYWNjb3VudHMudjEuUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSKpAsLzGGwIAhADGhFkYXRhc291cmNlOmludm9rZSIRZGF0YXNvdXJjZTppbnZva2UqDwoJc291cmNlX2lkEAQYAzABOiMKH3NhYXMuZGF0YXNvdXJjZS5yZWNlaXB0cy5wcnVuZWQQAkADSARQA1gDYAHa8xi0AQoCCDwSAwjYBBgFIgIIAioLVU5BVkFJTEFCTEUqElJFU09VUkNFX0VYSEFVU1RFRCoHQUJPUlRFRDIPc2Fhcy1kYXRhc291cmNlSkYvc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlU2VydmljZS9Mb29rdXBQcnVuZVNvdXJjZU9wZXJhdGlvblJlY2VpcHRzUIAgWIAgYAFyGAoGc291cmNlEgZpbnZva2USBHJlYWQYARLmAQoiTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI7LnNhYXMuYWNjb3VudHMudjEuTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSJLwvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUANYA2ABEvwDChVJbnZva2VTb3VyY2VPcGVyYXRpb24SLi5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlc3BvbnNlIoEDwvMYbggCEAMaEWRhdGFzb3VyY2U6aW52b2tlIhFkYXRhc291cmNlOmludm9rZSoPCglzb3VyY2VfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEARAA0gEUARYBGAB2vMYrwEKAgg8EgMI2AQYBSICCAIqC1VOQVZBSUxBQkxFKhJSRVNPVVJDRV9FWEhBVVNURUQqB0FCT1JURUQyD3NhYXMtZGF0YXNvdXJjZUo/L3NhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVNlcnZpY2UvTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uUICABFiAgEBgAXIYCgZzb3VyY2USBmludm9rZRIEcmVhZBgBgtPkkwJVOgEqIlAvdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zL3tvcGVyYXRpb259Omludm9rZRKHAgobTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5Mb29rdXBJbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKAAcLzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ADWARgAYLT5JMCLxItL3YxL2RhdGFzb3VyY2Utb3BlcmF0aW9uLXJlY2VpcHRzL3tlZmZlY3RfaWR9Ev8BChxWZXJpZnlTb3VyY2VPcGVyYXRpb25SZWNlaXB0Ei4uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSJ+wvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUARYBGABgtPkkwItOgEqIigvdjEvZGF0YXNvdXJjZS1vcGVyYXRpb24tcmVjZWlwdHMvdmVyaWZ5EoUCChRMaXN0U291cmNlT3BlcmF0aW9ucxItLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0Gi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIo0BwvMYRAgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKgwKBm9yZ19pZBACGAEwAToCEAFAAUgDUANYA2ABgtPkkwI/Ej0vdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zEpMCChdEZWNsYXJlU291cmNlT3BlcmF0aW9ucxIwLnNhYXMuYWNjb3VudHMudjEuRGVjbGFyZVNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0GjEuc2Fhcy5hY2NvdW50cy52MS5EZWNsYXJlU291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIpIBwvMYRggCEAQqDAoGb3JnX2lkEAIYATABOiYKInNhYXMuZGF0YXNvdXJjZS5vcGVyYXRpb24uZGVjbGFyZWQQAkABSARQA1gDYAGC0+STAkI6ASoiPS92MS9vcmdhbml6YXRpb25zL3tvcmdfaWR9L2RhdGFzb3VyY2VzL3tzb3VyY2VfaWR9L29wZXJhdGlvbnMSrAEKD0FkZEdpdEh1YlNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVzcG9uc2UiRMLzGEAIAhAEKgwKBm9yZ19pZBACGAEwATogChxzYWFzLmRhdGFzb3VyY2Uuc291cmNlLmFkZGVkEAJAAUgEUARYA2ABEpoBCglBZGRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlc3BvbnNlIkTC8xhACAIQBCoMCgZvcmdfaWQQAhgBMAE6IAocc2Fhcy5kYXRhc291cmNlLnNvdXJjZS5hZGRlZBACQAFIBFAEWANgARKlAQoMVXBkYXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UudXBkYXRlZBACQAFIBFACWANgARKPAQoUR2V0RGF0YXNvdXJjZUNhdGFsb2cSLS5zYWFzLmFjY291bnRzLnYxLkdldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdBouLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZUNhdGFsb2dSZXNwb25zZSIYwvMYFAgCEAEwAToCEAFAAUgDUAJYAmABEoIBCgtMaXN0U291cmNlcxIkLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZXNSZXF1ZXN0GiUuc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARJ8CglHZXRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKeAQoKU3luY1NvdXJjZRIjLnNhYXMuYWNjb3VudHMudjEuU3luY1NvdXJjZVJlcXVlc3QaJC5zYWFzLmFjY291bnRzLnYxLlN5bmNTb3VyY2VSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5zb3VyY2Uuc3luY2VkEAJAAUgEUARYAmABEogBCg1HZXRTb3VyY2VTeW5jEiYuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VTeW5jUmVxdWVzdBonLnNhYXMuYWNjb3VudHMudjEuR2V0U291cmNlU3luY1Jlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKlAQoMRGVsZXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UucmVtb3ZlZBACQAFIBFACWAJgARLEAQoTQmVnaW5HaXRIdWJBcHBTZXR1cBIsLnNhYXMuYWNjb3VudHMudjEuQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJlZ2luR2l0SHViQXBwU2V0dXBSZXNwb25zZSJQwvMYTAgCEAQqDAoGb3JnX2lkEAIYATABOiwKKHNhYXMuZGF0YXNvdXJjZS5naXRodWJfYXBwLnNldHVwX3N0YXJ0ZWQQAkABSARQAlgEYAESzwEKFkNvbXBsZXRlR2l0SHViQXBwU2V0dXASLy5zYWFzLmFjY291bnRzLnYxLkNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZUdpdEh1YkFwcFNldHVwUmVzcG9uc2UiUsLzGE4IAhAEKgwKBm9yZ19pZBACGAEwATouCipzYWFzLmRhdGFzb3VyY2UuZ2l0aHViX2FwcC5zZXR1cF9jb21wbGV0ZWQQAkABSARQBFgDYAESzQEKGE1pZ3JhdGVHaXRIdWJTb3VyY2VUb0FwcBIxLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBoyLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuY3JlZGVudGlhbC51cGRhdGVkEAJAAUgEUAJYA2ABEtUBChpCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGluaxIzLnNhYXMuYWNjb3VudHMudjEuQmVnaW5EYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjQuc2Fhcy5hY2NvdW50cy52MS5CZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkzC8xhICAIQAyoMCgZvcmdfaWQQAhgBMAE6KAokc2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua19zdGFydGVkEAJAAUgEUAJYBGABEtgBCh1Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGluaxI2LnNhYXMuYWNjb3VudHMudjEuQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0Gjcuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkbC8xhCCAIQAyoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua2VkEAJAAUgEUARYA2ABErUBChxMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzEjUuc2Fhcy5hY2NvdW50cy52MS5MaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBo2LnNhYXMuYWNjb3VudHMudjEuTGlzdE15RGF0YXNvdXJjZUFjY291bnRMaW5rc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARLUAQobRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rEjQuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXNwb25zZSJIwvMYRAgCEAMqDAoGb3JnX2lkEAIYATABOiQKIHNhYXMuZGF0YXNvdXJjZS5hY2NvdW50X3VubGlua2VkEAJAAUgEUAJYA2ABEqMBChZHZXREYXRhc291cmNlRGlyZWN0b3J5Ei8uc2Fhcy5hY2NvdW50cy52MS5HZXREYXRhc291cmNlRGlyZWN0b3J5UmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARK3AQoTQmluZERhdGFzb3VyY2VHcm91cBIsLnNhYXMuYWNjb3VudHMudjEuQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJDwvMYPwgCEAQqDAoGb3JnX2lkEAIYATABOh8KG3NhYXMuZGF0YXNvdXJjZS5ncm91cF9ib3VuZBACQAFIBFACWANgARK/AQoVVW5iaW5kRGF0YXNvdXJjZUdyb3VwEi4uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5ncm91cF91bmJvdW5kEAJAAUgEUAJYA2ABEsABChVDbGFpbURhdGFzb3VyY2VEb21haW4SLi5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkbC8xhCCAIQBCoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmRvbWFpbl9jbGFpbWVkEAJAAUgEUAJYA2ABEsQBChZWZXJpZnlEYXRhc291cmNlRG9tYWluEi8uc2Fhcy5hY2NvdW50cy52MS5WZXJpZnlEYXRhc291cmNlRG9tYWluUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkfC8xhDCAIQBCoMCgZvcmdfaWQQAhgBMAE6Iwofc2Fhcy5kYXRhc291cmNlLmRvbWFpbl92ZXJpZmllZBACQAFIBFACWANgARLDAQoWRGVsZXRlRGF0YXNvdXJjZURvbWFpbhIvLnNhYXMuYWNjb3VudHMudjEuRGVsZXRlRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaMC5zYWFzLmFjY291bnRzLnYxLkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5kb21haW5fcmVtb3ZlZBACQAFIBFACWANgARKgAQoVTGlzdFNvdXJjZURlbGVnYXRpb25zEi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESxwEKFlJldm9rZVNvdXJjZURlbGVnYXRpb24SLy5zYWFzLmFjY291bnRzLnYxLlJldm9rZVNvdXJjZURlbGVnYXRpb25SZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5SZXZva2VTb3VyY2VEZWxlZ2F0aW9uUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuZGVsZWdhdGlvbi5yZXZva2VkEAJAAUgEUAJYA2ABEusBChZEZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzEi8uc2Fhcy5hY2NvdW50cy52MS5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuRGVsZWdhdGVTb3VyY2VUcmlnZ2Vyc1Jlc3BvbnNlIm7C8xhqCAIQBCoMCgZvcmdfaWQQAhgBMAE6Sgoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24uY3JlYXRlZAoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24ucmV2b2tlZBACQAFIBFACWANgARKyAQobR2V0U291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESgwMKD1JlY29uY2lsZVNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UimgLC8xhqCAIQAxoRZGF0YXNvdXJjZTppbnZva2UiEWRhdGFzb3VyY2U6aW52b2tlKg8KCXNvdXJjZV9pZBAEGAMwATohCh1zYWFzLmRhdGFzb3VyY2Uuc291cmNlLnN5bmNlZBACQANIBFACWAJgAdrzGKcBCgIIPBIDCNgEGAUiAggCKgtVTkFWQUlMQUJMRSoSUkVTT1VSQ0VfRVhIQVVTVEVEKgdBQk9SVEVEMg9zYWFzLWRhdGFzb3VyY2VKOS9zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTZXJ2aWNlL0xvb2t1cFJlY29uY2lsZVNvdXJjZVCAIFiAIGABchgKBnNvdXJjZRIGaW52b2tlEgRyZWFkGAESvwEKFUxvb2t1cFJlY29uY2lsZVNvdXJjZRIuLnNhYXMuYWNjb3VudHMudjEuTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UiS8LzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ACWAJgAWIGcHJvdG8z", [file_buf_validate_validate, file_codefly_runnable_v0_options, file_google_api_annotations, file_google_protobuf_duration, file_google_protobuf_struct, file_google_protobuf_timestamp, file_saas_jobs_v1_jobs, file_saas_policy_v1_options]); + fileDesc("CiFzYWFzL2FjY291bnRzL3YxL2RhdGFzb3VyY2UucHJvdG8SEHNhYXMuYWNjb3VudHMudjEiXgoWR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIMCgRyZXBvGAEgASgJEg0KBXBhdGhzGAIgAygJEg4KBmJyYW5jaBgDIAEoCRIXCg9maWxlX2V4dGVuc2lvbnMYBCADKAki9AEKD0FwaU9BdXRoMkNvbmZpZxI2CgVncmFudBgEIAEoDjInLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnLkdyYW50EhEKCXRva2VuX3VybBgBIAEoCRIRCgljbGllbnRfaWQYAiABKAkSDgoGc2NvcGVzGAMgAygJInMKBUdyYW50EhUKEUdSQU5UX1VOU1BFQ0lGSUVEEAASFwoTR1JBTlRfUkVGUkVTSF9UT0tFThABEhwKGEdSQU5UX0NMSUVOVF9DUkVERU5USUFMUxACEhwKGEdSQU5UX0FVVEhPUklaQVRJT05fQ09ERRADIuoBChNBcGlEYXRhc291cmNlQ29uZmlnEhAKCGJhc2VfdXJsGAEgASgJEhUKDXJlc291cmNlX3BhdGgYAiABKAkSPAoPY3JlZGVudGlhbF9raW5kGAMgASgOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIZChFjcmVkZW50aWFsX2hlYWRlchgEIAEoCRIeChZjcmVkZW50aWFsX3F1ZXJ5X3BhcmFtGAUgASgJEjEKBm9hdXRoMhgGIAEoCzIhLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnIkEKF0NyYXdsZXJEYXRhc291cmNlQ29uZmlnEhMKC3NpdGVtYXBfdXJsGAEgASgJEhEKCW1heF9wYWdlcxgCIAEoDSKrAgoWVXBsb2FkRGF0YXNvdXJjZUNvbmZpZxIQCghlbmRwb2ludBgBIAEoCRIOCgZyZWdpb24YAiABKAkSDgoGYnVja2V0GAMgASgJEg4KBnByZWZpeBgEIAEoCRIVCg1hY2Nlc3Nfa2V5X2lkGAUgASgJEhMKC21heF9vYmplY3RzGAYgASgNEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACEkkKD2ZpbGVfZXh0ZW5zaW9ucxgJIAMoCUIwukgtkgEqECAiJnIkEAIYITIeXlwuW0EtWmEtejAtOV1bQS1aYS16MC05Ll8tXSokIoMHCgpEYXRhc291cmNlEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRI2Cghwcm92aWRlchgDIAEoDjIkLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyEjgKBmdpdGh1YhgFIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIyCgZzdGF0dXMYBiABKA4yIi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTdGF0dXMSGgoSd2ViaG9va19jb25maWd1cmVkGAcgASgIEi4KCmNyZWF0ZWRfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDmxhc3Rfc3luY2VkX2F0GAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgNhcGkYCyABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWcSOgoHY3Jhd2xlchgMIAEoCzIpLnNhYXMuYWNjb3VudHMudjEuQ3Jhd2xlckRhdGFzb3VyY2VDb25maWcSOAoGdXBsb2FkGA0gASgLMiguc2Fhcy5hY2NvdW50cy52MS5VcGxvYWREYXRhc291cmNlQ29uZmlnEhgKEGJvdW5kYXJ5X25vZGVfaWQYDiABKAkSNAoQbGFzdF9pbmdlc3RlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHAoUbGFzdF9pbmdlc3RlZF9jb21taXQYECABKAkSFQoNc3RhdHVzX3JlYXNvbhgRIAEoCRIWCg5ib3VuZGFyeV9sYWJlbBgSIAEoCRISCgpjb25mb3JtYW50GBMgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgUIAEoCRI/Cg1saXZlX2RlbGl2ZXJ5GBUgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlTGl2ZURlbGl2ZXJ5EjUKEnJlY29uY2lsZV9pbnRlcnZhbBgWIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkoECAQQBVIRdGFyZ2V0X2NvbGxlY3Rpb24isgMKFkFkZEdpdEh1YlNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI7CgRyZXBvGAIgASgJQi26SCpyKBADGP8BMiFeW0EtWmEtejAtOV8uLV0rL1tBLVphLXowLTlfLi1dKyQSIAoFcGF0aHMYAyADKAlCEbpIDpIBCxBAIgdyBRABGIAEEhgKBmJyYW5jaBgEIAEoCUIIukgFcgMY/wESJAoQYm91bmRhcnlfbm9kZV9pZBgIIAEoCUIIukgFcgOwAQFIABImChBjb2xsZWN0aW9uX2xhYmVsGAkgASgJQgq6SAdyBRABGP8BSAASHgoMYWNjZXNzX3Rva2VuGAYgASgJQgi6SAVyAxiACBIgCg53ZWJob29rX3NlY3JldBgHIAEoCUIIukgFcgMYgAgSSQoPZmlsZV9leHRlbnNpb25zGAogAygJQjC6SC2SASoQICImciQQAhghMh5eXC5bQS1aYS16MC05XVtBLVphLXowLTkuXy1dKiRCEQoIYm91bmRhcnkSBbpIAggBSgQIBRAGUhF0YXJnZXRfY29sbGVjdGlvbiJLChdBZGRHaXRIdWJTb3VyY2VSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsgEChBBZGRTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESQgoIcHJvdmlkZXIYAiABKA4yJC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VQcm92aWRlckIKukgHggEEEAEgABI6CgZnaXRodWIYBCABKAsyKC5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkRhdGFzb3VyY2VDb25maWdIABI0CgNhcGkYBSABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWdIABI8CgdjcmF3bGVyGAggASgLMikuc2Fhcy5hY2NvdW50cy52MS5DcmF3bGVyRGF0YXNvdXJjZUNvbmZpZ0gAEjoKBnVwbG9hZBgJIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuVXBsb2FkRGF0YXNvdXJjZUNvbmZpZ0gAEiQKEGJvdW5kYXJ5X25vZGVfaWQYDCABKAlCCLpIBXIDsAEBSAESJgoQY29sbGVjdGlvbl9sYWJlbBgNIAEoCUIKukgHcgUQARj/AUgBEhwKCmNyZWRlbnRpYWwYBiABKAlCCLpIBXIDGIAgEiAKDndlYmhvb2tfc2VjcmV0GAcgASgJQgi6SAVyAxiACBImChRvYXV0aDJfY2xpZW50X3NlY3JldBgKIAEoCUIIukgFcgMYgAhCCAoGY29uZmlnQhEKCGJvdW5kYXJ5EgW6SAIIAUoECAMQBFIRdGFyZ2V0X2NvbGxlY3Rpb24iRQoRQWRkU291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSLkAgoTVXBkYXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIYCgZicmFuY2gYAyABKAlCCLpIBXIDGP8BEiAKBXBhdGhzGAQgAygJQhG6SA6SAQsQQCIHcgUQARiABBJJCg9maWxlX2V4dGVuc2lvbnMYBSADKAlCMLpILZIBKhAgIiZyJBACGCEyHl5cLltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJBI8CghleHBlY3RlZBgGIAEoCzIiLnNhYXMuYWNjb3VudHMudjEuU291cmNlRmV0Y2hTY29wZUIGukgDyAEBEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACIs8BChBTb3VyY2VGZXRjaFNjb3BlEhgKBmJyYW5jaBgBIAEoCUIIukgFcgMY/wESIAoFcGF0aHMYAiADKAlCEbpIDpIBCxBAIgdyBRABGIAEEikKD2ZpbGVfZXh0ZW5zaW9ucxgDIAMoCUIQukgNkgEKECAiBnIEEAEYIRIpChBpbmNsdWRlX3BhdHRlcm5zGAQgAygJQg+6SAySAQkQECIFcgMYgAISKQoQZXhjbHVkZV9wYXR0ZXJucxgFIAMoCUIPukgMkgEJEBAiBXIDGIACIlgKFFVwZGF0ZVNvdXJjZVJlc3BvbnNlEjAKCmRhdGFzb3VyY2UYASABKAsyHC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2USDgoGam9iX2lkGAIgASgJIloKFURhdGFzb3VyY2VDb25maWdGaWVsZBILCgNrZXkYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEgwKBGhlbHAYAyABKAkSEAoIcmVxdWlyZWQYBCABKAgixAEKGURhdGFzb3VyY2VDb25uZWN0b3JCdWRnZXQSGgoSbWF4X2l0ZW1zX3Blcl9jYWxsGAEgASgNEhoKEm1heF9ieXRlc19wZXJfY2FsbBgCIAEoAxIWCg5tYXhfaXRlbV9ieXRlcxgDIAEoAxIdChVvcGVyYXRpb25zX3Blcl93aW5kb3cYBCABKA0SFgoOd2luZG93X3NlY29uZHMYBSABKAMSIAoYYmFja2dyb3VuZF9zaGFyZV9wZXJjZW50GAYgASgNIqoGChxEYXRhc291cmNlUHJvdmlkZXJEZXNjcmlwdG9yEjYKCHByb3ZpZGVyGAEgASgOMiQuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUHJvdmlkZXISFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEj4KDWNvbmZpZ19maWVsZHMYBCADKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDb25maWdGaWVsZBIYChBzdXBwb3J0c193ZWJob29rGAUgASgIEkcKGnN1cHBvcnRlZF9jcmVkZW50aWFsX2tpbmRzGAYgAygOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIRCgljb25uZWN0b3IYByABKAkSQQoJaW50ZXJmYWNlGAggASgOMi4uc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQ29ubmVjdG9ySW50ZXJmYWNlEkQKEGNyZWRlbnRpYWxfbW9kZXMYCSADKA4yKi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRI/Cg1yZWFkZXJzX21vZGVsGAogASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUmVhZGVyc01vZGVsEjsKBmJ1ZGdldBgLIAEoCzIrLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUNvbm5lY3RvckJ1ZGdldBISCgpjb25mb3JtYW50GAwgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgNIAEoCRIbChNhY2NlcHRzX25ld19zb3VyY2VzGA4gASgIEiAKGGxpdmVfZGVsaXZlcnlfY29uZmlndXJlZBgPIAEoCBIaChJhY2NlcHRzX29wZXJhdGlvbnMYECABKAgSFgoOb3BlcmF0aW9uc19nYXAYESABKAkSGwoTb2F1dGhfYXV0aG9yaXplX3VybBgSIAEoCRIXCg9vYXV0aF90b2tlbl91cmwYEyABKAkSFAoMb2F1dGhfc2NvcGVzGBQgAygJIh0KG0dldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdCJhChxHZXREYXRhc291cmNlQ2F0YWxvZ1Jlc3BvbnNlEkEKCXByb3ZpZGVycxgBIAMoCzIuLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyRGVzY3JpcHRvciIuChJMaXN0U291cmNlc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJIChNMaXN0U291cmNlc1Jlc3BvbnNlEjEKC2RhdGFzb3VyY2VzGAEgAygLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIkIKEEdldFNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiRQoRR2V0U291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSJ2ChFTeW5jU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIeCgxhY2Nlc3NfdG9rZW4YAyABKAlCCLpIBXIDGIAgEhEKCXJlY29ubmVjdBgEIAEoCCIkChJTeW5jU291cmNlUmVzcG9uc2USDgoGam9iX2lkGAEgASgJImoKFEdldFNvdXJjZVN5bmNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgZqb2JfaWQYAyABKAlCC7pICNgBAXIDsAEBIpUBChJTb3VyY2VTeW5jRGVsaXZlcnkSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARItCgVzdGF0ZRgCIAEoDjIWLnNhYXMuam9icy52MS5Kb2JTdGF0ZUIGukgDyAEBEjYKCWV4ZWN1dGlvbhgDIAEoCzIjLnNhYXMuam9icy52MS5Kb2JFeGVjdXRpb25SZWZlcmVuY2UiiwEKEVNvdXJjZVN5bmNDaGFuZ2VzEg0KBWZpbGVzGAEgASgNEg0KBWFkZGVkGAIgASgNEhAKCG1vZGlmaWVkGAMgASgNEg8KB2RlbGV0ZWQYBCABKA0SEwoLc3BsaXRfa25vd24YBSABKAgSEAoIc25hcHNob3QYBiABKAgSDgoGY29tbWl0GAcgASgJIq0BChFTb3VyY2VTeW5jRmFpbHVyZRI5CgZyZWFzb24YASABKA4yKS5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNGYWlsdXJlUmVhc29uEgwKBGNvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCRIQCghyZXRyeWluZxgEIAEoCBIsCghyZXRyeV9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAQKElNvdXJjZVN5bmNQcm9ncmVzcxIwCgVwaGFzZRgBIAEoDjIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY1BoYXNlEjQKB3RyaWdnZXIYAiABKA4yIy5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNUcmlnZ2VyEi0KCXF1ZXVlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoLZmV0Y2hpbmdfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi8KC2NvbXBpbGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1oYW5kZWRfb2ZmX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIvCgtmaW5pc2hlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoHY2hhbmdlcxgIIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0NoYW5nZXMSNAoHZmFpbHVyZRgJIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0ZhaWx1cmUSDwoHYXR0ZW1wdBgKIAEoDRIUCgxtYXhfYXR0ZW1wdHMYCyABKA0i0gEKFUdldFNvdXJjZVN5bmNSZXNwb25zZRIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBEi0KBXN0YXRlGAIgASgOMhYuc2Fhcy5qb2JzLnYxLkpvYlN0YXRlQga6SAPIAQESOAoKZGVsaXZlcmllcxgDIAMoCzIkLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0RlbGl2ZXJ5EjYKCHByb2dyZXNzGAQgASgLMiQuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VTeW5jUHJvZ3Jlc3MiRQoTRGVsZXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASIWChREZWxldGVTb3VyY2VSZXNwb25zZSJWChNHaXRIdWJBcHBSZXBvc2l0b3J5EgwKBHJlcG8YASABKAkSFgoOZGVmYXVsdF9icmFuY2gYAiABKAkSGQoRYWxyZWFkeV9jb25uZWN0ZWQYAyABKAgiNgoaQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJxChtCZWdpbkdpdEh1YkFwcFNldHVwUmVzcG9uc2USEwoLaW5zdGFsbF91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAinAEKHUNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEY/wESLAoPaW5zdGFsbGF0aW9uX2lkGAMgASgJQhO6SBByDhABGCAyCF5bMC05XSskEhgKBGNvZGUYBCABKAlCCrpIB3IFEAEY/wEidgoeQ29tcGxldGVHaXRIdWJBcHBTZXR1cFJlc3BvbnNlEhcKD2luc3RhbGxhdGlvbl9pZBgBIAEoCRI7CgxyZXBvc2l0b3JpZXMYAiADKAsyJS5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkFwcFJlcG9zaXRvcnkiUQofTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASJUCiBNaWdyYXRlR2l0SHViU291cmNlVG9BcHBSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsQBChVEYXRhc291cmNlQWNjb3VudExpbmsSCgoCaWQYASABKAkSDgoGb3JnX2lkGAIgASgJEg8KB3VzZXJfaWQYAyABKAkSEQoJY29ubmVjdG9yGAQgASgJEhsKE3Byb3ZpZGVyX2FjY291bnRfaWQYBSABKAkSHgoWcHJvdmlkZXJfYWNjb3VudF9sb2dpbhgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK3AQoWRGF0YXNvdXJjZUdyb3VwQmluZGluZxIKCgJpZBgBIAEoCRIOCgZvcmdfaWQYAiABKAkSEQoJY29ubmVjdG9yGAMgASgJEhkKEXByb3ZpZGVyX2dyb3VwX2lkGAQgASgJEg8KB3RlYW1faWQYBSABKAkSEgoKY3JlYXRlZF9ieRgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKUAgoYRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRIOCgZkb21haW4YAyABKAkSOAoGc3RhdHVzGAQgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRG9tYWluU3RhdHVzEhcKD3R4dF9yZWNvcmRfbmFtZRgFIAEoCRIYChB0eHRfcmVjb3JkX3ZhbHVlGAYgASgJEi8KC3ZlcmlmaWVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjcmVhdGVkX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIzChdEYXRhc291cmNlRGlyZWN0b3J5VGVhbRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJIqYBCiFCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIeCgxyZWRpcmVjdF91cmkYAyABKAlCCLpIBXIDGIAQEhEKCXNvdXJjZV9pZBgEIAEoCSJ6CiJCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEhUKDWF1dGhvcml6ZV91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAidQokQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEYgEASGAoEY29kZRgDIAEoCUIKukgHcgUQARj/ASJeCiVDb21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEjUKBGxpbmsYASABKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VBY2NvdW50TGluayI/CiNMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBIl4KJExpc3RNeURhdGFzb3VyY2VBY2NvdW50TGlua3NSZXNwb25zZRI2CgVsaW5rcxgBIAMoCzInLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUFjY291bnRMaW5rIlQKIkRlbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiJQojRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rUmVzcG9uc2UiOQodR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASKLAgoeR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlEjYKBWxpbmtzGAEgAygLMicuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQWNjb3VudExpbmsSOgoIYmluZGluZ3MYAiADKAsyKC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VHcm91cEJpbmRpbmcSOwoHZG9tYWlucxgDIAMoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEjgKBXRlYW1zGAQgAygLMikuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRGlyZWN0b3J5VGVhbSKuAQoaQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIlChFwcm92aWRlcl9ncm91cF9pZBgDIAEoCUIKukgHcgUQARj/ARIZCgd0ZWFtX2lkGAQgASgJQgi6SAVyA7ABASJYChtCaW5kRGF0YXNvdXJjZUdyb3VwUmVzcG9uc2USOQoHYmluZGluZxgBIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUdyb3VwQmluZGluZyJOChxVbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIh8KHVVuYmluZERhdGFzb3VyY2VHcm91cFJlc3BvbnNlIlQKHENsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIaCgZkb21haW4YAiABKAlCCrpIB3IFEAMY/QEiWwodQ2xhaW1EYXRhc291cmNlRG9tYWluUmVzcG9uc2USOgoGZG9tYWluGAEgASgLMiouc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlVmVyaWZpZWREb21haW4iTwodVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiXAoeVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlEjoKBmRvbWFpbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluIk8KHURlbGV0ZURhdGFzb3VyY2VEb21haW5SZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIiAKHkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSKeAgoQU291cmNlRGVsZWdhdGlvbhIKCgJpZBgBIAEoCRIRCglzb3VyY2VfaWQYAiABKAkSFAoMcHJpbmNpcGFsX2lkGAMgASgJEg4KBm1vZHVsZRgEIAEoCRIPCgdiaW5kaW5nGAUgASgJEi4KCmNyZWF0ZWRfYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnJldm9rZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEkAKCnJldm9jYXRpb24YCCABKA4yLC5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb25SZXZvY2F0aW9uEhIKCnJldm9rZWRfYnkYCSABKAkigQEKHExpc3RTb3VyY2VEZWxlZ2F0aW9uc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIgCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBSACIAQESFwoPaW5jbHVkZV9yZXZva2VkGAMgASgIQgwKCl9zb3VyY2VfaWQiWAodTGlzdFNvdXJjZURlbGVnYXRpb25zUmVzcG9uc2USNwoLZGVsZWdhdGlvbnMYASADKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iTwodUmV2b2tlU291cmNlRGVsZWdhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiWAoeUmV2b2tlU291cmNlRGVsZWdhdGlvblJlc3BvbnNlEjYKCmRlbGVnYXRpb24YASABKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iMgoPVHJpZ2dlcklkZW50aXR5Eg4KBnNvdXJjZRgBIAEoCRIPCgdiaW5kaW5nGAIgASgJIoQBChdEZWNsYXJlZFRyaWdnZXJTY2hlZHVsZRIMCgRjcm9uGAEgASgJEhAKCHRpbWV6b25lGAIgASgJEhIKCm1pc3NlZF9ydW4YAyABKAkSDwoHb3ZlcmxhcBgEIAEoCRIQCghkZWFkbGluZRgFIAEoAxISCgppbnB1dF9qc29uGAYgASgJIucCChpUcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRIRCglyZWZlcmVuY2UYASABKAkSFQoNZGVsZWdhdGlvbl9pZBgCIAEoCRIOCgZtb2R1bGUYAyABKAkSDwoHYmluZGluZxgEIAEoCRIQCghhdWRpZW5jZRgFIAEoCRIOCgZ0ZW5hbnQYBiABKAkSGgoSb3duZXJfcHJpbmNpcGFsX2lkGAcgASgJEg4KBnNjb3BlcxgIIAMoCRIOCgZhY3RpdmUYCSABKAgSLgoKY3JlYXRlZF9hdBgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKcmV2b2tlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASQAoKcmV2b2NhdGlvbhgMIAEoDjIsLnNhYXMuYWNjb3VudHMudjEuU291cmNlRGVsZWdhdGlvblJldm9jYXRpb24ivgEKE1RyaWdnZXJDaGlsZENvbnRleHQSFQoNZGVsZWdhdGlvbl9pZBgBIAEoCRIOCgZtb2R1bGUYAiABKAkSDwoHYmluZGluZxgDIAEoCRIQCghhdWRpZW5jZRgEIAEoCRIOCgZzY29wZXMYBSADKAkSDgoGbG9va3VwGAYgASgIEi0KCW1pbnRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGcmVjb3JkGAggASgJIs0CChhTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb24SDwoHcmVsZWFzZRgBIAEoCRIRCglvcGVyYXRpb24YAiABKAkSOwoIc2NoZWR1bGUYAyABKAsyKS5zYWFzLmFjY291bnRzLnYxLkRlY2xhcmVkVHJpZ2dlclNjaGVkdWxlEjMKCGlkZW50aXR5GAQgASgLMiEuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VySWRlbnRpdHkSDgoGZGlnZXN0GAUgASgJEjYKEmxhc3Rfb2NjdXJyZW5jZV9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNgoSbmV4dF9vY2N1cnJlbmNlX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChN1bmRlY2xhcmFibGVfcmVhc29uGAggASgJIlYKHURlbGVnYXRlU291cmNlVHJpZ2dlcnNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABASJjCh5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVzcG9uc2USQQoLZGVsZWdhdGlvbnMYASADKAsyLC5zYWFzLmFjY291bnRzLnYxLlRyaWdnZXJEZWxlZ2F0aW9uUmVmZXJlbmNlIlsKIkdldFNvdXJjZVRyaWdnZXJEZWNsYXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBIuIBCiNHZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZRI/CgtkZWNsYXJhdGlvbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuU291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEkEKC2RlbGVnYXRpb25zGAIgAygLMiwuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRI3CghjaGlsZHJlbhgDIAMoCzIlLnNhYXMuYWNjb3VudHMudjEuVHJpZ2dlckNoaWxkQ29udGV4dCJuChZSZWNvbmNpbGVTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIdCgllZmZlY3RfaWQYAyABKAlCCrpIB3IFEAEYgAEiTAoXUmVjb25jaWxlU291cmNlUmVzcG9uc2USEQoJZWZmZWN0X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIOCgZqb2JfaWQYAyABKAkiPQocTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBIdCgllZmZlY3RfaWQYASABKAlCCrpIB3IFEAEYgAEi8QIKD1NvdXJjZU9wZXJhdGlvbhIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg4KBm1ldGhvZBgDIAEoCRIMCgRwYXRoGAQgASgJEg0KBXF1ZXJ5GAUgAygJEi0KDGlucHV0X3NjaGVtYRgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSLgoNb3V0cHV0X3NjaGVtYRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSOAoGZWZmZWN0GAggASgOMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24uRWZmZWN0EhgKEG1heF9vdXRwdXRfYnl0ZXMYCSABKA0SDgoGZGlnZXN0GAogASgJIksKBkVmZmVjdBIWChJFRkZFQ1RfVU5TUEVDSUZJRUQQABIUChBFRkZFQ1RfUkVBRF9PTkxZEAESEwoPRUZGRUNUX01VVEFUSU9OEAIijgEKHkRlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQESNQoKb3BlcmF0aW9ucxgDIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlgKH0RlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVzcG9uc2USNQoKb3BlcmF0aW9ucxgBIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlQKG0xpc3RTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQEiVQocTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXNwb25zZRI1CgpvcGVyYXRpb25zGAEgAygLMiEuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24irgIKHEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBEjAKCW9wZXJhdGlvbhgDIAEoCUIdukgachgyFl5bYS16XVthLXowLTlfXXswLDYzfSQSHQoKaW5wdXRfanNvbhgEIAEoCUIJukgGcgQogIAEEhsKCWVmZmVjdF9pZBgFIAEoCUIIukgFcgMogAESSQobZXhwZWN0ZWRfZGVjbGFyYXRpb25fZGlnZXN0GAYgASgJQh+6SBxyGjIYXihzaGEyNTY6WzAtOWEtZl17NjR9KT8kSACIAQFCHgocX2V4cGVjdGVkX2RlY2xhcmF0aW9uX2RpZ2VzdCJ/ChZTb3VyY2VPcGVyYXRpb25SZWNlaXB0EhEKCWVmZmVjdF9pZBgBIAEoCRIUCgxjb21taXR0ZWRfYXQYAiABKAkSDgoGc3RhdHVzGAMgASgJEhcKD3Byb3ZpZGVyX3N0YXR1cxgEIAEoDRITCgtvdXRwdXRfanNvbhgFIAEoCSJvCh1JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZRITCgtvdXRwdXRfanNvbhgBIAEoCRI5CgdyZWNlaXB0GAIgASgLMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb25SZWNlaXB0IkMKIkxvb2t1cEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSHQoJZWZmZWN0X2lkGAEgASgJQgq6SAdyBRABKIABInkKI1BydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgllZmZlY3RfaWQYAyABKAlCCLpIBXIDKIABIlsKJFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZRIRCgllZmZlY3RfaWQYASABKAkSEAoIcmVjZWlwdHMYAiABKAMSDgoGc3RhdHVzGAMgASgJIkoKKUxvb2t1cFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0Eh0KCWVmZmVjdF9pZBgBIAEoCUIKukgHcgUQASiAASq3AQoSRGF0YXNvdXJjZVByb3ZpZGVyEiMKH0RBVEFTT1VSQ0VfUFJPVklERVJfVU5TUEVDSUZJRUQQABIeChpEQVRBU09VUkNFX1BST1ZJREVSX0dJVEhVQhABEhsKF0RBVEFTT1VSQ0VfUFJPVklERVJfQVBJEAISHwobREFUQVNPVVJDRV9QUk9WSURFUl9DUkFXTEVSEAMSHgoaREFUQVNPVVJDRV9QUk9WSURFUl9VUExPQUQQBCqRAQoQRGF0YXNvdXJjZVN0YXR1cxIhCh1EQVRBU09VUkNFX1NUQVRVU19VTlNQRUNJRklFRBAAEhwKGERBVEFTT1VSQ0VfU1RBVFVTX0FDVElWRRABEhwKGERBVEFTT1VSQ0VfU1RBVFVTX1BBVVNFRBACEh4KGkRBVEFTT1VSQ0VfU1RBVFVTX0RFR1JBREVEEAMqvAEKFkRhdGFzb3VyY2VMaXZlRGVsaXZlcnkSKAokREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX1VOU1BFQ0lGSUVEEAASIQodREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX05PTkUQARIrCidEQVRBU09VUkNFX0xJVkVfREVMSVZFUllfU09VUkNFX1dFQkhPT0sQAhIoCiREQVRBU09VUkNFX0xJVkVfREVMSVZFUllfQVBQX1dFQkhPT0sQAyrWAQoRQXBpQ3JlZGVudGlhbEtpbmQSIwofQVBJX0NSRURFTlRJQUxfS0lORF9VTlNQRUNJRklFRBAAEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfQkVBUkVSEAESHQoZQVBJX0NSRURFTlRJQUxfS0lORF9CQVNJQxACEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfSEVBREVSEAMSHQoZQVBJX0NSRURFTlRJQUxfS0lORF9RVUVSWRAEEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfT0FVVEgyEAUqpgIKHERhdGFzb3VyY2VDb25uZWN0b3JJbnRlcmZhY2USLgoqREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1VOU1BFQ0lGSUVEEAASKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX0ZJTEVTEAESKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1BBR0VTEAISKgomREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1JFQ09SRFMQAxIrCidEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfTUVTU0FHRVMQBBIpCiVEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfRVZFTlRTEAUq7AEKGERhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRIqCiZEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9VTlNQRUNJRklFRBAAEiMKH0RBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX05PTkUQARImCiJEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9PUkdfQVBQEAISKQolREFUQVNPVVJDRV9DUkVERU5USUFMX01PREVfVVNFUl9PQVVUSBADEiwKKERBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX1NUQVRJQ19TRUNSRVQQBCqXAQoWRGF0YXNvdXJjZVJlYWRlcnNNb2RlbBIoCiREQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfVU5TUEVDSUZJRUQQABIqCiZEQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfU09VUkNFX1NDT1BFRBABEicKI0RBVEFTT1VSQ0VfUkVBREVSU19NT0RFTF9UUkFOU0xBVEVEEAIq7gEKD1NvdXJjZVN5bmNQaGFzZRIhCh1TT1VSQ0VfU1lOQ19QSEFTRV9VTlNQRUNJRklFRBAAEhwKGFNPVVJDRV9TWU5DX1BIQVNFX1FVRVVFRBABEh4KGlNPVVJDRV9TWU5DX1BIQVNFX0ZFVENISU5HEAISHgoaU09VUkNFX1NZTkNfUEhBU0VfQ09NUElMRUQQAxIgChxTT1VSQ0VfU1lOQ19QSEFTRV9IQU5ERURfT0ZGEAQSGgoWU09VUkNFX1NZTkNfUEhBU0VfRE9ORRAFEhwKGFNPVVJDRV9TWU5DX1BIQVNFX0ZBSUxFRBAGKqYDChdTb3VyY2VTeW5jRmFpbHVyZVJlYXNvbhIqCiZTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEisKJ1NPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX1JBVEVfTElNSVRFRBABEikKJVNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX0NSRURFTlRJQUwQAhIsCihTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9BQ0NFU1NfREVOSUVEEAMSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fTk9UX0ZPVU5EEAQSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fVE9PX0xBUkdFEAUSLworU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fSE9TVF9VTkFWQUlMQUJMRRAGEiQKIFNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX09USEVSEAcSLgoqU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fREVMSVZFUllfRkFJTEVEEAgqwgEKEVNvdXJjZVN5bmNUcmlnZ2VyEiMKH1NPVVJDRV9TWU5DX1RSSUdHRVJfVU5TUEVDSUZJRUQQABIeChpTT1VSQ0VfU1lOQ19UUklHR0VSX01BTlVBTBABEiEKHVNPVVJDRV9TWU5DX1RSSUdHRVJfU0NIRURVTEVEEAISHwobU09VUkNFX1NZTkNfVFJJR0dFUl9XRUJIT09LEAMSJAogU09VUkNFX1NZTkNfVFJJR0dFUl9SRUNPTkZJR1VSRUQQBCqPAQoWRGF0YXNvdXJjZURvbWFpblN0YXR1cxIoCiREQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIkCiBEQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfUEVORElORxABEiUKIURBVEFTT1VSQ0VfRE9NQUlOX1NUQVRVU19WRVJJRklFRBACKpUDChpTb3VyY2VEZWxlZ2F0aW9uUmV2b2NhdGlvbhIsCihTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VOU1BFQ0lGSUVEEAASKAokU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVZPS0VEEAESKQolU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVBMQUNFRBACEi8KK1NPVVJDRV9ERUxFR0FUSU9OX1JFVk9DQVRJT05fU09VUkNFX0RFTEVURUQQAxIvCitTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX01FTUJFUl9SRU1PVkVEEAQSMAosU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9QRVJNSVNTSU9OX0xPU1QQBRIuCipTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VTRVJfSU5BQ1RJVkUQBhIwCixTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX0JJTkRJTkdfQ0hBTkdFRBAHMtc7ChFEYXRhc291cmNlU2VydmljZRK5AwocUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI1LnNhYXMuYWNjb3VudHMudjEuUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSKpAsLzGGwIAhADGhFkYXRhc291cmNlOmludm9rZSIRZGF0YXNvdXJjZTppbnZva2UqDwoJc291cmNlX2lkEAQYAzABOiMKH3NhYXMuZGF0YXNvdXJjZS5yZWNlaXB0cy5wcnVuZWQQAkADSARQA1gDYAHa8xi0AQoCCDwSAwjYBBgFIgIIAioLVU5BVkFJTEFCTEUqElJFU09VUkNFX0VYSEFVU1RFRCoHQUJPUlRFRDIPc2Fhcy1kYXRhc291cmNlSkYvc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlU2VydmljZS9Mb29rdXBQcnVuZVNvdXJjZU9wZXJhdGlvblJlY2VpcHRzUIAgWIAgYAFyGAoGc291cmNlEgZpbnZva2USBHJlYWQYARLmAQoiTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI7LnNhYXMuYWNjb3VudHMudjEuTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSJLwvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUANYA2ABEvwDChVJbnZva2VTb3VyY2VPcGVyYXRpb24SLi5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlc3BvbnNlIoEDwvMYbggCEAMaEWRhdGFzb3VyY2U6aW52b2tlIhFkYXRhc291cmNlOmludm9rZSoPCglzb3VyY2VfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEARAA0gEUARYBGAB2vMYrwEKAgg8EgMI2AQYBSICCAIqC1VOQVZBSUxBQkxFKhJSRVNPVVJDRV9FWEhBVVNURUQqB0FCT1JURUQyD3NhYXMtZGF0YXNvdXJjZUo/L3NhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVNlcnZpY2UvTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uUICABFiAgEBgAXIYCgZzb3VyY2USBmludm9rZRIEcmVhZBgBgtPkkwJVOgEqIlAvdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zL3tvcGVyYXRpb259Omludm9rZRKHAgobTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5Mb29rdXBJbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKAAcLzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ADWARgAYLT5JMCLxItL3YxL2RhdGFzb3VyY2Utb3BlcmF0aW9uLXJlY2VpcHRzL3tlZmZlY3RfaWR9EqMCChxWZXJpZnlTb3VyY2VPcGVyYXRpb25SZWNlaXB0Ei4uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKhAcLzGGoIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEANAAUgDUARYBGABgtPkkwItOgEqIigvdjEvZGF0YXNvdXJjZS1vcGVyYXRpb24tcmVjZWlwdHMvdmVyaWZ5EoUCChRMaXN0U291cmNlT3BlcmF0aW9ucxItLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0Gi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIo0BwvMYRAgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKgwKBm9yZ19pZBACGAEwAToCEAFAAUgDUANYA2ABgtPkkwI/Ej0vdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zEpMCChdEZWNsYXJlU291cmNlT3BlcmF0aW9ucxIwLnNhYXMuYWNjb3VudHMudjEuRGVjbGFyZVNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0GjEuc2Fhcy5hY2NvdW50cy52MS5EZWNsYXJlU291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIpIBwvMYRggCEAQqDAoGb3JnX2lkEAIYATABOiYKInNhYXMuZGF0YXNvdXJjZS5vcGVyYXRpb24uZGVjbGFyZWQQAkABSARQA1gDYAGC0+STAkI6ASoiPS92MS9vcmdhbml6YXRpb25zL3tvcmdfaWR9L2RhdGFzb3VyY2VzL3tzb3VyY2VfaWR9L29wZXJhdGlvbnMSrAEKD0FkZEdpdEh1YlNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVzcG9uc2UiRMLzGEAIAhAEKgwKBm9yZ19pZBACGAEwATogChxzYWFzLmRhdGFzb3VyY2Uuc291cmNlLmFkZGVkEAJAAUgEUARYA2ABEpoBCglBZGRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlc3BvbnNlIkTC8xhACAIQBCoMCgZvcmdfaWQQAhgBMAE6IAocc2Fhcy5kYXRhc291cmNlLnNvdXJjZS5hZGRlZBACQAFIBFAEWANgARKlAQoMVXBkYXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UudXBkYXRlZBACQAFIBFACWANgARKPAQoUR2V0RGF0YXNvdXJjZUNhdGFsb2cSLS5zYWFzLmFjY291bnRzLnYxLkdldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdBouLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZUNhdGFsb2dSZXNwb25zZSIYwvMYFAgCEAEwAToCEAFAAUgDUAJYAmABEoIBCgtMaXN0U291cmNlcxIkLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZXNSZXF1ZXN0GiUuc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARJ8CglHZXRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKeAQoKU3luY1NvdXJjZRIjLnNhYXMuYWNjb3VudHMudjEuU3luY1NvdXJjZVJlcXVlc3QaJC5zYWFzLmFjY291bnRzLnYxLlN5bmNTb3VyY2VSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5zb3VyY2Uuc3luY2VkEAJAAUgEUARYAmABEogBCg1HZXRTb3VyY2VTeW5jEiYuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VTeW5jUmVxdWVzdBonLnNhYXMuYWNjb3VudHMudjEuR2V0U291cmNlU3luY1Jlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKlAQoMRGVsZXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UucmVtb3ZlZBACQAFIBFACWAJgARLEAQoTQmVnaW5HaXRIdWJBcHBTZXR1cBIsLnNhYXMuYWNjb3VudHMudjEuQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJlZ2luR2l0SHViQXBwU2V0dXBSZXNwb25zZSJQwvMYTAgCEAQqDAoGb3JnX2lkEAIYATABOiwKKHNhYXMuZGF0YXNvdXJjZS5naXRodWJfYXBwLnNldHVwX3N0YXJ0ZWQQAkABSARQAlgEYAESzwEKFkNvbXBsZXRlR2l0SHViQXBwU2V0dXASLy5zYWFzLmFjY291bnRzLnYxLkNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZUdpdEh1YkFwcFNldHVwUmVzcG9uc2UiUsLzGE4IAhAEKgwKBm9yZ19pZBACGAEwATouCipzYWFzLmRhdGFzb3VyY2UuZ2l0aHViX2FwcC5zZXR1cF9jb21wbGV0ZWQQAkABSARQBFgDYAESzQEKGE1pZ3JhdGVHaXRIdWJTb3VyY2VUb0FwcBIxLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBoyLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuY3JlZGVudGlhbC51cGRhdGVkEAJAAUgEUAJYA2ABEtUBChpCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGluaxIzLnNhYXMuYWNjb3VudHMudjEuQmVnaW5EYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjQuc2Fhcy5hY2NvdW50cy52MS5CZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkzC8xhICAIQAyoMCgZvcmdfaWQQAhgBMAE6KAokc2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua19zdGFydGVkEAJAAUgEUAJYBGABEtgBCh1Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGluaxI2LnNhYXMuYWNjb3VudHMudjEuQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0Gjcuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkbC8xhCCAIQAyoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua2VkEAJAAUgEUARYA2ABErUBChxMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzEjUuc2Fhcy5hY2NvdW50cy52MS5MaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBo2LnNhYXMuYWNjb3VudHMudjEuTGlzdE15RGF0YXNvdXJjZUFjY291bnRMaW5rc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARLUAQobRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rEjQuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXNwb25zZSJIwvMYRAgCEAMqDAoGb3JnX2lkEAIYATABOiQKIHNhYXMuZGF0YXNvdXJjZS5hY2NvdW50X3VubGlua2VkEAJAAUgEUAJYA2ABEqMBChZHZXREYXRhc291cmNlRGlyZWN0b3J5Ei8uc2Fhcy5hY2NvdW50cy52MS5HZXREYXRhc291cmNlRGlyZWN0b3J5UmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARK3AQoTQmluZERhdGFzb3VyY2VHcm91cBIsLnNhYXMuYWNjb3VudHMudjEuQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJDwvMYPwgCEAQqDAoGb3JnX2lkEAIYATABOh8KG3NhYXMuZGF0YXNvdXJjZS5ncm91cF9ib3VuZBACQAFIBFACWANgARK/AQoVVW5iaW5kRGF0YXNvdXJjZUdyb3VwEi4uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5ncm91cF91bmJvdW5kEAJAAUgEUAJYA2ABEsABChVDbGFpbURhdGFzb3VyY2VEb21haW4SLi5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkbC8xhCCAIQBCoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmRvbWFpbl9jbGFpbWVkEAJAAUgEUAJYA2ABEsQBChZWZXJpZnlEYXRhc291cmNlRG9tYWluEi8uc2Fhcy5hY2NvdW50cy52MS5WZXJpZnlEYXRhc291cmNlRG9tYWluUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkfC8xhDCAIQBCoMCgZvcmdfaWQQAhgBMAE6Iwofc2Fhcy5kYXRhc291cmNlLmRvbWFpbl92ZXJpZmllZBACQAFIBFACWANgARLDAQoWRGVsZXRlRGF0YXNvdXJjZURvbWFpbhIvLnNhYXMuYWNjb3VudHMudjEuRGVsZXRlRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaMC5zYWFzLmFjY291bnRzLnYxLkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5kb21haW5fcmVtb3ZlZBACQAFIBFACWANgARKgAQoVTGlzdFNvdXJjZURlbGVnYXRpb25zEi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESxwEKFlJldm9rZVNvdXJjZURlbGVnYXRpb24SLy5zYWFzLmFjY291bnRzLnYxLlJldm9rZVNvdXJjZURlbGVnYXRpb25SZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5SZXZva2VTb3VyY2VEZWxlZ2F0aW9uUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuZGVsZWdhdGlvbi5yZXZva2VkEAJAAUgEUAJYA2ABEusBChZEZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzEi8uc2Fhcy5hY2NvdW50cy52MS5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuRGVsZWdhdGVTb3VyY2VUcmlnZ2Vyc1Jlc3BvbnNlIm7C8xhqCAIQBCoMCgZvcmdfaWQQAhgBMAE6Sgoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24uY3JlYXRlZAoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24ucmV2b2tlZBACQAFIBFACWANgARKyAQobR2V0U291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESgwMKD1JlY29uY2lsZVNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UimgLC8xhqCAIQAxoRZGF0YXNvdXJjZTppbnZva2UiEWRhdGFzb3VyY2U6aW52b2tlKg8KCXNvdXJjZV9pZBAEGAMwATohCh1zYWFzLmRhdGFzb3VyY2Uuc291cmNlLnN5bmNlZBACQANIBFACWAJgAdrzGKcBCgIIPBIDCNgEGAUiAggCKgtVTkFWQUlMQUJMRSoSUkVTT1VSQ0VfRVhIQVVTVEVEKgdBQk9SVEVEMg9zYWFzLWRhdGFzb3VyY2VKOS9zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTZXJ2aWNlL0xvb2t1cFJlY29uY2lsZVNvdXJjZVCAIFiAIGABchgKBnNvdXJjZRIGaW52b2tlEgRyZWFkGAESvwEKFUxvb2t1cFJlY29uY2lsZVNvdXJjZRIuLnNhYXMuYWNjb3VudHMudjEuTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UiS8LzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ACWAJgAWIGcHJvdG8z", [file_buf_validate_validate, file_codefly_runnable_v0_options, file_google_api_annotations, file_google_protobuf_duration, file_google_protobuf_struct, file_google_protobuf_timestamp, file_saas_jobs_v1_jobs, file_saas_policy_v1_options]); /** * GitHubDatasourceConfig is the public, non-secret configuration of a GitHub @@ -4233,6 +4233,8 @@ export const DatasourceService: GenService<{ * Committed means the normalized request and admitted declaration match the * stored attempt. Unknown remains unresolved; this method never redispatches. * Current actor, tenant and stored-source read authority apply before comparison. + * Source-scope refusals emit the existing failure audit; successful reads do not + * record another invocation or change the retained receipt. * This is independent of the paired Runnable Lookup contract above. * * @generated from rpc saas.accounts.v1.DatasourceService.VerifySourceOperationReceipt diff --git a/module/services/frontend/code/src/gen/saas/accounts/v1/datasource_pb.ts b/module/services/frontend/code/src/gen/saas/accounts/v1/datasource_pb.ts index 5565af190..945f6739d 100644 --- a/module/services/frontend/code/src/gen/saas/accounts/v1/datasource_pb.ts +++ b/module/services/frontend/code/src/gen/saas/accounts/v1/datasource_pb.ts @@ -18,7 +18,7 @@ import type { JsonObject, Message } from "@bufbuild/protobuf"; * Describes the file saas/accounts/v1/datasource.proto. */ export const file_saas_accounts_v1_datasource: GenFile = /*@__PURE__*/ - fileDesc("CiFzYWFzL2FjY291bnRzL3YxL2RhdGFzb3VyY2UucHJvdG8SEHNhYXMuYWNjb3VudHMudjEiXgoWR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIMCgRyZXBvGAEgASgJEg0KBXBhdGhzGAIgAygJEg4KBmJyYW5jaBgDIAEoCRIXCg9maWxlX2V4dGVuc2lvbnMYBCADKAki9AEKD0FwaU9BdXRoMkNvbmZpZxI2CgVncmFudBgEIAEoDjInLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnLkdyYW50EhEKCXRva2VuX3VybBgBIAEoCRIRCgljbGllbnRfaWQYAiABKAkSDgoGc2NvcGVzGAMgAygJInMKBUdyYW50EhUKEUdSQU5UX1VOU1BFQ0lGSUVEEAASFwoTR1JBTlRfUkVGUkVTSF9UT0tFThABEhwKGEdSQU5UX0NMSUVOVF9DUkVERU5USUFMUxACEhwKGEdSQU5UX0FVVEhPUklaQVRJT05fQ09ERRADIuoBChNBcGlEYXRhc291cmNlQ29uZmlnEhAKCGJhc2VfdXJsGAEgASgJEhUKDXJlc291cmNlX3BhdGgYAiABKAkSPAoPY3JlZGVudGlhbF9raW5kGAMgASgOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIZChFjcmVkZW50aWFsX2hlYWRlchgEIAEoCRIeChZjcmVkZW50aWFsX3F1ZXJ5X3BhcmFtGAUgASgJEjEKBm9hdXRoMhgGIAEoCzIhLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnIkEKF0NyYXdsZXJEYXRhc291cmNlQ29uZmlnEhMKC3NpdGVtYXBfdXJsGAEgASgJEhEKCW1heF9wYWdlcxgCIAEoDSKrAgoWVXBsb2FkRGF0YXNvdXJjZUNvbmZpZxIQCghlbmRwb2ludBgBIAEoCRIOCgZyZWdpb24YAiABKAkSDgoGYnVja2V0GAMgASgJEg4KBnByZWZpeBgEIAEoCRIVCg1hY2Nlc3Nfa2V5X2lkGAUgASgJEhMKC21heF9vYmplY3RzGAYgASgNEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACEkkKD2ZpbGVfZXh0ZW5zaW9ucxgJIAMoCUIwukgtkgEqECAiJnIkEAIYITIeXlwuW0EtWmEtejAtOV1bQS1aYS16MC05Ll8tXSokIoMHCgpEYXRhc291cmNlEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRI2Cghwcm92aWRlchgDIAEoDjIkLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyEjgKBmdpdGh1YhgFIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIyCgZzdGF0dXMYBiABKA4yIi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTdGF0dXMSGgoSd2ViaG9va19jb25maWd1cmVkGAcgASgIEi4KCmNyZWF0ZWRfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDmxhc3Rfc3luY2VkX2F0GAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgNhcGkYCyABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWcSOgoHY3Jhd2xlchgMIAEoCzIpLnNhYXMuYWNjb3VudHMudjEuQ3Jhd2xlckRhdGFzb3VyY2VDb25maWcSOAoGdXBsb2FkGA0gASgLMiguc2Fhcy5hY2NvdW50cy52MS5VcGxvYWREYXRhc291cmNlQ29uZmlnEhgKEGJvdW5kYXJ5X25vZGVfaWQYDiABKAkSNAoQbGFzdF9pbmdlc3RlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHAoUbGFzdF9pbmdlc3RlZF9jb21taXQYECABKAkSFQoNc3RhdHVzX3JlYXNvbhgRIAEoCRIWCg5ib3VuZGFyeV9sYWJlbBgSIAEoCRISCgpjb25mb3JtYW50GBMgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgUIAEoCRI/Cg1saXZlX2RlbGl2ZXJ5GBUgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlTGl2ZURlbGl2ZXJ5EjUKEnJlY29uY2lsZV9pbnRlcnZhbBgWIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkoECAQQBVIRdGFyZ2V0X2NvbGxlY3Rpb24isgMKFkFkZEdpdEh1YlNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI7CgRyZXBvGAIgASgJQi26SCpyKBADGP8BMiFeW0EtWmEtejAtOV8uLV0rL1tBLVphLXowLTlfLi1dKyQSIAoFcGF0aHMYAyADKAlCEbpIDpIBCxBAIgdyBRABGIAEEhgKBmJyYW5jaBgEIAEoCUIIukgFcgMY/wESJAoQYm91bmRhcnlfbm9kZV9pZBgIIAEoCUIIukgFcgOwAQFIABImChBjb2xsZWN0aW9uX2xhYmVsGAkgASgJQgq6SAdyBRABGP8BSAASHgoMYWNjZXNzX3Rva2VuGAYgASgJQgi6SAVyAxiACBIgCg53ZWJob29rX3NlY3JldBgHIAEoCUIIukgFcgMYgAgSSQoPZmlsZV9leHRlbnNpb25zGAogAygJQjC6SC2SASoQICImciQQAhghMh5eXC5bQS1aYS16MC05XVtBLVphLXowLTkuXy1dKiRCEQoIYm91bmRhcnkSBbpIAggBSgQIBRAGUhF0YXJnZXRfY29sbGVjdGlvbiJLChdBZGRHaXRIdWJTb3VyY2VSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsgEChBBZGRTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESQgoIcHJvdmlkZXIYAiABKA4yJC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VQcm92aWRlckIKukgHggEEEAEgABI6CgZnaXRodWIYBCABKAsyKC5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkRhdGFzb3VyY2VDb25maWdIABI0CgNhcGkYBSABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWdIABI8CgdjcmF3bGVyGAggASgLMikuc2Fhcy5hY2NvdW50cy52MS5DcmF3bGVyRGF0YXNvdXJjZUNvbmZpZ0gAEjoKBnVwbG9hZBgJIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuVXBsb2FkRGF0YXNvdXJjZUNvbmZpZ0gAEiQKEGJvdW5kYXJ5X25vZGVfaWQYDCABKAlCCLpIBXIDsAEBSAESJgoQY29sbGVjdGlvbl9sYWJlbBgNIAEoCUIKukgHcgUQARj/AUgBEhwKCmNyZWRlbnRpYWwYBiABKAlCCLpIBXIDGIAgEiAKDndlYmhvb2tfc2VjcmV0GAcgASgJQgi6SAVyAxiACBImChRvYXV0aDJfY2xpZW50X3NlY3JldBgKIAEoCUIIukgFcgMYgAhCCAoGY29uZmlnQhEKCGJvdW5kYXJ5EgW6SAIIAUoECAMQBFIRdGFyZ2V0X2NvbGxlY3Rpb24iRQoRQWRkU291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSLkAgoTVXBkYXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIYCgZicmFuY2gYAyABKAlCCLpIBXIDGP8BEiAKBXBhdGhzGAQgAygJQhG6SA6SAQsQQCIHcgUQARiABBJJCg9maWxlX2V4dGVuc2lvbnMYBSADKAlCMLpILZIBKhAgIiZyJBACGCEyHl5cLltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJBI8CghleHBlY3RlZBgGIAEoCzIiLnNhYXMuYWNjb3VudHMudjEuU291cmNlRmV0Y2hTY29wZUIGukgDyAEBEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACIs8BChBTb3VyY2VGZXRjaFNjb3BlEhgKBmJyYW5jaBgBIAEoCUIIukgFcgMY/wESIAoFcGF0aHMYAiADKAlCEbpIDpIBCxBAIgdyBRABGIAEEikKD2ZpbGVfZXh0ZW5zaW9ucxgDIAMoCUIQukgNkgEKECAiBnIEEAEYIRIpChBpbmNsdWRlX3BhdHRlcm5zGAQgAygJQg+6SAySAQkQECIFcgMYgAISKQoQZXhjbHVkZV9wYXR0ZXJucxgFIAMoCUIPukgMkgEJEBAiBXIDGIACIlgKFFVwZGF0ZVNvdXJjZVJlc3BvbnNlEjAKCmRhdGFzb3VyY2UYASABKAsyHC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2USDgoGam9iX2lkGAIgASgJIloKFURhdGFzb3VyY2VDb25maWdGaWVsZBILCgNrZXkYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEgwKBGhlbHAYAyABKAkSEAoIcmVxdWlyZWQYBCABKAgixAEKGURhdGFzb3VyY2VDb25uZWN0b3JCdWRnZXQSGgoSbWF4X2l0ZW1zX3Blcl9jYWxsGAEgASgNEhoKEm1heF9ieXRlc19wZXJfY2FsbBgCIAEoAxIWCg5tYXhfaXRlbV9ieXRlcxgDIAEoAxIdChVvcGVyYXRpb25zX3Blcl93aW5kb3cYBCABKA0SFgoOd2luZG93X3NlY29uZHMYBSABKAMSIAoYYmFja2dyb3VuZF9zaGFyZV9wZXJjZW50GAYgASgNIqoGChxEYXRhc291cmNlUHJvdmlkZXJEZXNjcmlwdG9yEjYKCHByb3ZpZGVyGAEgASgOMiQuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUHJvdmlkZXISFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEj4KDWNvbmZpZ19maWVsZHMYBCADKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDb25maWdGaWVsZBIYChBzdXBwb3J0c193ZWJob29rGAUgASgIEkcKGnN1cHBvcnRlZF9jcmVkZW50aWFsX2tpbmRzGAYgAygOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIRCgljb25uZWN0b3IYByABKAkSQQoJaW50ZXJmYWNlGAggASgOMi4uc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQ29ubmVjdG9ySW50ZXJmYWNlEkQKEGNyZWRlbnRpYWxfbW9kZXMYCSADKA4yKi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRI/Cg1yZWFkZXJzX21vZGVsGAogASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUmVhZGVyc01vZGVsEjsKBmJ1ZGdldBgLIAEoCzIrLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUNvbm5lY3RvckJ1ZGdldBISCgpjb25mb3JtYW50GAwgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgNIAEoCRIbChNhY2NlcHRzX25ld19zb3VyY2VzGA4gASgIEiAKGGxpdmVfZGVsaXZlcnlfY29uZmlndXJlZBgPIAEoCBIaChJhY2NlcHRzX29wZXJhdGlvbnMYECABKAgSFgoOb3BlcmF0aW9uc19nYXAYESABKAkSGwoTb2F1dGhfYXV0aG9yaXplX3VybBgSIAEoCRIXCg9vYXV0aF90b2tlbl91cmwYEyABKAkSFAoMb2F1dGhfc2NvcGVzGBQgAygJIh0KG0dldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdCJhChxHZXREYXRhc291cmNlQ2F0YWxvZ1Jlc3BvbnNlEkEKCXByb3ZpZGVycxgBIAMoCzIuLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyRGVzY3JpcHRvciIuChJMaXN0U291cmNlc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJIChNMaXN0U291cmNlc1Jlc3BvbnNlEjEKC2RhdGFzb3VyY2VzGAEgAygLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIkIKEEdldFNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiRQoRR2V0U291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSJ2ChFTeW5jU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIeCgxhY2Nlc3NfdG9rZW4YAyABKAlCCLpIBXIDGIAgEhEKCXJlY29ubmVjdBgEIAEoCCIkChJTeW5jU291cmNlUmVzcG9uc2USDgoGam9iX2lkGAEgASgJImoKFEdldFNvdXJjZVN5bmNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgZqb2JfaWQYAyABKAlCC7pICNgBAXIDsAEBIpUBChJTb3VyY2VTeW5jRGVsaXZlcnkSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARItCgVzdGF0ZRgCIAEoDjIWLnNhYXMuam9icy52MS5Kb2JTdGF0ZUIGukgDyAEBEjYKCWV4ZWN1dGlvbhgDIAEoCzIjLnNhYXMuam9icy52MS5Kb2JFeGVjdXRpb25SZWZlcmVuY2UiiwEKEVNvdXJjZVN5bmNDaGFuZ2VzEg0KBWZpbGVzGAEgASgNEg0KBWFkZGVkGAIgASgNEhAKCG1vZGlmaWVkGAMgASgNEg8KB2RlbGV0ZWQYBCABKA0SEwoLc3BsaXRfa25vd24YBSABKAgSEAoIc25hcHNob3QYBiABKAgSDgoGY29tbWl0GAcgASgJIq0BChFTb3VyY2VTeW5jRmFpbHVyZRI5CgZyZWFzb24YASABKA4yKS5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNGYWlsdXJlUmVhc29uEgwKBGNvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCRIQCghyZXRyeWluZxgEIAEoCBIsCghyZXRyeV9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAQKElNvdXJjZVN5bmNQcm9ncmVzcxIwCgVwaGFzZRgBIAEoDjIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY1BoYXNlEjQKB3RyaWdnZXIYAiABKA4yIy5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNUcmlnZ2VyEi0KCXF1ZXVlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoLZmV0Y2hpbmdfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi8KC2NvbXBpbGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1oYW5kZWRfb2ZmX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIvCgtmaW5pc2hlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoHY2hhbmdlcxgIIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0NoYW5nZXMSNAoHZmFpbHVyZRgJIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0ZhaWx1cmUSDwoHYXR0ZW1wdBgKIAEoDRIUCgxtYXhfYXR0ZW1wdHMYCyABKA0i0gEKFUdldFNvdXJjZVN5bmNSZXNwb25zZRIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBEi0KBXN0YXRlGAIgASgOMhYuc2Fhcy5qb2JzLnYxLkpvYlN0YXRlQga6SAPIAQESOAoKZGVsaXZlcmllcxgDIAMoCzIkLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0RlbGl2ZXJ5EjYKCHByb2dyZXNzGAQgASgLMiQuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VTeW5jUHJvZ3Jlc3MiRQoTRGVsZXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASIWChREZWxldGVTb3VyY2VSZXNwb25zZSJWChNHaXRIdWJBcHBSZXBvc2l0b3J5EgwKBHJlcG8YASABKAkSFgoOZGVmYXVsdF9icmFuY2gYAiABKAkSGQoRYWxyZWFkeV9jb25uZWN0ZWQYAyABKAgiNgoaQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJxChtCZWdpbkdpdEh1YkFwcFNldHVwUmVzcG9uc2USEwoLaW5zdGFsbF91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAinAEKHUNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEY/wESLAoPaW5zdGFsbGF0aW9uX2lkGAMgASgJQhO6SBByDhABGCAyCF5bMC05XSskEhgKBGNvZGUYBCABKAlCCrpIB3IFEAEY/wEidgoeQ29tcGxldGVHaXRIdWJBcHBTZXR1cFJlc3BvbnNlEhcKD2luc3RhbGxhdGlvbl9pZBgBIAEoCRI7CgxyZXBvc2l0b3JpZXMYAiADKAsyJS5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkFwcFJlcG9zaXRvcnkiUQofTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASJUCiBNaWdyYXRlR2l0SHViU291cmNlVG9BcHBSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsQBChVEYXRhc291cmNlQWNjb3VudExpbmsSCgoCaWQYASABKAkSDgoGb3JnX2lkGAIgASgJEg8KB3VzZXJfaWQYAyABKAkSEQoJY29ubmVjdG9yGAQgASgJEhsKE3Byb3ZpZGVyX2FjY291bnRfaWQYBSABKAkSHgoWcHJvdmlkZXJfYWNjb3VudF9sb2dpbhgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK3AQoWRGF0YXNvdXJjZUdyb3VwQmluZGluZxIKCgJpZBgBIAEoCRIOCgZvcmdfaWQYAiABKAkSEQoJY29ubmVjdG9yGAMgASgJEhkKEXByb3ZpZGVyX2dyb3VwX2lkGAQgASgJEg8KB3RlYW1faWQYBSABKAkSEgoKY3JlYXRlZF9ieRgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKUAgoYRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRIOCgZkb21haW4YAyABKAkSOAoGc3RhdHVzGAQgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRG9tYWluU3RhdHVzEhcKD3R4dF9yZWNvcmRfbmFtZRgFIAEoCRIYChB0eHRfcmVjb3JkX3ZhbHVlGAYgASgJEi8KC3ZlcmlmaWVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjcmVhdGVkX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIzChdEYXRhc291cmNlRGlyZWN0b3J5VGVhbRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJIqYBCiFCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIeCgxyZWRpcmVjdF91cmkYAyABKAlCCLpIBXIDGIAQEhEKCXNvdXJjZV9pZBgEIAEoCSJ6CiJCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEhUKDWF1dGhvcml6ZV91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAidQokQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEYgEASGAoEY29kZRgDIAEoCUIKukgHcgUQARj/ASJeCiVDb21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEjUKBGxpbmsYASABKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VBY2NvdW50TGluayI/CiNMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBIl4KJExpc3RNeURhdGFzb3VyY2VBY2NvdW50TGlua3NSZXNwb25zZRI2CgVsaW5rcxgBIAMoCzInLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUFjY291bnRMaW5rIlQKIkRlbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiJQojRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rUmVzcG9uc2UiOQodR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASKLAgoeR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlEjYKBWxpbmtzGAEgAygLMicuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQWNjb3VudExpbmsSOgoIYmluZGluZ3MYAiADKAsyKC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VHcm91cEJpbmRpbmcSOwoHZG9tYWlucxgDIAMoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEjgKBXRlYW1zGAQgAygLMikuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRGlyZWN0b3J5VGVhbSKuAQoaQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIlChFwcm92aWRlcl9ncm91cF9pZBgDIAEoCUIKukgHcgUQARj/ARIZCgd0ZWFtX2lkGAQgASgJQgi6SAVyA7ABASJYChtCaW5kRGF0YXNvdXJjZUdyb3VwUmVzcG9uc2USOQoHYmluZGluZxgBIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUdyb3VwQmluZGluZyJOChxVbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIh8KHVVuYmluZERhdGFzb3VyY2VHcm91cFJlc3BvbnNlIlQKHENsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIaCgZkb21haW4YAiABKAlCCrpIB3IFEAMY/QEiWwodQ2xhaW1EYXRhc291cmNlRG9tYWluUmVzcG9uc2USOgoGZG9tYWluGAEgASgLMiouc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlVmVyaWZpZWREb21haW4iTwodVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiXAoeVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlEjoKBmRvbWFpbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluIk8KHURlbGV0ZURhdGFzb3VyY2VEb21haW5SZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIiAKHkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSKeAgoQU291cmNlRGVsZWdhdGlvbhIKCgJpZBgBIAEoCRIRCglzb3VyY2VfaWQYAiABKAkSFAoMcHJpbmNpcGFsX2lkGAMgASgJEg4KBm1vZHVsZRgEIAEoCRIPCgdiaW5kaW5nGAUgASgJEi4KCmNyZWF0ZWRfYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnJldm9rZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEkAKCnJldm9jYXRpb24YCCABKA4yLC5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb25SZXZvY2F0aW9uEhIKCnJldm9rZWRfYnkYCSABKAkigQEKHExpc3RTb3VyY2VEZWxlZ2F0aW9uc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIgCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBSACIAQESFwoPaW5jbHVkZV9yZXZva2VkGAMgASgIQgwKCl9zb3VyY2VfaWQiWAodTGlzdFNvdXJjZURlbGVnYXRpb25zUmVzcG9uc2USNwoLZGVsZWdhdGlvbnMYASADKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iTwodUmV2b2tlU291cmNlRGVsZWdhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiWAoeUmV2b2tlU291cmNlRGVsZWdhdGlvblJlc3BvbnNlEjYKCmRlbGVnYXRpb24YASABKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iMgoPVHJpZ2dlcklkZW50aXR5Eg4KBnNvdXJjZRgBIAEoCRIPCgdiaW5kaW5nGAIgASgJIoQBChdEZWNsYXJlZFRyaWdnZXJTY2hlZHVsZRIMCgRjcm9uGAEgASgJEhAKCHRpbWV6b25lGAIgASgJEhIKCm1pc3NlZF9ydW4YAyABKAkSDwoHb3ZlcmxhcBgEIAEoCRIQCghkZWFkbGluZRgFIAEoAxISCgppbnB1dF9qc29uGAYgASgJIucCChpUcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRIRCglyZWZlcmVuY2UYASABKAkSFQoNZGVsZWdhdGlvbl9pZBgCIAEoCRIOCgZtb2R1bGUYAyABKAkSDwoHYmluZGluZxgEIAEoCRIQCghhdWRpZW5jZRgFIAEoCRIOCgZ0ZW5hbnQYBiABKAkSGgoSb3duZXJfcHJpbmNpcGFsX2lkGAcgASgJEg4KBnNjb3BlcxgIIAMoCRIOCgZhY3RpdmUYCSABKAgSLgoKY3JlYXRlZF9hdBgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKcmV2b2tlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASQAoKcmV2b2NhdGlvbhgMIAEoDjIsLnNhYXMuYWNjb3VudHMudjEuU291cmNlRGVsZWdhdGlvblJldm9jYXRpb24ivgEKE1RyaWdnZXJDaGlsZENvbnRleHQSFQoNZGVsZWdhdGlvbl9pZBgBIAEoCRIOCgZtb2R1bGUYAiABKAkSDwoHYmluZGluZxgDIAEoCRIQCghhdWRpZW5jZRgEIAEoCRIOCgZzY29wZXMYBSADKAkSDgoGbG9va3VwGAYgASgIEi0KCW1pbnRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGcmVjb3JkGAggASgJIs0CChhTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb24SDwoHcmVsZWFzZRgBIAEoCRIRCglvcGVyYXRpb24YAiABKAkSOwoIc2NoZWR1bGUYAyABKAsyKS5zYWFzLmFjY291bnRzLnYxLkRlY2xhcmVkVHJpZ2dlclNjaGVkdWxlEjMKCGlkZW50aXR5GAQgASgLMiEuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VySWRlbnRpdHkSDgoGZGlnZXN0GAUgASgJEjYKEmxhc3Rfb2NjdXJyZW5jZV9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNgoSbmV4dF9vY2N1cnJlbmNlX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChN1bmRlY2xhcmFibGVfcmVhc29uGAggASgJIlYKHURlbGVnYXRlU291cmNlVHJpZ2dlcnNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABASJjCh5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVzcG9uc2USQQoLZGVsZWdhdGlvbnMYASADKAsyLC5zYWFzLmFjY291bnRzLnYxLlRyaWdnZXJEZWxlZ2F0aW9uUmVmZXJlbmNlIlsKIkdldFNvdXJjZVRyaWdnZXJEZWNsYXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBIuIBCiNHZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZRI/CgtkZWNsYXJhdGlvbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuU291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEkEKC2RlbGVnYXRpb25zGAIgAygLMiwuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRI3CghjaGlsZHJlbhgDIAMoCzIlLnNhYXMuYWNjb3VudHMudjEuVHJpZ2dlckNoaWxkQ29udGV4dCJuChZSZWNvbmNpbGVTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIdCgllZmZlY3RfaWQYAyABKAlCCrpIB3IFEAEYgAEiTAoXUmVjb25jaWxlU291cmNlUmVzcG9uc2USEQoJZWZmZWN0X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIOCgZqb2JfaWQYAyABKAkiPQocTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBIdCgllZmZlY3RfaWQYASABKAlCCrpIB3IFEAEYgAEi8QIKD1NvdXJjZU9wZXJhdGlvbhIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg4KBm1ldGhvZBgDIAEoCRIMCgRwYXRoGAQgASgJEg0KBXF1ZXJ5GAUgAygJEi0KDGlucHV0X3NjaGVtYRgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSLgoNb3V0cHV0X3NjaGVtYRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSOAoGZWZmZWN0GAggASgOMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24uRWZmZWN0EhgKEG1heF9vdXRwdXRfYnl0ZXMYCSABKA0SDgoGZGlnZXN0GAogASgJIksKBkVmZmVjdBIWChJFRkZFQ1RfVU5TUEVDSUZJRUQQABIUChBFRkZFQ1RfUkVBRF9PTkxZEAESEwoPRUZGRUNUX01VVEFUSU9OEAIijgEKHkRlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQESNQoKb3BlcmF0aW9ucxgDIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlgKH0RlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVzcG9uc2USNQoKb3BlcmF0aW9ucxgBIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlQKG0xpc3RTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQEiVQocTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXNwb25zZRI1CgpvcGVyYXRpb25zGAEgAygLMiEuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24irgIKHEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBEjAKCW9wZXJhdGlvbhgDIAEoCUIdukgachgyFl5bYS16XVthLXowLTlfXXswLDYzfSQSHQoKaW5wdXRfanNvbhgEIAEoCUIJukgGcgQogIAEEhsKCWVmZmVjdF9pZBgFIAEoCUIIukgFcgMogAESSQobZXhwZWN0ZWRfZGVjbGFyYXRpb25fZGlnZXN0GAYgASgJQh+6SBxyGjIYXihzaGEyNTY6WzAtOWEtZl17NjR9KT8kSACIAQFCHgocX2V4cGVjdGVkX2RlY2xhcmF0aW9uX2RpZ2VzdCJ/ChZTb3VyY2VPcGVyYXRpb25SZWNlaXB0EhEKCWVmZmVjdF9pZBgBIAEoCRIUCgxjb21taXR0ZWRfYXQYAiABKAkSDgoGc3RhdHVzGAMgASgJEhcKD3Byb3ZpZGVyX3N0YXR1cxgEIAEoDRITCgtvdXRwdXRfanNvbhgFIAEoCSJvCh1JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZRITCgtvdXRwdXRfanNvbhgBIAEoCRI5CgdyZWNlaXB0GAIgASgLMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb25SZWNlaXB0IkMKIkxvb2t1cEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSHQoJZWZmZWN0X2lkGAEgASgJQgq6SAdyBRABKIABInkKI1BydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgllZmZlY3RfaWQYAyABKAlCCLpIBXIDKIABIlsKJFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZRIRCgllZmZlY3RfaWQYASABKAkSEAoIcmVjZWlwdHMYAiABKAMSDgoGc3RhdHVzGAMgASgJIkoKKUxvb2t1cFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0Eh0KCWVmZmVjdF9pZBgBIAEoCUIKukgHcgUQASiAASq3AQoSRGF0YXNvdXJjZVByb3ZpZGVyEiMKH0RBVEFTT1VSQ0VfUFJPVklERVJfVU5TUEVDSUZJRUQQABIeChpEQVRBU09VUkNFX1BST1ZJREVSX0dJVEhVQhABEhsKF0RBVEFTT1VSQ0VfUFJPVklERVJfQVBJEAISHwobREFUQVNPVVJDRV9QUk9WSURFUl9DUkFXTEVSEAMSHgoaREFUQVNPVVJDRV9QUk9WSURFUl9VUExPQUQQBCqRAQoQRGF0YXNvdXJjZVN0YXR1cxIhCh1EQVRBU09VUkNFX1NUQVRVU19VTlNQRUNJRklFRBAAEhwKGERBVEFTT1VSQ0VfU1RBVFVTX0FDVElWRRABEhwKGERBVEFTT1VSQ0VfU1RBVFVTX1BBVVNFRBACEh4KGkRBVEFTT1VSQ0VfU1RBVFVTX0RFR1JBREVEEAMqvAEKFkRhdGFzb3VyY2VMaXZlRGVsaXZlcnkSKAokREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX1VOU1BFQ0lGSUVEEAASIQodREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX05PTkUQARIrCidEQVRBU09VUkNFX0xJVkVfREVMSVZFUllfU09VUkNFX1dFQkhPT0sQAhIoCiREQVRBU09VUkNFX0xJVkVfREVMSVZFUllfQVBQX1dFQkhPT0sQAyrWAQoRQXBpQ3JlZGVudGlhbEtpbmQSIwofQVBJX0NSRURFTlRJQUxfS0lORF9VTlNQRUNJRklFRBAAEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfQkVBUkVSEAESHQoZQVBJX0NSRURFTlRJQUxfS0lORF9CQVNJQxACEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfSEVBREVSEAMSHQoZQVBJX0NSRURFTlRJQUxfS0lORF9RVUVSWRAEEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfT0FVVEgyEAUqpgIKHERhdGFzb3VyY2VDb25uZWN0b3JJbnRlcmZhY2USLgoqREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1VOU1BFQ0lGSUVEEAASKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX0ZJTEVTEAESKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1BBR0VTEAISKgomREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1JFQ09SRFMQAxIrCidEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfTUVTU0FHRVMQBBIpCiVEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfRVZFTlRTEAUq7AEKGERhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRIqCiZEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9VTlNQRUNJRklFRBAAEiMKH0RBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX05PTkUQARImCiJEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9PUkdfQVBQEAISKQolREFUQVNPVVJDRV9DUkVERU5USUFMX01PREVfVVNFUl9PQVVUSBADEiwKKERBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX1NUQVRJQ19TRUNSRVQQBCqXAQoWRGF0YXNvdXJjZVJlYWRlcnNNb2RlbBIoCiREQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfVU5TUEVDSUZJRUQQABIqCiZEQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfU09VUkNFX1NDT1BFRBABEicKI0RBVEFTT1VSQ0VfUkVBREVSU19NT0RFTF9UUkFOU0xBVEVEEAIq7gEKD1NvdXJjZVN5bmNQaGFzZRIhCh1TT1VSQ0VfU1lOQ19QSEFTRV9VTlNQRUNJRklFRBAAEhwKGFNPVVJDRV9TWU5DX1BIQVNFX1FVRVVFRBABEh4KGlNPVVJDRV9TWU5DX1BIQVNFX0ZFVENISU5HEAISHgoaU09VUkNFX1NZTkNfUEhBU0VfQ09NUElMRUQQAxIgChxTT1VSQ0VfU1lOQ19QSEFTRV9IQU5ERURfT0ZGEAQSGgoWU09VUkNFX1NZTkNfUEhBU0VfRE9ORRAFEhwKGFNPVVJDRV9TWU5DX1BIQVNFX0ZBSUxFRBAGKqYDChdTb3VyY2VTeW5jRmFpbHVyZVJlYXNvbhIqCiZTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEisKJ1NPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX1JBVEVfTElNSVRFRBABEikKJVNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX0NSRURFTlRJQUwQAhIsCihTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9BQ0NFU1NfREVOSUVEEAMSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fTk9UX0ZPVU5EEAQSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fVE9PX0xBUkdFEAUSLworU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fSE9TVF9VTkFWQUlMQUJMRRAGEiQKIFNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX09USEVSEAcSLgoqU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fREVMSVZFUllfRkFJTEVEEAgqwgEKEVNvdXJjZVN5bmNUcmlnZ2VyEiMKH1NPVVJDRV9TWU5DX1RSSUdHRVJfVU5TUEVDSUZJRUQQABIeChpTT1VSQ0VfU1lOQ19UUklHR0VSX01BTlVBTBABEiEKHVNPVVJDRV9TWU5DX1RSSUdHRVJfU0NIRURVTEVEEAISHwobU09VUkNFX1NZTkNfVFJJR0dFUl9XRUJIT09LEAMSJAogU09VUkNFX1NZTkNfVFJJR0dFUl9SRUNPTkZJR1VSRUQQBCqPAQoWRGF0YXNvdXJjZURvbWFpblN0YXR1cxIoCiREQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIkCiBEQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfUEVORElORxABEiUKIURBVEFTT1VSQ0VfRE9NQUlOX1NUQVRVU19WRVJJRklFRBACKpUDChpTb3VyY2VEZWxlZ2F0aW9uUmV2b2NhdGlvbhIsCihTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VOU1BFQ0lGSUVEEAASKAokU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVZPS0VEEAESKQolU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVBMQUNFRBACEi8KK1NPVVJDRV9ERUxFR0FUSU9OX1JFVk9DQVRJT05fU09VUkNFX0RFTEVURUQQAxIvCitTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX01FTUJFUl9SRU1PVkVEEAQSMAosU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9QRVJNSVNTSU9OX0xPU1QQBRIuCipTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VTRVJfSU5BQ1RJVkUQBhIwCixTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX0JJTkRJTkdfQ0hBTkdFRBAHMrM7ChFEYXRhc291cmNlU2VydmljZRK5AwocUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI1LnNhYXMuYWNjb3VudHMudjEuUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSKpAsLzGGwIAhADGhFkYXRhc291cmNlOmludm9rZSIRZGF0YXNvdXJjZTppbnZva2UqDwoJc291cmNlX2lkEAQYAzABOiMKH3NhYXMuZGF0YXNvdXJjZS5yZWNlaXB0cy5wcnVuZWQQAkADSARQA1gDYAHa8xi0AQoCCDwSAwjYBBgFIgIIAioLVU5BVkFJTEFCTEUqElJFU09VUkNFX0VYSEFVU1RFRCoHQUJPUlRFRDIPc2Fhcy1kYXRhc291cmNlSkYvc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlU2VydmljZS9Mb29rdXBQcnVuZVNvdXJjZU9wZXJhdGlvblJlY2VpcHRzUIAgWIAgYAFyGAoGc291cmNlEgZpbnZva2USBHJlYWQYARLmAQoiTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI7LnNhYXMuYWNjb3VudHMudjEuTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSJLwvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUANYA2ABEvwDChVJbnZva2VTb3VyY2VPcGVyYXRpb24SLi5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlc3BvbnNlIoEDwvMYbggCEAMaEWRhdGFzb3VyY2U6aW52b2tlIhFkYXRhc291cmNlOmludm9rZSoPCglzb3VyY2VfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEARAA0gEUARYBGAB2vMYrwEKAgg8EgMI2AQYBSICCAIqC1VOQVZBSUxBQkxFKhJSRVNPVVJDRV9FWEhBVVNURUQqB0FCT1JURUQyD3NhYXMtZGF0YXNvdXJjZUo/L3NhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVNlcnZpY2UvTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uUICABFiAgEBgAXIYCgZzb3VyY2USBmludm9rZRIEcmVhZBgBgtPkkwJVOgEqIlAvdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zL3tvcGVyYXRpb259Omludm9rZRKHAgobTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5Mb29rdXBJbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKAAcLzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ADWARgAYLT5JMCLxItL3YxL2RhdGFzb3VyY2Utb3BlcmF0aW9uLXJlY2VpcHRzL3tlZmZlY3RfaWR9Ev8BChxWZXJpZnlTb3VyY2VPcGVyYXRpb25SZWNlaXB0Ei4uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSJ+wvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUARYBGABgtPkkwItOgEqIigvdjEvZGF0YXNvdXJjZS1vcGVyYXRpb24tcmVjZWlwdHMvdmVyaWZ5EoUCChRMaXN0U291cmNlT3BlcmF0aW9ucxItLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0Gi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIo0BwvMYRAgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKgwKBm9yZ19pZBACGAEwAToCEAFAAUgDUANYA2ABgtPkkwI/Ej0vdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zEpMCChdEZWNsYXJlU291cmNlT3BlcmF0aW9ucxIwLnNhYXMuYWNjb3VudHMudjEuRGVjbGFyZVNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0GjEuc2Fhcy5hY2NvdW50cy52MS5EZWNsYXJlU291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIpIBwvMYRggCEAQqDAoGb3JnX2lkEAIYATABOiYKInNhYXMuZGF0YXNvdXJjZS5vcGVyYXRpb24uZGVjbGFyZWQQAkABSARQA1gDYAGC0+STAkI6ASoiPS92MS9vcmdhbml6YXRpb25zL3tvcmdfaWR9L2RhdGFzb3VyY2VzL3tzb3VyY2VfaWR9L29wZXJhdGlvbnMSrAEKD0FkZEdpdEh1YlNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVzcG9uc2UiRMLzGEAIAhAEKgwKBm9yZ19pZBACGAEwATogChxzYWFzLmRhdGFzb3VyY2Uuc291cmNlLmFkZGVkEAJAAUgEUARYA2ABEpoBCglBZGRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlc3BvbnNlIkTC8xhACAIQBCoMCgZvcmdfaWQQAhgBMAE6IAocc2Fhcy5kYXRhc291cmNlLnNvdXJjZS5hZGRlZBACQAFIBFAEWANgARKlAQoMVXBkYXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UudXBkYXRlZBACQAFIBFACWANgARKPAQoUR2V0RGF0YXNvdXJjZUNhdGFsb2cSLS5zYWFzLmFjY291bnRzLnYxLkdldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdBouLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZUNhdGFsb2dSZXNwb25zZSIYwvMYFAgCEAEwAToCEAFAAUgDUAJYAmABEoIBCgtMaXN0U291cmNlcxIkLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZXNSZXF1ZXN0GiUuc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARJ8CglHZXRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKeAQoKU3luY1NvdXJjZRIjLnNhYXMuYWNjb3VudHMudjEuU3luY1NvdXJjZVJlcXVlc3QaJC5zYWFzLmFjY291bnRzLnYxLlN5bmNTb3VyY2VSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5zb3VyY2Uuc3luY2VkEAJAAUgEUARYAmABEogBCg1HZXRTb3VyY2VTeW5jEiYuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VTeW5jUmVxdWVzdBonLnNhYXMuYWNjb3VudHMudjEuR2V0U291cmNlU3luY1Jlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKlAQoMRGVsZXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UucmVtb3ZlZBACQAFIBFACWAJgARLEAQoTQmVnaW5HaXRIdWJBcHBTZXR1cBIsLnNhYXMuYWNjb3VudHMudjEuQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJlZ2luR2l0SHViQXBwU2V0dXBSZXNwb25zZSJQwvMYTAgCEAQqDAoGb3JnX2lkEAIYATABOiwKKHNhYXMuZGF0YXNvdXJjZS5naXRodWJfYXBwLnNldHVwX3N0YXJ0ZWQQAkABSARQAlgEYAESzwEKFkNvbXBsZXRlR2l0SHViQXBwU2V0dXASLy5zYWFzLmFjY291bnRzLnYxLkNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZUdpdEh1YkFwcFNldHVwUmVzcG9uc2UiUsLzGE4IAhAEKgwKBm9yZ19pZBACGAEwATouCipzYWFzLmRhdGFzb3VyY2UuZ2l0aHViX2FwcC5zZXR1cF9jb21wbGV0ZWQQAkABSARQBFgDYAESzQEKGE1pZ3JhdGVHaXRIdWJTb3VyY2VUb0FwcBIxLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBoyLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuY3JlZGVudGlhbC51cGRhdGVkEAJAAUgEUAJYA2ABEtUBChpCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGluaxIzLnNhYXMuYWNjb3VudHMudjEuQmVnaW5EYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjQuc2Fhcy5hY2NvdW50cy52MS5CZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkzC8xhICAIQAyoMCgZvcmdfaWQQAhgBMAE6KAokc2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua19zdGFydGVkEAJAAUgEUAJYBGABEtgBCh1Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGluaxI2LnNhYXMuYWNjb3VudHMudjEuQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0Gjcuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkbC8xhCCAIQAyoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua2VkEAJAAUgEUARYA2ABErUBChxMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzEjUuc2Fhcy5hY2NvdW50cy52MS5MaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBo2LnNhYXMuYWNjb3VudHMudjEuTGlzdE15RGF0YXNvdXJjZUFjY291bnRMaW5rc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARLUAQobRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rEjQuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXNwb25zZSJIwvMYRAgCEAMqDAoGb3JnX2lkEAIYATABOiQKIHNhYXMuZGF0YXNvdXJjZS5hY2NvdW50X3VubGlua2VkEAJAAUgEUAJYA2ABEqMBChZHZXREYXRhc291cmNlRGlyZWN0b3J5Ei8uc2Fhcy5hY2NvdW50cy52MS5HZXREYXRhc291cmNlRGlyZWN0b3J5UmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARK3AQoTQmluZERhdGFzb3VyY2VHcm91cBIsLnNhYXMuYWNjb3VudHMudjEuQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJDwvMYPwgCEAQqDAoGb3JnX2lkEAIYATABOh8KG3NhYXMuZGF0YXNvdXJjZS5ncm91cF9ib3VuZBACQAFIBFACWANgARK/AQoVVW5iaW5kRGF0YXNvdXJjZUdyb3VwEi4uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5ncm91cF91bmJvdW5kEAJAAUgEUAJYA2ABEsABChVDbGFpbURhdGFzb3VyY2VEb21haW4SLi5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkbC8xhCCAIQBCoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmRvbWFpbl9jbGFpbWVkEAJAAUgEUAJYA2ABEsQBChZWZXJpZnlEYXRhc291cmNlRG9tYWluEi8uc2Fhcy5hY2NvdW50cy52MS5WZXJpZnlEYXRhc291cmNlRG9tYWluUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkfC8xhDCAIQBCoMCgZvcmdfaWQQAhgBMAE6Iwofc2Fhcy5kYXRhc291cmNlLmRvbWFpbl92ZXJpZmllZBACQAFIBFACWANgARLDAQoWRGVsZXRlRGF0YXNvdXJjZURvbWFpbhIvLnNhYXMuYWNjb3VudHMudjEuRGVsZXRlRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaMC5zYWFzLmFjY291bnRzLnYxLkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5kb21haW5fcmVtb3ZlZBACQAFIBFACWANgARKgAQoVTGlzdFNvdXJjZURlbGVnYXRpb25zEi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESxwEKFlJldm9rZVNvdXJjZURlbGVnYXRpb24SLy5zYWFzLmFjY291bnRzLnYxLlJldm9rZVNvdXJjZURlbGVnYXRpb25SZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5SZXZva2VTb3VyY2VEZWxlZ2F0aW9uUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuZGVsZWdhdGlvbi5yZXZva2VkEAJAAUgEUAJYA2ABEusBChZEZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzEi8uc2Fhcy5hY2NvdW50cy52MS5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuRGVsZWdhdGVTb3VyY2VUcmlnZ2Vyc1Jlc3BvbnNlIm7C8xhqCAIQBCoMCgZvcmdfaWQQAhgBMAE6Sgoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24uY3JlYXRlZAoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24ucmV2b2tlZBACQAFIBFACWANgARKyAQobR2V0U291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESgwMKD1JlY29uY2lsZVNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UimgLC8xhqCAIQAxoRZGF0YXNvdXJjZTppbnZva2UiEWRhdGFzb3VyY2U6aW52b2tlKg8KCXNvdXJjZV9pZBAEGAMwATohCh1zYWFzLmRhdGFzb3VyY2Uuc291cmNlLnN5bmNlZBACQANIBFACWAJgAdrzGKcBCgIIPBIDCNgEGAUiAggCKgtVTkFWQUlMQUJMRSoSUkVTT1VSQ0VfRVhIQVVTVEVEKgdBQk9SVEVEMg9zYWFzLWRhdGFzb3VyY2VKOS9zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTZXJ2aWNlL0xvb2t1cFJlY29uY2lsZVNvdXJjZVCAIFiAIGABchgKBnNvdXJjZRIGaW52b2tlEgRyZWFkGAESvwEKFUxvb2t1cFJlY29uY2lsZVNvdXJjZRIuLnNhYXMuYWNjb3VudHMudjEuTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UiS8LzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ACWAJgAUK3AQoUY29tLnNhYXMuYWNjb3VudHMudjFCD0RhdGFzb3VyY2VQcm90b1ABWixhY2NvdW50cy9wa2cvZ2VuL3NhYXMvYWNjb3VudHMvdjE7YWNjb3VudHN2MaICA1NBWKoCEFNhYXMuQWNjb3VudHMuVjHKAhBTYWFzXEFjY291bnRzXFYx4gIcU2Fhc1xBY2NvdW50c1xWMVxHUEJNZXRhZGF0YeoCElNhYXM6OkFjY291bnRzOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_codefly_runnable_v0_options, file_google_api_annotations, file_google_protobuf_duration, file_google_protobuf_struct, file_google_protobuf_timestamp, file_saas_jobs_v1_jobs, file_saas_policy_v1_options]); + fileDesc("CiFzYWFzL2FjY291bnRzL3YxL2RhdGFzb3VyY2UucHJvdG8SEHNhYXMuYWNjb3VudHMudjEiXgoWR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIMCgRyZXBvGAEgASgJEg0KBXBhdGhzGAIgAygJEg4KBmJyYW5jaBgDIAEoCRIXCg9maWxlX2V4dGVuc2lvbnMYBCADKAki9AEKD0FwaU9BdXRoMkNvbmZpZxI2CgVncmFudBgEIAEoDjInLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnLkdyYW50EhEKCXRva2VuX3VybBgBIAEoCRIRCgljbGllbnRfaWQYAiABKAkSDgoGc2NvcGVzGAMgAygJInMKBUdyYW50EhUKEUdSQU5UX1VOU1BFQ0lGSUVEEAASFwoTR1JBTlRfUkVGUkVTSF9UT0tFThABEhwKGEdSQU5UX0NMSUVOVF9DUkVERU5USUFMUxACEhwKGEdSQU5UX0FVVEhPUklaQVRJT05fQ09ERRADIuoBChNBcGlEYXRhc291cmNlQ29uZmlnEhAKCGJhc2VfdXJsGAEgASgJEhUKDXJlc291cmNlX3BhdGgYAiABKAkSPAoPY3JlZGVudGlhbF9raW5kGAMgASgOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIZChFjcmVkZW50aWFsX2hlYWRlchgEIAEoCRIeChZjcmVkZW50aWFsX3F1ZXJ5X3BhcmFtGAUgASgJEjEKBm9hdXRoMhgGIAEoCzIhLnNhYXMuYWNjb3VudHMudjEuQXBpT0F1dGgyQ29uZmlnIkEKF0NyYXdsZXJEYXRhc291cmNlQ29uZmlnEhMKC3NpdGVtYXBfdXJsGAEgASgJEhEKCW1heF9wYWdlcxgCIAEoDSKrAgoWVXBsb2FkRGF0YXNvdXJjZUNvbmZpZxIQCghlbmRwb2ludBgBIAEoCRIOCgZyZWdpb24YAiABKAkSDgoGYnVja2V0GAMgASgJEg4KBnByZWZpeBgEIAEoCRIVCg1hY2Nlc3Nfa2V5X2lkGAUgASgJEhMKC21heF9vYmplY3RzGAYgASgNEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACEkkKD2ZpbGVfZXh0ZW5zaW9ucxgJIAMoCUIwukgtkgEqECAiJnIkEAIYITIeXlwuW0EtWmEtejAtOV1bQS1aYS16MC05Ll8tXSokIoMHCgpEYXRhc291cmNlEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRI2Cghwcm92aWRlchgDIAEoDjIkLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyEjgKBmdpdGh1YhgFIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuR2l0SHViRGF0YXNvdXJjZUNvbmZpZxIyCgZzdGF0dXMYBiABKA4yIi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTdGF0dXMSGgoSd2ViaG9va19jb25maWd1cmVkGAcgASgIEi4KCmNyZWF0ZWRfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDmxhc3Rfc3luY2VkX2F0GAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgNhcGkYCyABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWcSOgoHY3Jhd2xlchgMIAEoCzIpLnNhYXMuYWNjb3VudHMudjEuQ3Jhd2xlckRhdGFzb3VyY2VDb25maWcSOAoGdXBsb2FkGA0gASgLMiguc2Fhcy5hY2NvdW50cy52MS5VcGxvYWREYXRhc291cmNlQ29uZmlnEhgKEGJvdW5kYXJ5X25vZGVfaWQYDiABKAkSNAoQbGFzdF9pbmdlc3RlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHAoUbGFzdF9pbmdlc3RlZF9jb21taXQYECABKAkSFQoNc3RhdHVzX3JlYXNvbhgRIAEoCRIWCg5ib3VuZGFyeV9sYWJlbBgSIAEoCRISCgpjb25mb3JtYW50GBMgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgUIAEoCRI/Cg1saXZlX2RlbGl2ZXJ5GBUgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlTGl2ZURlbGl2ZXJ5EjUKEnJlY29uY2lsZV9pbnRlcnZhbBgWIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkoECAQQBVIRdGFyZ2V0X2NvbGxlY3Rpb24isgMKFkFkZEdpdEh1YlNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI7CgRyZXBvGAIgASgJQi26SCpyKBADGP8BMiFeW0EtWmEtejAtOV8uLV0rL1tBLVphLXowLTlfLi1dKyQSIAoFcGF0aHMYAyADKAlCEbpIDpIBCxBAIgdyBRABGIAEEhgKBmJyYW5jaBgEIAEoCUIIukgFcgMY/wESJAoQYm91bmRhcnlfbm9kZV9pZBgIIAEoCUIIukgFcgOwAQFIABImChBjb2xsZWN0aW9uX2xhYmVsGAkgASgJQgq6SAdyBRABGP8BSAASHgoMYWNjZXNzX3Rva2VuGAYgASgJQgi6SAVyAxiACBIgCg53ZWJob29rX3NlY3JldBgHIAEoCUIIukgFcgMYgAgSSQoPZmlsZV9leHRlbnNpb25zGAogAygJQjC6SC2SASoQICImciQQAhghMh5eXC5bQS1aYS16MC05XVtBLVphLXowLTkuXy1dKiRCEQoIYm91bmRhcnkSBbpIAggBSgQIBRAGUhF0YXJnZXRfY29sbGVjdGlvbiJLChdBZGRHaXRIdWJTb3VyY2VSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsgEChBBZGRTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESQgoIcHJvdmlkZXIYAiABKA4yJC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VQcm92aWRlckIKukgHggEEEAEgABI6CgZnaXRodWIYBCABKAsyKC5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkRhdGFzb3VyY2VDb25maWdIABI0CgNhcGkYBSABKAsyJS5zYWFzLmFjY291bnRzLnYxLkFwaURhdGFzb3VyY2VDb25maWdIABI8CgdjcmF3bGVyGAggASgLMikuc2Fhcy5hY2NvdW50cy52MS5DcmF3bGVyRGF0YXNvdXJjZUNvbmZpZ0gAEjoKBnVwbG9hZBgJIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuVXBsb2FkRGF0YXNvdXJjZUNvbmZpZ0gAEiQKEGJvdW5kYXJ5X25vZGVfaWQYDCABKAlCCLpIBXIDsAEBSAESJgoQY29sbGVjdGlvbl9sYWJlbBgNIAEoCUIKukgHcgUQARj/AUgBEhwKCmNyZWRlbnRpYWwYBiABKAlCCLpIBXIDGIAgEiAKDndlYmhvb2tfc2VjcmV0GAcgASgJQgi6SAVyAxiACBImChRvYXV0aDJfY2xpZW50X3NlY3JldBgKIAEoCUIIukgFcgMYgAhCCAoGY29uZmlnQhEKCGJvdW5kYXJ5EgW6SAIIAUoECAMQBFIRdGFyZ2V0X2NvbGxlY3Rpb24iRQoRQWRkU291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSLkAgoTVXBkYXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIYCgZicmFuY2gYAyABKAlCCLpIBXIDGP8BEiAKBXBhdGhzGAQgAygJQhG6SA6SAQsQQCIHcgUQARiABBJJCg9maWxlX2V4dGVuc2lvbnMYBSADKAlCMLpILZIBKhAgIiZyJBACGCEyHl5cLltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJBI8CghleHBlY3RlZBgGIAEoCzIiLnNhYXMuYWNjb3VudHMudjEuU291cmNlRmV0Y2hTY29wZUIGukgDyAEBEisKEGluY2x1ZGVfcGF0dGVybnMYByADKAlCEbpIDpIBCxAQIgdyBRABGIACEisKEGV4Y2x1ZGVfcGF0dGVybnMYCCADKAlCEbpIDpIBCxAQIgdyBRABGIACIs8BChBTb3VyY2VGZXRjaFNjb3BlEhgKBmJyYW5jaBgBIAEoCUIIukgFcgMY/wESIAoFcGF0aHMYAiADKAlCEbpIDpIBCxBAIgdyBRABGIAEEikKD2ZpbGVfZXh0ZW5zaW9ucxgDIAMoCUIQukgNkgEKECAiBnIEEAEYIRIpChBpbmNsdWRlX3BhdHRlcm5zGAQgAygJQg+6SAySAQkQECIFcgMYgAISKQoQZXhjbHVkZV9wYXR0ZXJucxgFIAMoCUIPukgMkgEJEBAiBXIDGIACIlgKFFVwZGF0ZVNvdXJjZVJlc3BvbnNlEjAKCmRhdGFzb3VyY2UYASABKAsyHC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2USDgoGam9iX2lkGAIgASgJIloKFURhdGFzb3VyY2VDb25maWdGaWVsZBILCgNrZXkYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEgwKBGhlbHAYAyABKAkSEAoIcmVxdWlyZWQYBCABKAgixAEKGURhdGFzb3VyY2VDb25uZWN0b3JCdWRnZXQSGgoSbWF4X2l0ZW1zX3Blcl9jYWxsGAEgASgNEhoKEm1heF9ieXRlc19wZXJfY2FsbBgCIAEoAxIWCg5tYXhfaXRlbV9ieXRlcxgDIAEoAxIdChVvcGVyYXRpb25zX3Blcl93aW5kb3cYBCABKA0SFgoOd2luZG93X3NlY29uZHMYBSABKAMSIAoYYmFja2dyb3VuZF9zaGFyZV9wZXJjZW50GAYgASgNIqoGChxEYXRhc291cmNlUHJvdmlkZXJEZXNjcmlwdG9yEjYKCHByb3ZpZGVyGAEgASgOMiQuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUHJvdmlkZXISFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEj4KDWNvbmZpZ19maWVsZHMYBCADKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDb25maWdGaWVsZBIYChBzdXBwb3J0c193ZWJob29rGAUgASgIEkcKGnN1cHBvcnRlZF9jcmVkZW50aWFsX2tpbmRzGAYgAygOMiMuc2Fhcy5hY2NvdW50cy52MS5BcGlDcmVkZW50aWFsS2luZBIRCgljb25uZWN0b3IYByABKAkSQQoJaW50ZXJmYWNlGAggASgOMi4uc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQ29ubmVjdG9ySW50ZXJmYWNlEkQKEGNyZWRlbnRpYWxfbW9kZXMYCSADKA4yKi5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRI/Cg1yZWFkZXJzX21vZGVsGAogASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlUmVhZGVyc01vZGVsEjsKBmJ1ZGdldBgLIAEoCzIrLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUNvbm5lY3RvckJ1ZGdldBISCgpjb25mb3JtYW50GAwgASgIEhcKD2NvbmZvcm1hbmNlX2dhcBgNIAEoCRIbChNhY2NlcHRzX25ld19zb3VyY2VzGA4gASgIEiAKGGxpdmVfZGVsaXZlcnlfY29uZmlndXJlZBgPIAEoCBIaChJhY2NlcHRzX29wZXJhdGlvbnMYECABKAgSFgoOb3BlcmF0aW9uc19nYXAYESABKAkSGwoTb2F1dGhfYXV0aG9yaXplX3VybBgSIAEoCRIXCg9vYXV0aF90b2tlbl91cmwYEyABKAkSFAoMb2F1dGhfc2NvcGVzGBQgAygJIh0KG0dldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdCJhChxHZXREYXRhc291cmNlQ2F0YWxvZ1Jlc3BvbnNlEkEKCXByb3ZpZGVycxgBIAMoCzIuLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVByb3ZpZGVyRGVzY3JpcHRvciIuChJMaXN0U291cmNlc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJIChNMaXN0U291cmNlc1Jlc3BvbnNlEjEKC2RhdGFzb3VyY2VzGAEgAygLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIkIKEEdldFNvdXJjZVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiRQoRR2V0U291cmNlUmVzcG9uc2USMAoKZGF0YXNvdXJjZRgBIAEoCzIcLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZSJ2ChFTeW5jU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABARIeCgxhY2Nlc3NfdG9rZW4YAyABKAlCCLpIBXIDGIAgEhEKCXJlY29ubmVjdBgEIAEoCCIkChJTeW5jU291cmNlUmVzcG9uc2USDgoGam9iX2lkGAEgASgJImoKFEdldFNvdXJjZVN5bmNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgZqb2JfaWQYAyABKAlCC7pICNgBAXIDsAEBIpUBChJTb3VyY2VTeW5jRGVsaXZlcnkSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARItCgVzdGF0ZRgCIAEoDjIWLnNhYXMuam9icy52MS5Kb2JTdGF0ZUIGukgDyAEBEjYKCWV4ZWN1dGlvbhgDIAEoCzIjLnNhYXMuam9icy52MS5Kb2JFeGVjdXRpb25SZWZlcmVuY2UiiwEKEVNvdXJjZVN5bmNDaGFuZ2VzEg0KBWZpbGVzGAEgASgNEg0KBWFkZGVkGAIgASgNEhAKCG1vZGlmaWVkGAMgASgNEg8KB2RlbGV0ZWQYBCABKA0SEwoLc3BsaXRfa25vd24YBSABKAgSEAoIc25hcHNob3QYBiABKAgSDgoGY29tbWl0GAcgASgJIq0BChFTb3VyY2VTeW5jRmFpbHVyZRI5CgZyZWFzb24YASABKA4yKS5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNGYWlsdXJlUmVhc29uEgwKBGNvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCRIQCghyZXRyeWluZxgEIAEoCBIsCghyZXRyeV9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAihAQKElNvdXJjZVN5bmNQcm9ncmVzcxIwCgVwaGFzZRgBIAEoDjIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY1BoYXNlEjQKB3RyaWdnZXIYAiABKA4yIy5zYWFzLmFjY291bnRzLnYxLlNvdXJjZVN5bmNUcmlnZ2VyEi0KCXF1ZXVlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoLZmV0Y2hpbmdfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi8KC2NvbXBpbGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1oYW5kZWRfb2ZmX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIvCgtmaW5pc2hlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNAoHY2hhbmdlcxgIIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0NoYW5nZXMSNAoHZmFpbHVyZRgJIAEoCzIjLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0ZhaWx1cmUSDwoHYXR0ZW1wdBgKIAEoDRIUCgxtYXhfYXR0ZW1wdHMYCyABKA0i0gEKFUdldFNvdXJjZVN5bmNSZXNwb25zZRIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBEi0KBXN0YXRlGAIgASgOMhYuc2Fhcy5qb2JzLnYxLkpvYlN0YXRlQga6SAPIAQESOAoKZGVsaXZlcmllcxgDIAMoCzIkLnNhYXMuYWNjb3VudHMudjEuU291cmNlU3luY0RlbGl2ZXJ5EjYKCHByb2dyZXNzGAQgASgLMiQuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VTeW5jUHJvZ3Jlc3MiRQoTRGVsZXRlU291cmNlUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASIWChREZWxldGVTb3VyY2VSZXNwb25zZSJWChNHaXRIdWJBcHBSZXBvc2l0b3J5EgwKBHJlcG8YASABKAkSFgoOZGVmYXVsdF9icmFuY2gYAiABKAkSGQoRYWxyZWFkeV9jb25uZWN0ZWQYAyABKAgiNgoaQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASJxChtCZWdpbkdpdEh1YkFwcFNldHVwUmVzcG9uc2USEwoLaW5zdGFsbF91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAinAEKHUNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEY/wESLAoPaW5zdGFsbGF0aW9uX2lkGAMgASgJQhO6SBByDhABGCAyCF5bMC05XSskEhgKBGNvZGUYBCABKAlCCrpIB3IFEAEY/wEidgoeQ29tcGxldGVHaXRIdWJBcHBTZXR1cFJlc3BvbnNlEhcKD2luc3RhbGxhdGlvbl9pZBgBIAEoCRI7CgxyZXBvc2l0b3JpZXMYAiADKAsyJS5zYWFzLmFjY291bnRzLnYxLkdpdEh1YkFwcFJlcG9zaXRvcnkiUQofTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhQKAmlkGAIgASgJQgi6SAVyA7ABASJUCiBNaWdyYXRlR2l0SHViU291cmNlVG9BcHBSZXNwb25zZRIwCgpkYXRhc291cmNlGAEgASgLMhwuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlIsQBChVEYXRhc291cmNlQWNjb3VudExpbmsSCgoCaWQYASABKAkSDgoGb3JnX2lkGAIgASgJEg8KB3VzZXJfaWQYAyABKAkSEQoJY29ubmVjdG9yGAQgASgJEhsKE3Byb3ZpZGVyX2FjY291bnRfaWQYBSABKAkSHgoWcHJvdmlkZXJfYWNjb3VudF9sb2dpbhgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK3AQoWRGF0YXNvdXJjZUdyb3VwQmluZGluZxIKCgJpZBgBIAEoCRIOCgZvcmdfaWQYAiABKAkSEQoJY29ubmVjdG9yGAMgASgJEhkKEXByb3ZpZGVyX2dyb3VwX2lkGAQgASgJEg8KB3RlYW1faWQYBSABKAkSEgoKY3JlYXRlZF9ieRgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKUAgoYRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEgoKAmlkGAEgASgJEg4KBm9yZ19pZBgCIAEoCRIOCgZkb21haW4YAyABKAkSOAoGc3RhdHVzGAQgASgOMiguc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRG9tYWluU3RhdHVzEhcKD3R4dF9yZWNvcmRfbmFtZRgFIAEoCRIYChB0eHRfcmVjb3JkX3ZhbHVlGAYgASgJEi8KC3ZlcmlmaWVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjcmVhdGVkX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIzChdEYXRhc291cmNlRGlyZWN0b3J5VGVhbRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJIqYBCiFCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIeCgxyZWRpcmVjdF91cmkYAyABKAlCCLpIBXIDGIAQEhEKCXNvdXJjZV9pZBgEIAEoCSJ6CiJCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEhUKDWF1dGhvcml6ZV91cmwYASABKAkSDQoFc3RhdGUYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAidQokQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGQoFc3RhdGUYAiABKAlCCrpIB3IFEAEYgEASGAoEY29kZRgDIAEoCUIKukgHcgUQARj/ASJeCiVDb21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlEjUKBGxpbmsYASABKAsyJy5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VBY2NvdW50TGluayI/CiNMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBIl4KJExpc3RNeURhdGFzb3VyY2VBY2NvdW50TGlua3NSZXNwb25zZRI2CgVsaW5rcxgBIAMoCzInLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUFjY291bnRMaW5rIlQKIkRlbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiJQojRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rUmVzcG9uc2UiOQodR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABASKLAgoeR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlEjYKBWxpbmtzGAEgAygLMicuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlQWNjb3VudExpbmsSOgoIYmluZGluZ3MYAiADKAsyKC5zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VHcm91cEJpbmRpbmcSOwoHZG9tYWlucxgDIAMoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluEjgKBXRlYW1zGAQgAygLMikuc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlRGlyZWN0b3J5VGVhbSKuAQoaQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARI0Cgljb25uZWN0b3IYAiABKAlCIbpIHnIcEAIYIDIWXlthLXpdW2EtejAtOS1dezEsMzF9JBIlChFwcm92aWRlcl9ncm91cF9pZBgDIAEoCUIKukgHcgUQARj/ARIZCgd0ZWFtX2lkGAQgASgJQgi6SAVyA7ABASJYChtCaW5kRGF0YXNvdXJjZUdyb3VwUmVzcG9uc2USOQoHYmluZGluZxgBIAEoCzIoLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZUdyb3VwQmluZGluZyJOChxVbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIh8KHVVuYmluZERhdGFzb3VyY2VHcm91cFJlc3BvbnNlIlQKHENsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIaCgZkb21haW4YAiABKAlCCrpIB3IFEAMY/QEiWwodQ2xhaW1EYXRhc291cmNlRG9tYWluUmVzcG9uc2USOgoGZG9tYWluGAEgASgLMiouc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlVmVyaWZpZWREb21haW4iTwodVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiXAoeVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlEjoKBmRvbWFpbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVZlcmlmaWVkRG9tYWluIk8KHURlbGV0ZURhdGFzb3VyY2VEb21haW5SZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESFAoCaWQYAiABKAlCCLpIBXIDsAEBIiAKHkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSKeAgoQU291cmNlRGVsZWdhdGlvbhIKCgJpZBgBIAEoCRIRCglzb3VyY2VfaWQYAiABKAkSFAoMcHJpbmNpcGFsX2lkGAMgASgJEg4KBm1vZHVsZRgEIAEoCRIPCgdiaW5kaW5nGAUgASgJEi4KCmNyZWF0ZWRfYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnJldm9rZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEkAKCnJldm9jYXRpb24YCCABKA4yLC5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb25SZXZvY2F0aW9uEhIKCnJldm9rZWRfYnkYCSABKAkigQEKHExpc3RTb3VyY2VEZWxlZ2F0aW9uc1JlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIgCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBSACIAQESFwoPaW5jbHVkZV9yZXZva2VkGAMgASgIQgwKCl9zb3VyY2VfaWQiWAodTGlzdFNvdXJjZURlbGVnYXRpb25zUmVzcG9uc2USNwoLZGVsZWdhdGlvbnMYASADKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iTwodUmV2b2tlU291cmNlRGVsZWdhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIUCgJpZBgCIAEoCUIIukgFcgOwAQEiWAoeUmV2b2tlU291cmNlRGVsZWdhdGlvblJlc3BvbnNlEjYKCmRlbGVnYXRpb24YASABKAsyIi5zYWFzLmFjY291bnRzLnYxLlNvdXJjZURlbGVnYXRpb24iMgoPVHJpZ2dlcklkZW50aXR5Eg4KBnNvdXJjZRgBIAEoCRIPCgdiaW5kaW5nGAIgASgJIoQBChdEZWNsYXJlZFRyaWdnZXJTY2hlZHVsZRIMCgRjcm9uGAEgASgJEhAKCHRpbWV6b25lGAIgASgJEhIKCm1pc3NlZF9ydW4YAyABKAkSDwoHb3ZlcmxhcBgEIAEoCRIQCghkZWFkbGluZRgFIAEoAxISCgppbnB1dF9qc29uGAYgASgJIucCChpUcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRIRCglyZWZlcmVuY2UYASABKAkSFQoNZGVsZWdhdGlvbl9pZBgCIAEoCRIOCgZtb2R1bGUYAyABKAkSDwoHYmluZGluZxgEIAEoCRIQCghhdWRpZW5jZRgFIAEoCRIOCgZ0ZW5hbnQYBiABKAkSGgoSb3duZXJfcHJpbmNpcGFsX2lkGAcgASgJEg4KBnNjb3BlcxgIIAMoCRIOCgZhY3RpdmUYCSABKAgSLgoKY3JlYXRlZF9hdBgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKcmV2b2tlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASQAoKcmV2b2NhdGlvbhgMIAEoDjIsLnNhYXMuYWNjb3VudHMudjEuU291cmNlRGVsZWdhdGlvblJldm9jYXRpb24ivgEKE1RyaWdnZXJDaGlsZENvbnRleHQSFQoNZGVsZWdhdGlvbl9pZBgBIAEoCRIOCgZtb2R1bGUYAiABKAkSDwoHYmluZGluZxgDIAEoCRIQCghhdWRpZW5jZRgEIAEoCRIOCgZzY29wZXMYBSADKAkSDgoGbG9va3VwGAYgASgIEi0KCW1pbnRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGcmVjb3JkGAggASgJIs0CChhTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb24SDwoHcmVsZWFzZRgBIAEoCRIRCglvcGVyYXRpb24YAiABKAkSOwoIc2NoZWR1bGUYAyABKAsyKS5zYWFzLmFjY291bnRzLnYxLkRlY2xhcmVkVHJpZ2dlclNjaGVkdWxlEjMKCGlkZW50aXR5GAQgASgLMiEuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VySWRlbnRpdHkSDgoGZGlnZXN0GAUgASgJEjYKEmxhc3Rfb2NjdXJyZW5jZV9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNgoSbmV4dF9vY2N1cnJlbmNlX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChN1bmRlY2xhcmFibGVfcmVhc29uGAggASgJIlYKHURlbGVnYXRlU291cmNlVHJpZ2dlcnNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABASJjCh5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVzcG9uc2USQQoLZGVsZWdhdGlvbnMYASADKAsyLC5zYWFzLmFjY291bnRzLnYxLlRyaWdnZXJEZWxlZ2F0aW9uUmVmZXJlbmNlIlsKIkdldFNvdXJjZVRyaWdnZXJEZWNsYXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBIuIBCiNHZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZRI/CgtkZWNsYXJhdGlvbhgBIAEoCzIqLnNhYXMuYWNjb3VudHMudjEuU291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEkEKC2RlbGVnYXRpb25zGAIgAygLMiwuc2Fhcy5hY2NvdW50cy52MS5UcmlnZ2VyRGVsZWdhdGlvblJlZmVyZW5jZRI3CghjaGlsZHJlbhgDIAMoCzIlLnNhYXMuYWNjb3VudHMudjEuVHJpZ2dlckNoaWxkQ29udGV4dCJuChZSZWNvbmNpbGVTb3VyY2VSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIdCgllZmZlY3RfaWQYAyABKAlCCrpIB3IFEAEYgAEiTAoXUmVjb25jaWxlU291cmNlUmVzcG9uc2USEQoJZWZmZWN0X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIOCgZqb2JfaWQYAyABKAkiPQocTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBIdCgllZmZlY3RfaWQYASABKAlCCrpIB3IFEAEYgAEi8QIKD1NvdXJjZU9wZXJhdGlvbhIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg4KBm1ldGhvZBgDIAEoCRIMCgRwYXRoGAQgASgJEg0KBXF1ZXJ5GAUgAygJEi0KDGlucHV0X3NjaGVtYRgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSLgoNb3V0cHV0X3NjaGVtYRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSOAoGZWZmZWN0GAggASgOMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24uRWZmZWN0EhgKEG1heF9vdXRwdXRfYnl0ZXMYCSABKA0SDgoGZGlnZXN0GAogASgJIksKBkVmZmVjdBIWChJFRkZFQ1RfVU5TUEVDSUZJRUQQABIUChBFRkZFQ1RfUkVBRF9PTkxZEAESEwoPRUZGRUNUX01VVEFUSU9OEAIijgEKHkRlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQESNQoKb3BlcmF0aW9ucxgDIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlgKH0RlY2xhcmVTb3VyY2VPcGVyYXRpb25zUmVzcG9uc2USNQoKb3BlcmF0aW9ucxgBIAMoCzIhLnNhYXMuYWNjb3VudHMudjEuU291cmNlT3BlcmF0aW9uIlQKG0xpc3RTb3VyY2VPcGVyYXRpb25zUmVxdWVzdBIYCgZvcmdfaWQYASABKAlCCLpIBXIDsAEBEhsKCXNvdXJjZV9pZBgCIAEoCUIIukgFcgOwAQEiVQocTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXNwb25zZRI1CgpvcGVyYXRpb25zGAEgAygLMiEuc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb24irgIKHEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSGAoGb3JnX2lkGAEgASgJQgi6SAVyA7ABARIbCglzb3VyY2VfaWQYAiABKAlCCLpIBXIDsAEBEjAKCW9wZXJhdGlvbhgDIAEoCUIdukgachgyFl5bYS16XVthLXowLTlfXXswLDYzfSQSHQoKaW5wdXRfanNvbhgEIAEoCUIJukgGcgQogIAEEhsKCWVmZmVjdF9pZBgFIAEoCUIIukgFcgMogAESSQobZXhwZWN0ZWRfZGVjbGFyYXRpb25fZGlnZXN0GAYgASgJQh+6SBxyGjIYXihzaGEyNTY6WzAtOWEtZl17NjR9KT8kSACIAQFCHgocX2V4cGVjdGVkX2RlY2xhcmF0aW9uX2RpZ2VzdCJ/ChZTb3VyY2VPcGVyYXRpb25SZWNlaXB0EhEKCWVmZmVjdF9pZBgBIAEoCRIUCgxjb21taXR0ZWRfYXQYAiABKAkSDgoGc3RhdHVzGAMgASgJEhcKD3Byb3ZpZGVyX3N0YXR1cxgEIAEoDRITCgtvdXRwdXRfanNvbhgFIAEoCSJvCh1JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZRITCgtvdXRwdXRfanNvbhgBIAEoCRI5CgdyZWNlaXB0GAIgASgLMiguc2Fhcy5hY2NvdW50cy52MS5Tb3VyY2VPcGVyYXRpb25SZWNlaXB0IkMKIkxvb2t1cEludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QSHQoJZWZmZWN0X2lkGAEgASgJQgq6SAdyBRABKIABInkKI1BydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0EhgKBm9yZ19pZBgBIAEoCUIIukgFcgOwAQESGwoJc291cmNlX2lkGAIgASgJQgi6SAVyA7ABARIbCgllZmZlY3RfaWQYAyABKAlCCLpIBXIDKIABIlsKJFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZRIRCgllZmZlY3RfaWQYASABKAkSEAoIcmVjZWlwdHMYAiABKAMSDgoGc3RhdHVzGAMgASgJIkoKKUxvb2t1cFBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXF1ZXN0Eh0KCWVmZmVjdF9pZBgBIAEoCUIKukgHcgUQASiAASq3AQoSRGF0YXNvdXJjZVByb3ZpZGVyEiMKH0RBVEFTT1VSQ0VfUFJPVklERVJfVU5TUEVDSUZJRUQQABIeChpEQVRBU09VUkNFX1BST1ZJREVSX0dJVEhVQhABEhsKF0RBVEFTT1VSQ0VfUFJPVklERVJfQVBJEAISHwobREFUQVNPVVJDRV9QUk9WSURFUl9DUkFXTEVSEAMSHgoaREFUQVNPVVJDRV9QUk9WSURFUl9VUExPQUQQBCqRAQoQRGF0YXNvdXJjZVN0YXR1cxIhCh1EQVRBU09VUkNFX1NUQVRVU19VTlNQRUNJRklFRBAAEhwKGERBVEFTT1VSQ0VfU1RBVFVTX0FDVElWRRABEhwKGERBVEFTT1VSQ0VfU1RBVFVTX1BBVVNFRBACEh4KGkRBVEFTT1VSQ0VfU1RBVFVTX0RFR1JBREVEEAMqvAEKFkRhdGFzb3VyY2VMaXZlRGVsaXZlcnkSKAokREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX1VOU1BFQ0lGSUVEEAASIQodREFUQVNPVVJDRV9MSVZFX0RFTElWRVJZX05PTkUQARIrCidEQVRBU09VUkNFX0xJVkVfREVMSVZFUllfU09VUkNFX1dFQkhPT0sQAhIoCiREQVRBU09VUkNFX0xJVkVfREVMSVZFUllfQVBQX1dFQkhPT0sQAyrWAQoRQXBpQ3JlZGVudGlhbEtpbmQSIwofQVBJX0NSRURFTlRJQUxfS0lORF9VTlNQRUNJRklFRBAAEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfQkVBUkVSEAESHQoZQVBJX0NSRURFTlRJQUxfS0lORF9CQVNJQxACEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfSEVBREVSEAMSHQoZQVBJX0NSRURFTlRJQUxfS0lORF9RVUVSWRAEEh4KGkFQSV9DUkVERU5USUFMX0tJTkRfT0FVVEgyEAUqpgIKHERhdGFzb3VyY2VDb25uZWN0b3JJbnRlcmZhY2USLgoqREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1VOU1BFQ0lGSUVEEAASKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX0ZJTEVTEAESKAokREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1BBR0VTEAISKgomREFUQVNPVVJDRV9DT05ORUNUT1JfSU5URVJGQUNFX1JFQ09SRFMQAxIrCidEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfTUVTU0FHRVMQBBIpCiVEQVRBU09VUkNFX0NPTk5FQ1RPUl9JTlRFUkZBQ0VfRVZFTlRTEAUq7AEKGERhdGFzb3VyY2VDcmVkZW50aWFsTW9kZRIqCiZEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9VTlNQRUNJRklFRBAAEiMKH0RBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX05PTkUQARImCiJEQVRBU09VUkNFX0NSRURFTlRJQUxfTU9ERV9PUkdfQVBQEAISKQolREFUQVNPVVJDRV9DUkVERU5USUFMX01PREVfVVNFUl9PQVVUSBADEiwKKERBVEFTT1VSQ0VfQ1JFREVOVElBTF9NT0RFX1NUQVRJQ19TRUNSRVQQBCqXAQoWRGF0YXNvdXJjZVJlYWRlcnNNb2RlbBIoCiREQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfVU5TUEVDSUZJRUQQABIqCiZEQVRBU09VUkNFX1JFQURFUlNfTU9ERUxfU09VUkNFX1NDT1BFRBABEicKI0RBVEFTT1VSQ0VfUkVBREVSU19NT0RFTF9UUkFOU0xBVEVEEAIq7gEKD1NvdXJjZVN5bmNQaGFzZRIhCh1TT1VSQ0VfU1lOQ19QSEFTRV9VTlNQRUNJRklFRBAAEhwKGFNPVVJDRV9TWU5DX1BIQVNFX1FVRVVFRBABEh4KGlNPVVJDRV9TWU5DX1BIQVNFX0ZFVENISU5HEAISHgoaU09VUkNFX1NZTkNfUEhBU0VfQ09NUElMRUQQAxIgChxTT1VSQ0VfU1lOQ19QSEFTRV9IQU5ERURfT0ZGEAQSGgoWU09VUkNFX1NZTkNfUEhBU0VfRE9ORRAFEhwKGFNPVVJDRV9TWU5DX1BIQVNFX0ZBSUxFRBAGKqYDChdTb3VyY2VTeW5jRmFpbHVyZVJlYXNvbhIqCiZTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEisKJ1NPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX1JBVEVfTElNSVRFRBABEikKJVNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX0NSRURFTlRJQUwQAhIsCihTT1VSQ0VfU1lOQ19GQUlMVVJFX1JFQVNPTl9BQ0NFU1NfREVOSUVEEAMSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fTk9UX0ZPVU5EEAQSKAokU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fVE9PX0xBUkdFEAUSLworU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fSE9TVF9VTkFWQUlMQUJMRRAGEiQKIFNPVVJDRV9TWU5DX0ZBSUxVUkVfUkVBU09OX09USEVSEAcSLgoqU09VUkNFX1NZTkNfRkFJTFVSRV9SRUFTT05fREVMSVZFUllfRkFJTEVEEAgqwgEKEVNvdXJjZVN5bmNUcmlnZ2VyEiMKH1NPVVJDRV9TWU5DX1RSSUdHRVJfVU5TUEVDSUZJRUQQABIeChpTT1VSQ0VfU1lOQ19UUklHR0VSX01BTlVBTBABEiEKHVNPVVJDRV9TWU5DX1RSSUdHRVJfU0NIRURVTEVEEAISHwobU09VUkNFX1NZTkNfVFJJR0dFUl9XRUJIT09LEAMSJAogU09VUkNFX1NZTkNfVFJJR0dFUl9SRUNPTkZJR1VSRUQQBCqPAQoWRGF0YXNvdXJjZURvbWFpblN0YXR1cxIoCiREQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIkCiBEQVRBU09VUkNFX0RPTUFJTl9TVEFUVVNfUEVORElORxABEiUKIURBVEFTT1VSQ0VfRE9NQUlOX1NUQVRVU19WRVJJRklFRBACKpUDChpTb3VyY2VEZWxlZ2F0aW9uUmV2b2NhdGlvbhIsCihTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VOU1BFQ0lGSUVEEAASKAokU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVZPS0VEEAESKQolU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9SRVBMQUNFRBACEi8KK1NPVVJDRV9ERUxFR0FUSU9OX1JFVk9DQVRJT05fU09VUkNFX0RFTEVURUQQAxIvCitTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX01FTUJFUl9SRU1PVkVEEAQSMAosU09VUkNFX0RFTEVHQVRJT05fUkVWT0NBVElPTl9QRVJNSVNTSU9OX0xPU1QQBRIuCipTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX1VTRVJfSU5BQ1RJVkUQBhIwCixTT1VSQ0VfREVMRUdBVElPTl9SRVZPQ0FUSU9OX0JJTkRJTkdfQ0hBTkdFRBAHMtc7ChFEYXRhc291cmNlU2VydmljZRK5AwocUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI1LnNhYXMuYWNjb3VudHMudjEuUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSKpAsLzGGwIAhADGhFkYXRhc291cmNlOmludm9rZSIRZGF0YXNvdXJjZTppbnZva2UqDwoJc291cmNlX2lkEAQYAzABOiMKH3NhYXMuZGF0YXNvdXJjZS5yZWNlaXB0cy5wcnVuZWQQAkADSARQA1gDYAHa8xi0AQoCCDwSAwjYBBgFIgIIAioLVU5BVkFJTEFCTEUqElJFU09VUkNFX0VYSEFVU1RFRCoHQUJPUlRFRDIPc2Fhcy1kYXRhc291cmNlSkYvc2Fhcy5hY2NvdW50cy52MS5EYXRhc291cmNlU2VydmljZS9Mb29rdXBQcnVuZVNvdXJjZU9wZXJhdGlvblJlY2VpcHRzUIAgWIAgYAFyGAoGc291cmNlEgZpbnZva2USBHJlYWQYARLmAQoiTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0cxI7LnNhYXMuYWNjb3VudHMudjEuTG9va3VwUHJ1bmVTb3VyY2VPcGVyYXRpb25SZWNlaXB0c1JlcXVlc3QaNi5zYWFzLmFjY291bnRzLnYxLlBydW5lU291cmNlT3BlcmF0aW9uUmVjZWlwdHNSZXNwb25zZSJLwvMYRwgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKg8KCWVmZmVjdF9pZBAEGAMwAToCEAFAAUgDUANYA2ABEvwDChVJbnZva2VTb3VyY2VPcGVyYXRpb24SLi5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkludm9rZVNvdXJjZU9wZXJhdGlvblJlc3BvbnNlIoEDwvMYbggCEAMaEWRhdGFzb3VyY2U6aW52b2tlIhFkYXRhc291cmNlOmludm9rZSoPCglzb3VyY2VfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEARAA0gEUARYBGAB2vMYrwEKAgg8EgMI2AQYBSICCAIqC1VOQVZBSUxBQkxFKhJSRVNPVVJDRV9FWEhBVVNURUQqB0FCT1JURUQyD3NhYXMtZGF0YXNvdXJjZUo/L3NhYXMuYWNjb3VudHMudjEuRGF0YXNvdXJjZVNlcnZpY2UvTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uUICABFiAgEBgAXIYCgZzb3VyY2USBmludm9rZRIEcmVhZBgBgtPkkwJVOgEqIlAvdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zL3tvcGVyYXRpb259Omludm9rZRKHAgobTG9va3VwSW52b2tlU291cmNlT3BlcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5Mb29rdXBJbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKAAcLzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ADWARgAYLT5JMCLxItL3YxL2RhdGFzb3VyY2Utb3BlcmF0aW9uLXJlY2VpcHRzL3tlZmZlY3RfaWR9EqMCChxWZXJpZnlTb3VyY2VPcGVyYXRpb25SZWNlaXB0Ei4uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5JbnZva2VTb3VyY2VPcGVyYXRpb25SZXNwb25zZSKhAcLzGGoIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6JQohc2Fhcy5kYXRhc291cmNlLm9wZXJhdGlvbi5pbnZva2VkEANAAUgDUARYBGABgtPkkwItOgEqIigvdjEvZGF0YXNvdXJjZS1vcGVyYXRpb24tcmVjZWlwdHMvdmVyaWZ5EoUCChRMaXN0U291cmNlT3BlcmF0aW9ucxItLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0Gi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIo0BwvMYRAgCEAMaD2RhdGFzb3VyY2U6cmVhZCIPZGF0YXNvdXJjZTpyZWFkKgwKBm9yZ19pZBACGAEwAToCEAFAAUgDUANYA2ABgtPkkwI/Ej0vdjEvb3JnYW5pemF0aW9ucy97b3JnX2lkfS9kYXRhc291cmNlcy97c291cmNlX2lkfS9vcGVyYXRpb25zEpMCChdEZWNsYXJlU291cmNlT3BlcmF0aW9ucxIwLnNhYXMuYWNjb3VudHMudjEuRGVjbGFyZVNvdXJjZU9wZXJhdGlvbnNSZXF1ZXN0GjEuc2Fhcy5hY2NvdW50cy52MS5EZWNsYXJlU291cmNlT3BlcmF0aW9uc1Jlc3BvbnNlIpIBwvMYRggCEAQqDAoGb3JnX2lkEAIYATABOiYKInNhYXMuZGF0YXNvdXJjZS5vcGVyYXRpb24uZGVjbGFyZWQQAkABSARQA1gDYAGC0+STAkI6ASoiPS92MS9vcmdhbml6YXRpb25zL3tvcmdfaWR9L2RhdGFzb3VyY2VzL3tzb3VyY2VfaWR9L29wZXJhdGlvbnMSrAEKD0FkZEdpdEh1YlNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuQWRkR2l0SHViU291cmNlUmVzcG9uc2UiRMLzGEAIAhAEKgwKBm9yZ19pZBACGAEwATogChxzYWFzLmRhdGFzb3VyY2Uuc291cmNlLmFkZGVkEAJAAUgEUARYA2ABEpoBCglBZGRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkFkZFNvdXJjZVJlc3BvbnNlIkTC8xhACAIQBCoMCgZvcmdfaWQQAhgBMAE6IAocc2Fhcy5kYXRhc291cmNlLnNvdXJjZS5hZGRlZBACQAFIBFAEWANgARKlAQoMVXBkYXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5VcGRhdGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UudXBkYXRlZBACQAFIBFACWANgARKPAQoUR2V0RGF0YXNvdXJjZUNhdGFsb2cSLS5zYWFzLmFjY291bnRzLnYxLkdldERhdGFzb3VyY2VDYXRhbG9nUmVxdWVzdBouLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZUNhdGFsb2dSZXNwb25zZSIYwvMYFAgCEAEwAToCEAFAAUgDUAJYAmABEoIBCgtMaXN0U291cmNlcxIkLnNhYXMuYWNjb3VudHMudjEuTGlzdFNvdXJjZXNSZXF1ZXN0GiUuc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARJ8CglHZXRTb3VyY2USIi5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlcXVlc3QaIy5zYWFzLmFjY291bnRzLnYxLkdldFNvdXJjZVJlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKeAQoKU3luY1NvdXJjZRIjLnNhYXMuYWNjb3VudHMudjEuU3luY1NvdXJjZVJlcXVlc3QaJC5zYWFzLmFjY291bnRzLnYxLlN5bmNTb3VyY2VSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5zb3VyY2Uuc3luY2VkEAJAAUgEUARYAmABEogBCg1HZXRTb3VyY2VTeW5jEiYuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VTeW5jUmVxdWVzdBonLnNhYXMuYWNjb3VudHMudjEuR2V0U291cmNlU3luY1Jlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARKlAQoMRGVsZXRlU291cmNlEiUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXF1ZXN0GiYuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVTb3VyY2VSZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5zb3VyY2UucmVtb3ZlZBACQAFIBFACWAJgARLEAQoTQmVnaW5HaXRIdWJBcHBTZXR1cBIsLnNhYXMuYWNjb3VudHMudjEuQmVnaW5HaXRIdWJBcHBTZXR1cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJlZ2luR2l0SHViQXBwU2V0dXBSZXNwb25zZSJQwvMYTAgCEAQqDAoGb3JnX2lkEAIYATABOiwKKHNhYXMuZGF0YXNvdXJjZS5naXRodWJfYXBwLnNldHVwX3N0YXJ0ZWQQAkABSARQAlgEYAESzwEKFkNvbXBsZXRlR2l0SHViQXBwU2V0dXASLy5zYWFzLmFjY291bnRzLnYxLkNvbXBsZXRlR2l0SHViQXBwU2V0dXBSZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZUdpdEh1YkFwcFNldHVwUmVzcG9uc2UiUsLzGE4IAhAEKgwKBm9yZ19pZBACGAEwATouCipzYWFzLmRhdGFzb3VyY2UuZ2l0aHViX2FwcC5zZXR1cF9jb21wbGV0ZWQQAkABSARQBFgDYAESzQEKGE1pZ3JhdGVHaXRIdWJTb3VyY2VUb0FwcBIxLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVxdWVzdBoyLnNhYXMuYWNjb3VudHMudjEuTWlncmF0ZUdpdEh1YlNvdXJjZVRvQXBwUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuY3JlZGVudGlhbC51cGRhdGVkEAJAAUgEUAJYA2ABEtUBChpCZWdpbkRhdGFzb3VyY2VBY2NvdW50TGluaxIzLnNhYXMuYWNjb3VudHMudjEuQmVnaW5EYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjQuc2Fhcy5hY2NvdW50cy52MS5CZWdpbkRhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkzC8xhICAIQAyoMCgZvcmdfaWQQAhgBMAE6KAokc2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua19zdGFydGVkEAJAAUgEUAJYBGABEtgBCh1Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGluaxI2LnNhYXMuYWNjb3VudHMudjEuQ29tcGxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0Gjcuc2Fhcy5hY2NvdW50cy52MS5Db21wbGV0ZURhdGFzb3VyY2VBY2NvdW50TGlua1Jlc3BvbnNlIkbC8xhCCAIQAyoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmFjY291bnRfbGlua2VkEAJAAUgEUARYA2ABErUBChxMaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzEjUuc2Fhcy5hY2NvdW50cy52MS5MaXN0TXlEYXRhc291cmNlQWNjb3VudExpbmtzUmVxdWVzdBo2LnNhYXMuYWNjb3VudHMudjEuTGlzdE15RGF0YXNvdXJjZUFjY291bnRMaW5rc1Jlc3BvbnNlIibC8xgiCAIQAyoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARLUAQobRGVsZXRlRGF0YXNvdXJjZUFjY291bnRMaW5rEjQuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5EZWxldGVEYXRhc291cmNlQWNjb3VudExpbmtSZXNwb25zZSJIwvMYRAgCEAMqDAoGb3JnX2lkEAIYATABOiQKIHNhYXMuZGF0YXNvdXJjZS5hY2NvdW50X3VubGlua2VkEAJAAUgEUAJYA2ABEqMBChZHZXREYXRhc291cmNlRGlyZWN0b3J5Ei8uc2Fhcy5hY2NvdW50cy52MS5HZXREYXRhc291cmNlRGlyZWN0b3J5UmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuR2V0RGF0YXNvdXJjZURpcmVjdG9yeVJlc3BvbnNlIibC8xgiCAIQBCoMCgZvcmdfaWQQAhgBMAE6AhABQAFIA1ACWANgARK3AQoTQmluZERhdGFzb3VyY2VHcm91cBIsLnNhYXMuYWNjb3VudHMudjEuQmluZERhdGFzb3VyY2VHcm91cFJlcXVlc3QaLS5zYWFzLmFjY291bnRzLnYxLkJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJDwvMYPwgCEAQqDAoGb3JnX2lkEAIYATABOh8KG3NhYXMuZGF0YXNvdXJjZS5ncm91cF9ib3VuZBACQAFIBFACWANgARK/AQoVVW5iaW5kRGF0YXNvdXJjZUdyb3VwEi4uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5VbmJpbmREYXRhc291cmNlR3JvdXBSZXNwb25zZSJFwvMYQQgCEAQqDAoGb3JnX2lkEAIYATABOiEKHXNhYXMuZGF0YXNvdXJjZS5ncm91cF91bmJvdW5kEAJAAUgEUAJYA2ABEsABChVDbGFpbURhdGFzb3VyY2VEb21haW4SLi5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaLy5zYWFzLmFjY291bnRzLnYxLkNsYWltRGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkbC8xhCCAIQBCoMCgZvcmdfaWQQAhgBMAE6Igoec2Fhcy5kYXRhc291cmNlLmRvbWFpbl9jbGFpbWVkEAJAAUgEUAJYA2ABEsQBChZWZXJpZnlEYXRhc291cmNlRG9tYWluEi8uc2Fhcy5hY2NvdW50cy52MS5WZXJpZnlEYXRhc291cmNlRG9tYWluUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuVmVyaWZ5RGF0YXNvdXJjZURvbWFpblJlc3BvbnNlIkfC8xhDCAIQBCoMCgZvcmdfaWQQAhgBMAE6Iwofc2Fhcy5kYXRhc291cmNlLmRvbWFpbl92ZXJpZmllZBACQAFIBFACWANgARLDAQoWRGVsZXRlRGF0YXNvdXJjZURvbWFpbhIvLnNhYXMuYWNjb3VudHMudjEuRGVsZXRlRGF0YXNvdXJjZURvbWFpblJlcXVlc3QaMC5zYWFzLmFjY291bnRzLnYxLkRlbGV0ZURhdGFzb3VyY2VEb21haW5SZXNwb25zZSJGwvMYQggCEAQqDAoGb3JnX2lkEAIYATABOiIKHnNhYXMuZGF0YXNvdXJjZS5kb21haW5fcmVtb3ZlZBACQAFIBFACWANgARKgAQoVTGlzdFNvdXJjZURlbGVnYXRpb25zEi4uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXF1ZXN0Gi8uc2Fhcy5hY2NvdW50cy52MS5MaXN0U291cmNlRGVsZWdhdGlvbnNSZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESxwEKFlJldm9rZVNvdXJjZURlbGVnYXRpb24SLy5zYWFzLmFjY291bnRzLnYxLlJldm9rZVNvdXJjZURlbGVnYXRpb25SZXF1ZXN0GjAuc2Fhcy5hY2NvdW50cy52MS5SZXZva2VTb3VyY2VEZWxlZ2F0aW9uUmVzcG9uc2UiSsLzGEYIAhAEKgwKBm9yZ19pZBACGAEwATomCiJzYWFzLmRhdGFzb3VyY2UuZGVsZWdhdGlvbi5yZXZva2VkEAJAAUgEUAJYA2ABEusBChZEZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzEi8uc2Fhcy5hY2NvdW50cy52MS5EZWxlZ2F0ZVNvdXJjZVRyaWdnZXJzUmVxdWVzdBowLnNhYXMuYWNjb3VudHMudjEuRGVsZWdhdGVTb3VyY2VUcmlnZ2Vyc1Jlc3BvbnNlIm7C8xhqCAIQBCoMCgZvcmdfaWQQAhgBMAE6Sgoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24uY3JlYXRlZAoic2Fhcy5kYXRhc291cmNlLmRlbGVnYXRpb24ucmV2b2tlZBACQAFIBFACWANgARKyAQobR2V0U291cmNlVHJpZ2dlckRlY2xhcmF0aW9uEjQuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXF1ZXN0GjUuc2Fhcy5hY2NvdW50cy52MS5HZXRTb3VyY2VUcmlnZ2VyRGVjbGFyYXRpb25SZXNwb25zZSImwvMYIggCEAQqDAoGb3JnX2lkEAIYATABOgIQAUABSANQAlgDYAESgwMKD1JlY29uY2lsZVNvdXJjZRIoLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UimgLC8xhqCAIQAxoRZGF0YXNvdXJjZTppbnZva2UiEWRhdGFzb3VyY2U6aW52b2tlKg8KCXNvdXJjZV9pZBAEGAMwATohCh1zYWFzLmRhdGFzb3VyY2Uuc291cmNlLnN5bmNlZBACQANIBFACWAJgAdrzGKcBCgIIPBIDCNgEGAUiAggCKgtVTkFWQUlMQUJMRSoSUkVTT1VSQ0VfRVhIQVVTVEVEKgdBQk9SVEVEMg9zYWFzLWRhdGFzb3VyY2VKOS9zYWFzLmFjY291bnRzLnYxLkRhdGFzb3VyY2VTZXJ2aWNlL0xvb2t1cFJlY29uY2lsZVNvdXJjZVCAIFiAIGABchgKBnNvdXJjZRIGaW52b2tlEgRyZWFkGAESvwEKFUxvb2t1cFJlY29uY2lsZVNvdXJjZRIuLnNhYXMuYWNjb3VudHMudjEuTG9va3VwUmVjb25jaWxlU291cmNlUmVxdWVzdBopLnNhYXMuYWNjb3VudHMudjEuUmVjb25jaWxlU291cmNlUmVzcG9uc2UiS8LzGEcIAhADGg9kYXRhc291cmNlOnJlYWQiD2RhdGFzb3VyY2U6cmVhZCoPCgllZmZlY3RfaWQQBBgDMAE6AhABQAFIA1ACWAJgAUK3AQoUY29tLnNhYXMuYWNjb3VudHMudjFCD0RhdGFzb3VyY2VQcm90b1ABWixhY2NvdW50cy9wa2cvZ2VuL3NhYXMvYWNjb3VudHMvdjE7YWNjb3VudHN2MaICA1NBWKoCEFNhYXMuQWNjb3VudHMuVjHKAhBTYWFzXEFjY291bnRzXFYx4gIcU2Fhc1xBY2NvdW50c1xWMVxHUEJNZXRhZGF0YeoCElNhYXM6OkFjY291bnRzOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_codefly_runnable_v0_options, file_google_api_annotations, file_google_protobuf_duration, file_google_protobuf_struct, file_google_protobuf_timestamp, file_saas_jobs_v1_jobs, file_saas_policy_v1_options]); /** * GitHubDatasourceConfig is the public, non-secret configuration of a GitHub @@ -4233,6 +4233,8 @@ export const DatasourceService: GenService<{ * Committed means the normalized request and admitted declaration match the * stored attempt. Unknown remains unresolved; this method never redispatches. * Current actor, tenant and stored-source read authority apply before comparison. + * Source-scope refusals emit the existing failure audit; successful reads do not + * record another invocation or change the retained receipt. * This is independent of the paired Runnable Lookup contract above. * * @generated from rpc saas.accounts.v1.DatasourceService.VerifySourceOperationReceipt From 8c4d97dfb7d4a2e67eeb1331315ded411e661a22 Mon Sep 17 00:00:00 2001 From: Gael <338191059+gael-obin@users.noreply.github.com> Date: Tue, 3 Nov 2026 00:18:36 -0500 Subject: [PATCH 3/3] docs(sdk): reference the maintained CI generator pin --- libraries/source-read-sdk/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/source-read-sdk/README.md b/libraries/source-read-sdk/README.md index fedc5d1dd..8ea65c363 100644 --- a/libraries/source-read-sdk/README.md +++ b/libraries/source-read-sdk/README.md @@ -59,7 +59,7 @@ provider. ## Regenerate -Requires released Codefly CLI **v0.1.219** (the CI pin). From the repository root: +Use the released Codefly CLI selected by the [CI installer](../../scripts/ci/install-codefly.sh). From the repository root: ```sh codefly generate client --from saas-starter/accounts/authority --name source-read-sdk \