From c3125f878955aa39f899856e1aea0f7dc5f11d71 Mon Sep 17 00:00:00 2001 From: Ayla Croft Date: Sun, 20 Sep 2026 13:59:26 -0400 Subject: [PATCH 1/6] docs(s021): G1 plan with the canonicalisation measured, and the slice opens ROADMAP row 021 to in_progress. NOTES.md carries the measurement of the two RFC 8785 packages (rfc8785 1.0.0 refuses OTP 28; jcs 0.2.0 matches the RFC's own vector byte for byte), the decision for jcs open to the owner's veto, the nine-line build plan, the two-item manual queue, and four deviations stated before any code. plan_check: PASS. Signed-off-by: Ayla Croft --- ROADMAP.md | 2 +- slices/021-permission-gate/NOTES.md | 78 +++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 slices/021-permission-gate/NOTES.md diff --git a/ROADMAP.md b/ROADMAP.md index 6ebf70e..a38f4f0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -38,7 +38,7 @@ standards register names the rows that ask for them. | 012 | Session process + agent loop (gen_statem, DynamicSupervisor, rehydration) | 1 Core loop | L | 010, 011 | approved | | 013 | LiveView chat UI with streaming | 1 Core loop | M | 012 | approved | | 020 | Tool protocol + registry | 2 Tools | M | 012 | approved | -| 021 | Permission gate + approval UI (M2 fingerprint-bound, M7) | 2 Tools | M | 020, 013 | planned | +| 021 | Permission gate + approval UI (M2 fingerprint-bound, M7) | 2 Tools | M | 020, 013 | in_progress | | 022 | Core tools: filesystem, web fetch/search, shell (MuonTrap) | 2 Tools | L | 021 | planned | | 023 | Context compaction + session lineage | 2 Tools | M | 012 | planned | | 024 | Effect catalog, authority selection (`TRINITY_AUTHORITY`), local receipts | 2 Tools | L | 021, 022 | planned | diff --git a/slices/021-permission-gate/NOTES.md b/slices/021-permission-gate/NOTES.md new file mode 100644 index 0000000..f698f71 --- /dev/null +++ b/slices/021-permission-gate/NOTES.md @@ -0,0 +1,78 @@ +# Slice 021: NOTES + +## The canonicalisation, measured 2026-09-20 before any code + +The fingerprint docs/07 and this slice's M2 rule name is `sha256(rfc8785_canonical({tool, args, scope, cwd, +canonicalization_version}))`. Two RFC 8785 packages on hex, read from their tarballs in a scratch directory and +run against the RFC's own example (section 3.2.3: the `numbers`, `string` and `literals` object): + +| Candidate | Result | Derived by | +|---|---|---| +| `rfc8785` 1.0.0 (2026-07-24, 935 downloads, no runtime deps, 1,377 lines, an ES6 number corpus in its own suite) | **Refuses to compile on this tree's OTP**: `rfc8785 requires Erlang/OTP 29 or later (found OTP 28)`. The OTP pin is 28.5.0.5 for Burrito's ERTS (VERSIONS.md), so it is out until the pin moves. | `mix deps.get && mix run` in the scratch project | +| `jcs` 0.2.0 (2025-03-31, 91,772 downloads, depends on jason, 402 lines, Apache-2.0) | **Matches the RFC vector byte for byte**, numbers included (`1e+30`, `4.5`, `0.002`, `1e-27`, and `2.0` as `2`), through `:erlang.float_to_binary(:short)`; keys sorted as the RFC asks. Pre-1.0 and eighteen months since its release: R11's trigger, noted. | the same, `Jcs.encode/1` against `expected.txt` | + +**Decision at G1: `jcs ~> 0.2`**, with the RFC vector as a test in the tree so a later version that stops +matching fails the gate, and `canonicalization_version` 1 bound into every fingerprint so a change of scheme is a +new version rather than a silent difference. Open to the owner's veto. + +## G1 plan, 2026-09-20 + +Tree at `81b8da1` on `main` (020 and 013 approved); branch `slice/021-permission-gate`; ROADMAP row 021 set to +`in_progress` in this commit. docs/07's permission gate section is the contract. Each line names its test. + +1. `chore(s021): add jcs ~> 0.2`; `Trinity.Permissions.Fingerprint`: `canonical/1` (jcs) and `of/4` + (`sha256` hex over `{tool, args, scope, cwd, canonicalization_version: 1}`). Tests: the RFC 8785 vector; the + same call twice is the same digest; a changed argument, scope or cwd is a different one. +2. Migrations: `tool_permissions` (tool, pattern, decision, scope, expires_at, decided_by, timestamps) and + `approvals` (session_id, tool, args, risk, fingerprint, status, decision, decided_at, decided_by, consumed_at, + expires_at, timestamps); schemas `Permissions.Rule` and `Permissions.Approval`; `Permissions.Store` inside the + boundary. docs/05 synced. Test: the two tables through the store on SQLite; the postgres job on both. +3. The tier's source. 020 left `Permissions.tier/1` an empty attribute because Permissions may not read the + registry; here the registry hands the core tools' declared risks to Permissions at admission + (`Permissions.put_core_tiers/1`, Tools → Permissions, the allowed direction), a dynamic tool never does, and + `tier/1` reads that table by name alone. Test: the census's "every mapped name is a core tool" gains content; + `tier("echo")` is `:read`, `tier("mcp:fake:echo")` is `:ask`. +4. `Permissions.Policy.Layered` (the implementation in force): session grants (rules scoped `session:`, a + fingerprint pattern `fp:`, unexpired) → an unconsumed "once" approval for the fingerprint (consumed on + use) → a denied approval for the fingerprint in this turn → persona policy (`settings.permissions`) → global + rules (a glob on one named argument, `key=glob`, `*` for any; prefix as a trailing `*`) → the default by + tier (config `permissions: [default: %{read: :allow, network: :allow, write: :ask, exec: :ask, destructive: + :ask}]`, unmapped `:ask`). Tests: each layer in isolation and the order between two. +5. `Permissions.Gate` (GenServer): `request/4` writes the pending row, broadcasts `{:approval, :requested, a}` on + `approvals:` and `approvals:all` (row before broadcast), arms the expiry + (`permissions: [expiry_ms: 600_000]`, short in test); `decide_request/3` (`:once | :session | :always | + :deny`) updates the row, writes the grant or the rule (always: the pattern the user confirmed), broadcasts + `{:approval, :decided, a}`; expiry decides `:deny` as `"expiry"`; pending rows are reloaded at init with their + timers. Tests: AC6 (expiry within the short timeout, the row `expired`, the decision `deny`), AC7's auto half + (every decision a row with `decided_at`), a decided row cannot be decided twice. +6. The runner: an `:ask` answer creates the request through the Gate and returns + `{:error, {:approval_required, approval_id}, meta}`; the Session, seeing one in the turn's results, holds those + calls, enters `approval_wait` (the state 012 left without an inbound transition), subscribes to + `approvals:` at init, and on the last decision re-runs the held calls, where the runner asks the policy + again: the once grant or the session grant allows, the denial denies, and the fingerprint is re-derived from + the arguments actually passed (a divergence is `:deny`). Tests: AC1 (Echo, `:read`, runs with the Gate's + `request/4` never called, a Mox on the Gate's behaviour), AC3 (a session grant: the second identical call + runs without asking, a different argument asks again, a new session asks), AC4 (an always rule with a glob: + a call inside runs, outside asks; the rule row exists), AC5 (deny: the tool row says denied, the turn goes + on to a final message), AC8 (kill during `approval_wait`: the row is pending after the restart, deciding it + updates the row and broadcasts; the restarted session is idle, as 012's reset-is-total requires). +7. LiveView: `TrinityWeb.ApprovalComponents.approval_card` (tool, risk badge, arguments pretty-printed, the danger + line for `:exec` and `:destructive`, the four buttons; "always" shows the pre-filled, editable pattern), + rendered in `SessionLive.Show` while a request is pending; a pending count in the shell's bar from + `approvals:all`; `PermissionsLive` at `/permissions` listing approvals (decided and pending) and rules with + a revoke. Everything the UI does is `Permissions.decide_request/3`; the buttons carry no authority (M7). + Tests: the card renders on `{:approval, :requested, _}`; each button decides; `/permissions` lists the row. +8. Screenshots for AC2 and AC7 from the dev server driven by chromium, as at 013, with a write-risk test tool + available in dev (the fake provider flag gains a tool script). docs/07 synced; docs/01 tree. +9. Gate, coverage row, PROOF.md, ROADMAP to `done`, pull request (signed merge body), tag. + +Manual verification queue, for the owner at G4: +- **AC2**: `TRINITY_FAKE_PROVIDER=1 mix phx.server`, a session, send "write"; the fake calls a write-risk tool; + the card appears; "Allow once"; the tool runs and the final message follows. Screenshot. +- **AC7**: after a few decisions, open `/permissions`: every decision listed with its time. Screenshot. + +Deviations from SLICE.md, stated before building: the runner asks the policy at execution and the Session never +pre-checks, so `decide/3` stays exactly once per execution attempt (020 AC7) and the M2 re-derivation is the same +call; "allow once" is an approval row consumed at its one use, not a rule; a denial is bound to the fingerprint +for the turn that asked and never outlives it; the persona layer reads `personas.settings["permissions"]` +(`tool => decision`), the smallest shape 030 can grow. From 897be2b7c8a1f909e93c67d866d09822ee5d2fa2 Mon Sep 17 00:00:00 2001 From: Ayla Croft Date: Sun, 20 Sep 2026 13:59:41 -0400 Subject: [PATCH 2/6] chore(s021): add jcs ~> 0.2 RFC 8785 canonical JSON for the approval fingerprints (docs/07), chosen by the measurement in NOTES.md: jcs 0.2.0 matches the RFC's own vector on this OTP; rfc8785 1.0.0 refuses OTP 28. VERSIONS row added; hex.audit clean. Signed-off-by: Ayla Croft --- VERSIONS.md | 1 + lib/trinity/versions.ex | 7 +++++++ mix.exs | 3 +++ mix.lock | 1 + 4 files changed, 12 insertions(+) diff --git a/VERSIONS.md b/VERSIONS.md index 4c25af3..9bd93b2 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -136,6 +136,7 @@ never pin a version hex marks as retired or vulnerable. | `phoenix_streamdown` | not used (measured at Slice 013, 2026-09-20) | 🔍 not a single package | Streaming markdown renderer for LiveView. Measured at Slice 013: 1.0.0-beta.4 (2026-05-03) was still the latest release with no stable behind it, and this file's own rule forbids a pre-release. It is 801 lines over `mdex`, whose own `streaming: true` option completes fragments; the rest is a rendering rule Slice 013 keeps anyway. The row stays so the decision is visible where a reader would look for the package. | | `mdex` | ~> 0.13 | ✅ in `mix.lock` | Markdown renderer for the chat (`TrinityWeb.Markdown`), streaming fragments completed by its `streaming: true` option, raw HTML omitted (`unsafe: false`) and the default sanitizer on top. Added at Slice 013 after the measurement in its NOTES.md: `earmark` 1.4.49 is retired on hex with an open XSS advisory (EEF-CVE-2026-48591), which the gate refuses. ⚠️ A Rust NIF (`mdex_native`): the first in the bundle. Measured at Slice 013 (NOTES finding 13): neither precompiled artifact loads in Burrito's musl ERTS on Linux, so the linux package builds it from source for musl with Zig as the linker (`rustler` below, `scripts/zig-cc-musl`, the three settings in config/config.exs); macOS and Windows load the precompiled artifact. The `--smoke` path prints whether it rendered, and the `package` workflow reads that line on every target. | | `jsv` | ~> 0.23 | ✅ in `mix.lock` | JSON Schema (2020-12) validation of tool arguments in `Trinity.Tools.Schema`, with `cast: false` so a malformed call is refused and never repaired (docs/07). Was transitive through req_llm; direct since Slice 020 because a module of ours calls it (ADR-0009: Trinity's own tool behaviour, jsv for its schemas). | +| `jcs` | ~> 0.2 | ✅ in `mix.lock` | RFC 8785 canonical JSON, under every approval fingerprint (`Trinity.Permissions.Fingerprint`, Slice 021) and, at 024, under the receipts' signed payload. Chosen at Slice 021: it matches the RFC's own example vector byte for byte on this OTP, and `test/trinity/permissions/fingerprint_test.exs` keeps that vector so a release that stops matching fails the gate. ⚠️ Pre-1.0, released 2025-03-31 with nothing since (R11's trigger). The alternative, `rfc8785` 1.0.0, refuses OTP 28 and waits on the OTP pin. | | `rustler` | ~> 0.38 | ✅ in `mix.lock` | Build time only (`runtime: false`): what `rustler_precompiled` needs to compile `mdex_native` from source when `MDEX_NATIVE_BUILD=1`, which the linux package sets (owner decision 2026-09-20, Slice 013 NOTES finding 14). Nothing in the tree calls it. | ### Dev and quality diff --git a/lib/trinity/versions.ex b/lib/trinity/versions.ex index 487d2db..45e79c4 100644 --- a/lib/trinity/versions.ex +++ b/lib/trinity/versions.ex @@ -274,6 +274,13 @@ defmodule Trinity.Versions do note: "JSON Schema (2020-12) validation of tool arguments in `Trinity.Tools.Schema`, with `cast: false` so a malformed call is refused and never repaired (docs/07). Was transitive through req_llm; direct since Slice 020 because a module of ours calls it (ADR-0009: Trinity's own tool behaviour, jsv for its schemas)." }, + %{ + name: "jcs", + pin: "~> 0.2", + lock: "jcs", + note: + "RFC 8785 canonical JSON, under every approval fingerprint (`Trinity.Permissions.Fingerprint`, Slice 021) and, at 024, under the receipts' signed payload. Chosen at Slice 021: it matches the RFC's own example vector byte for byte on this OTP, and `test/trinity/permissions/fingerprint_test.exs` keeps that vector so a release that stops matching fails the gate. ⚠️ Pre-1.0, released 2025-03-31 with nothing since (R11's trigger). The alternative, `rfc8785` 1.0.0, refuses OTP 28 and waits on the OTP pin." + }, %{ name: "rustler", pin: "~> 0.38", diff --git a/mix.exs b/mix.exs index 9786a0d..a416e5b 100644 --- a/mix.exs +++ b/mix.exs @@ -106,6 +106,9 @@ defmodule Trinity.MixProject do # Slice 020: JSON Schema validation of tool arguments (Trinity.Tools.Schema). Already in # the lock through req_llm; direct because a module of ours calls it (ADR-0009). {:jsv, "~> 0.23"}, + # Slice 021: RFC 8785 canonical JSON under every approval fingerprint (docs/07). Chosen + # by the measurement in the slice's NOTES.md; the RFC's vector is a test in the tree. + {:jcs, "~> 0.2"}, # Slice 013 (owner decision, 2026-09-20): the linux package builds mdex's NIF from # source for musl (MDEX_NATIVE_BUILD=1 and TRINITY_NIF_TARGET in config/config.exs), # because neither precompiled artifact loads in Burrito's musl ERTS (NOTES finding 13). diff --git a/mix.lock b/mix.lock index a1a6611..16976ce 100644 --- a/mix.lock +++ b/mix.lock @@ -32,6 +32,7 @@ "idna": {:hex, :idna, "7.1.0", "1067a13043538129602d2f2ce6899d8713125c7d19734aa557ce2e3ea55bd4f1", [:rebar3], [], "hexpm", "6ae959a025bf36df61a8cab8508d9654891b5426a84c44d82deaffd6ddf8c71f"}, "igniter": {:hex, :igniter, "0.8.4", "f79f1bbdc2fb7b9ca030a22d12a585b060cbf5b94b9d3f23b1148578a9e05d11", [:mix], [{:ex_ast, "~> 0.5", [hex: :ex_ast, repo: "hexpm", optional: false]}, {:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4.5", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "a9b1cbec996ccb100b4f7d8130129b2dd3f18eb4224ac9a0e907e428ca90dbd7"}, "jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"}, + "jcs": {:hex, :jcs, "0.2.0", "e0524c23b576e8247f9f5f09d1b82cb3f92c7b132932b82d5d656461831c6c99", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f52e86571f56fab695682bf0ab7fd697768acb20de16b30809e9654d1ec1c9dd"}, "jsv": {:hex, :jsv, "0.23.0", "db238039fc2e437bca3e226b09eacd72ebd588d6e014d0d4150330f6ca6762fa", [:mix], [{:abnf_parsec, "~> 2.0", [hex: :abnf_parsec, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:idna, "~> 6.0 or ~> 7.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:texture, ">= 1.2.1", [hex: :texture, repo: "hexpm", optional: false]}], "hexpm", "3876f6ada437b3a7ec6214c9b942bd218f25d245b92a7970a034a7cf06dbe925"}, "lazy_html": {:hex, :lazy_html, "0.1.12", "31a55ee622918fce988c94b06232227b42daa64e4eab14ac32081d0f3fd8db6f", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "8a0da594776caee58782c6f93b2abaa5bdb809daf8d43351a561f7de9dc2e2a8"}, "llm_db": {:hex, :llm_db, "2026.9.4", "f56fdc8012477a0fa33247841f980c9a71e80408a5b69f63692ea238f46f8636", [:mix], [{:dotenvy, "~> 1.1", [hex: :dotenvy, repo: "hexpm", optional: false]}, {:igniter, "~> 0.7", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:toml, "~> 0.7", [hex: :toml, repo: "hexpm", optional: false]}, {:zoi, "~> 0.10", [hex: :zoi, repo: "hexpm", optional: false]}], "hexpm", "196a162cfc8826746ee84eeb395dd3a17268bfff2154ba378799bc1511e722ce"}, From 1f3727f398c3d95b1b6ef87eb08a05e4f41bcf37 Mon Sep 17 00:00:00 2001 From: Ayla Croft Date: Sun, 20 Sep 2026 14:19:38 -0400 Subject: [PATCH 3/6] feat(s021): the permission gate: layered policy, fingerprints, the Gate, approval_wait, the card and the audit Lines 2 to 8 of the G1 plan. Trinity.Permissions.Fingerprint (sha256 over RFC 8785 of tool, args, scope, cwd, canonicalization_version 1; the RFC's vector is a test). The tool_permissions and approvals tables with their schemas (Rule: the pattern language `*`, `key=glob`, `fp:`, `re:`; Approval: status, decision, decided_at, decided_by, consumed_at, expires_at) and Store. The tier's source: the registry hands the core tools' declared risks to Permissions.put_core_tiers/1 at its start and nothing else writes them. Policy.Layered in docs/07's order: session grants, the newest unspent decision for the fingerprint (allow once and deny are each consumed by one execution), persona settings, global rules, the default by tier. Permissions.Gate: a request is a row then a broadcast on approvals: and approvals:all, an expiry timer, pending rows reloaded at init; decide_request/3 records the decision and writes the session grant or the global rule it implies. The runner turns an :ask into a request and an approval_required result; the Session holds those calls in approval_wait (012's empty state, now entered) and runs them again when the last decision lands, where the policy re-derives the fingerprint. TrinityWeb.ApprovalComponents (the card, the risk badge, the pending indicator), the card in the chat, PermissionsLive at /permissions (pending decidable, every decision with its time and decider, rules revocable). scripts/dev_chat_on_test_registry.sh serves the chat on the test registry for the screenshots, on its own database. Tests, 25 in test/trinity/permissions and 4 in the LiveView suite: the RFC vector, the pattern language, each policy layer and their order, the Gate's rows and broadcasts, AC1 (a read tool never reaches the Gate), AC2's two halves (approval_wait and the card; allow once runs the tool, the final message follows), AC3 (a session grant: the identical call runs, other arguments ask, another session asks), AC4 (an always rule with a glob, outside it asks, revocable), AC5 (a denial the model reads, the turn goes on), AC6 (expiry into a denial decided by expiry within the timeout), AC7 (every decision a row with decided_at; the audit page), AC8 (killed in approval_wait: the row pending and decidable, the restarted session idle). Screenshots in proof/. Gate exit 0, 233 tests; credo --strict --all clean; sobelow clean; docs/01, 05 and 07 synced. Signed-off-by: Ayla Croft --- REUSE.toml | 2 +- config/test.exs | 8 +- docs/01-architecture.md | 3 +- docs/05-data-model.md | 21 +- docs/07-security-model.md | 18 +- lib/trinity.ex | 2 + lib/trinity/application.ex | 2 + lib/trinity/permissions.ex | 150 ++++++++++---- lib/trinity/permissions/approval.ex | 61 ++++++ lib/trinity/permissions/fingerprint.ex | 36 ++++ lib/trinity/permissions/gate.ex | 170 +++++++++++++++ lib/trinity/permissions/policy.ex | 24 +++ lib/trinity/permissions/policy/layered.ex | 95 +++++++++ lib/trinity/permissions/rule.ex | 93 +++++++++ lib/trinity/permissions/store.ex | 113 ++++++++++ lib/trinity/sessions/session.ex | 84 ++++++-- lib/trinity/sessions/state.ex | 11 +- lib/trinity/tools/registry.ex | 24 ++- lib/trinity/tools/runner.ex | 16 +- .../components/approval_components.ex | 155 ++++++++++++++ lib/trinity_web/live/permissions_live.ex | 187 +++++++++++++++++ lib/trinity_web/live/session_live/show.ex | 68 +++++- lib/trinity_web/router.ex | 2 + .../20260920200000_create_permissions.exs | 49 +++++ scripts/dev_chat_on_test_registry.sh | 30 +++ .../proof/ac2-allow-once-final.png | Bin 0 -> 52410 bytes .../proof/ac2-approval-card.png | Bin 0 -> 69769 bytes .../021-permission-gate/proof/ac5-denied.png | Bin 0 -> 75462 bytes .../proof/ac7-permissions-audit.png | Bin 0 -> 99515 bytes test/support/rfc8785_expected.txt | 1 + test/support/rfc8785_input.json | 1 + test/support/tools/write_note.ex | 29 +++ test/trinity/permissions/fingerprint_test.exs | 32 +++ test/trinity/permissions/gate_test.exs | 195 ++++++++++++++++++ test/trinity/permissions/rule_test.exs | 54 +++++ .../trinity/permissions/session_flow_test.exs | 162 +++++++++++++++ test/trinity/tools/registry_test.exs | 7 +- test/trinity/tools/runner_test.exs | 14 +- test/trinity_web/live/approval_live_test.exs | 157 ++++++++++++++ 39 files changed, 1994 insertions(+), 82 deletions(-) create mode 100644 lib/trinity/permissions/approval.ex create mode 100644 lib/trinity/permissions/fingerprint.ex create mode 100644 lib/trinity/permissions/gate.ex create mode 100644 lib/trinity/permissions/policy.ex create mode 100644 lib/trinity/permissions/policy/layered.ex create mode 100644 lib/trinity/permissions/rule.ex create mode 100644 lib/trinity/permissions/store.ex create mode 100644 lib/trinity_web/components/approval_components.ex create mode 100644 lib/trinity_web/live/permissions_live.ex create mode 100644 priv/repo/migrations/20260920200000_create_permissions.exs create mode 100755 scripts/dev_chat_on_test_registry.sh create mode 100644 slices/021-permission-gate/proof/ac2-allow-once-final.png create mode 100644 slices/021-permission-gate/proof/ac2-approval-card.png create mode 100644 slices/021-permission-gate/proof/ac5-denied.png create mode 100644 slices/021-permission-gate/proof/ac7-permissions-audit.png create mode 100644 test/support/rfc8785_expected.txt create mode 100644 test/support/rfc8785_input.json create mode 100644 test/support/tools/write_note.ex create mode 100644 test/trinity/permissions/fingerprint_test.exs create mode 100644 test/trinity/permissions/gate_test.exs create mode 100644 test/trinity/permissions/rule_test.exs create mode 100644 test/trinity/permissions/session_flow_test.exs create mode 100644 test/trinity_web/live/approval_live_test.exs diff --git a/REUSE.toml b/REUSE.toml index 44888a2..770def4 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -11,7 +11,7 @@ SPDX-PackageDownloadLocation = "https://github.com/ScriptKittyOS/Trinity" # the gap is recorded rather than glossed. [[annotations]] -path = ["mix.lock", "src-tauri/Cargo.lock", "**/*.md", "**/*.json", "**/*.tsv", "**/*.cff", "**/*.toml", ".tool-versions", ".gitignore", ".sobelow-skips", ".sobelow-skips.reasons", "priv/name_digests.txt", ".formatter.exs", "slices/**/proof/**"] +path = ["mix.lock", "src-tauri/Cargo.lock", "**/*.md", "**/*.json", "**/*.tsv", "**/*.cff", "**/*.toml", ".tool-versions", ".gitignore", ".sobelow-skips", ".sobelow-skips.reasons", "priv/name_digests.txt", ".formatter.exs", "slices/**/proof/**", "test/support/*.txt"] precedence = "aggregate" SPDX-FileCopyrightText = "Sudo Apt Holdings LLC" SPDX-License-Identifier = "Apache-2.0" diff --git a/config/test.exs b/config/test.exs index 8e373fa..3fbb856 100644 --- a/config/test.exs +++ b/config/test.exs @@ -14,11 +14,15 @@ config :trinity, :tools, Trinity.TestTools.Echo, Trinity.TestTools.Sleep, Trinity.TestTools.Crash, - Trinity.TestTools.Big + Trinity.TestTools.Big, + Trinity.TestTools.WriteNote ], - toolsets: %{core: ["echo", "sleep", "crash", "big"]}, + toolsets: %{core: ["echo", "sleep", "crash", "big", "write_note"]}, timeout_ms: 2_000 +# Slice 021: requests expire fast enough for AC6 to watch, and a session grant lasts an hour. +config :trinity, :permissions, expiry_ms: 1_000, session_grant_ms: 3_600_000 + # Slice 012: sessions hibernate and stop quickly in tests so AC8 is observable in seconds. config :trinity, :sessions, idle_hibernate_ms: 200, idle_stop_ms: 60_000 diff --git a/docs/01-architecture.md b/docs/01-architecture.md index 1a223ab..b32bbdf 100644 --- a/docs/01-architecture.md +++ b/docs/01-architecture.md @@ -26,7 +26,8 @@ Trinity.Application ├── Trinity.Tools.Supervisor # Slice 020, as built: Trinity.Tools.TaskSupervisor (every tool │ │ # call of a turn runs under it) and Trinity.Tools.Registry │ │ # (GenServer over ETS). 022 adds the stateful runtimes beside them -├── Trinity.Permissions.Gate # approval requests + allowlist cache. Slice 021 +├── Trinity.Permissions.Gate # Slice 021, as built: approval requests (rows, then broadcasts), +│ # decisions, expiries; pending rows reloaded with their timers ├── Trinity.Receipts.Supervisor # Slice 024 │ └── Trinity.Receipts.ChainWriter (one per chain_scope, :unique in Trinity.Registry; ADR-0013) │ # serialises append per scope. prev_hash -> receipt_hash is a read-then-write, so diff --git a/docs/05-data-model.md b/docs/05-data-model.md index 34271e6..ad9911e 100644 --- a/docs/05-data-model.md +++ b/docs/05-data-model.md @@ -78,17 +78,28 @@ Filesystem is canonical for content; DB is the index (rebuildable via `mix trini ### skill_changes (Slice 041) Staged proposals by the agent: `skill_id`, `diff`, `rationale`, `status`, `decided_by`, `decided_at`. -### tool_permissions (Slice 021) +### tool_permissions (Slice 021, as built) | column | type | notes | |---|---|---| | tool | string | | -| pattern | string | glob/regex on args (e.g. shell command prefix, path) | +| pattern | string | `*`, `key=glob` (`*` in a segment, `**` across, `?` one character; a trailing `*` is a prefix), `fp:` (a session grant bound to a fingerprint), `re:` (hand-edited rows only) | | decision | string | "allow" \| "deny" \| "ask" | | scope | string | "global" \| "session:" \| "persona:" | -| expires_at | nullable | "allow for this session" | +| expires_at | nullable | set on "allow for this session" grants | +| decided_by | string, nullable | who wrote it ("liveview" from the card) | -### approvals (Slice 021) -Pending/decided approval requests: `session_id`, `tool`, `args`, `risk`, `status`, `decided_at`, `channel`. +### approvals (Slice 021, as built) +One row per request, the audit trail this slice owns; slice 024 reads it for decision receipts. +| column | type | notes | +|---|---|---| +| session_id | fk sessions | | +| tool, args, risk | string, map, string | the call and its tier at request time | +| fingerprint | string | `sha256(rfc8785({tool, args, scope, cwd, canonicalization_version}))`, re-derived at execution | +| status | string | "pending" \| "allowed" \| "denied" \| "expired" | +| decision | string, nullable | "once" \| "session" \| "always" \| "deny" | +| decided_at, decided_by | timestamp, string | every decided row has both ("expiry" is a decider) | +| consumed_at | nullable | a "once" allowance or a denial is spent by the execution that reads it | +| expires_at | timestamp | pending past it becomes "expired" with decision "deny" | ### tasks (Slice 050) | column | type | notes | diff --git a/docs/07-security-model.md b/docs/07-security-model.md index f105ea8..0e5a43e 100644 --- a/docs/07-security-model.md +++ b/docs/07-security-model.md @@ -39,10 +39,20 @@ system prompt states that instructions inside untrusted blocks are data, not com Every `Trinity.Tools.Tool` declares `effect/0` (`:none | :artifact | :catalog`) and the gate derives risk from the tool **name only** via `Trinity.Permissions.tier/1` (`:read | :write | :exec | :network | :destructive`; unmapped → ask). Name-only is deliberate: it makes the tier a code-owned function of a value no caller can influence. That holds only while the namespace is closed. Tools registered at runtime carry names chosen elsewhere, by an MCP server or a skill author, so **every dynamic tool is namespaced before the tier lookup**: `mcp::`, `skill:`. Core tool names are reserved and cannot be claimed. Without this a hostile server naming its tool `fs_read` inherits the `:read` tier and its allow-by-default policy, and the unmapped-goes-to-ask fallback does not catch it, because the name is mapped. -`Trinity.Permissions.decide(session, tool, args)` consults, in order: session grants → persona policy → global -`tool_permissions` → default policy (`:read` allow, `:network` allow, `:write` ask, `:exec` ask, `:destructive` ask). -An `:ask` suspends the Session in `approval_wait`, broadcasts to `approvals:`, and resumes on decision. -Decisions are recorded (`approvals` table) and receipted. Approvals bind the canonical fingerprint of `(tool, args, scope, cwd, canonicalization_version)` and are re-derived at execution; "allow for this session" binds that fingerprint with an expiry; "always allow" is a rule, recorded as such. +`Trinity.Permissions.decide(session, tool, args, opts)` consults, in order: session grants → the newest unspent +decision for this fingerprint (an "allow once" or a denial, each spent by the execution that reads it) → +persona policy → global `tool_permissions` → default policy (`:read` allow, `:network` allow, `:write` ask, +`:exec` ask, `:destructive` ask; an unmapped name asks). +An `:ask` suspends the Session in `approval_wait`, broadcasts to `approvals:` (and `approvals:all`), and +resumes on decision. Decisions are recorded (`approvals` table) and receipted (024). Approvals bind the canonical +fingerprint of `(tool, args, scope, cwd, canonicalization_version)` and are re-derived at execution; "allow for +this session" binds that fingerprint with an expiry; "always allow" is a rule, recorded as such. + +As built at slice 021: the tier table is written once, by the registry, from the `risk/0` of the modules +`config :trinity, :tools` names, so a tier comes from code and config and never from a runtime registration; the +runner asks the policy at execution and the Session never pre-checks, so the decision that runs a call is the one +made against the arguments actually passed; a request left undecided expires into a denial decided by +`"expiry"`; the card's buttons and the `/permissions` page call `decide_request/3` and nothing else. ## Shell (Slice 022) diff --git a/lib/trinity.ex b/lib/trinity.ex index 4c021d3..b834b0d 100644 --- a/lib/trinity.ex +++ b/lib/trinity.ex @@ -24,6 +24,8 @@ defmodule Trinity do LLM, Tools, Permissions, + Permissions.Approval, + Permissions.Rule, Effects.Catalog ] ++ if(Mix.env() == :test, do: [DataCase, NetworkGuard, Factory], else: []) diff --git a/lib/trinity/application.ex b/lib/trinity/application.ex index d38cfec..26ad11a 100644 --- a/lib/trinity/application.ex +++ b/lib/trinity/application.ex @@ -40,6 +40,8 @@ defmodule Trinity.Application do # Slice 020: the tool registry and the task supervisor tool calls run under, before # the sessions that call them. Trinity.Tools.Supervisor, + # Slice 021: approval requests and their decisions, with pending rows reloaded. + Trinity.Permissions.Gate, Trinity.Sessions.Supervisor, # Start to serve requests, typically the last entry TrinityWeb.Endpoint diff --git a/lib/trinity/permissions.ex b/lib/trinity/permissions.ex index 845a584..8f450f3 100644 --- a/lib/trinity/permissions.ex +++ b/lib/trinity/permissions.ex @@ -2,54 +2,132 @@ # SPDX-License-Identifier: Apache-2.0 defmodule Trinity.Permissions do @moduledoc """ - The permission gate's door. Slice 020 ships the shape; slice 021 the policy, the grants, the - approvals and the `approval_wait` path. - - `tier/1` is a function of the tool name alone (docs/07), read from a module attribute this - module owns: the core tool names 022 adds carry their tiers here, and any other name, a - namespaced dynamic tool included, is `:ask`. The map is code, not config, and it reads no - registry, so nothing a caller passes and nothing registered at runtime can move a tier. - `decide/3` consults the policy implementation in force (`config :trinity, - :permissions_policy`, default `Trinity.Permissions.Policy.Default`, which allows everything - until 021), and the runner calls it exactly once per tool call. + The permission gate (docs/07). Slice 020 shipped the shape; slice 021 the policy, the + grants, the approvals and their audit. + + **The tier is a function of the tool name alone.** Core tools hand their declared risk to + this module when the registry admits them (`put_core_tiers/1`, the one writer, called from + the registry's start with the modules named in config, never for a dynamic tool); `tier/1` + reads that table by name and answers `:ask` for any other name, a namespaced dynamic tool + included. Nothing a caller passes and nothing registered at runtime can move a tier. + + **A decision is data.** `decide/4` consults the policy in force (`Policy.Layered` by + default; a test may put a mock in `config :trinity, :permissions_policy`). An `:ask` + becomes an `approvals` row through the `Gate`, broadcast on `approvals:` and + `approvals:all` after it is written; the UI's only power is `decide_request/3`, which + records the decision, writes the grant or the rule it implies, and broadcasts. An approval + binds a fingerprint (`Trinity.Permissions.Fingerprint`) re-derived at execution. """ - use Boundary, deps: [Trinity], exports: [Policy] + use Boundary, deps: [Trinity], exports: [Policy, Approval, Rule, Fingerprint, Gate] - # Core tool names and their tiers. Empty at slice 020: no core tool lives in lib/ yet; 022 - # adds fs_read, fs_write, web_fetch, shell and the rest here, beside their modules. - @tiers %{} + alias Trinity.Permissions.{Approval, Fingerprint, Gate, Policy, Rule, Store} @type tier :: :read | :write | :exec | :network | :destructive | :ask @type decision :: :allow | :deny | :ask + @type request_decision :: :once | :session | :always | :deny - defmodule Policy do - @moduledoc "What decides a call. Slice 021 implements the layered policy; the default allows." - @callback decide(session_id :: String.t() | nil, tool :: String.t(), args :: map()) :: - Trinity.Permissions.decision() + @tiers_key {__MODULE__, :core_tiers} + @tier_values [:read, :write, :exec, :network, :destructive] - defmodule Default do - @moduledoc false - @behaviour Trinity.Permissions.Policy - @impl true - def decide(_session_id, _tool, _args), do: :allow - end - end + ## Tiers - @doc "The risk tier for a name: a mapped core name's tier, else `:ask`." + @doc "The risk tier for a name: a core tool's declared risk, else `:ask`." @spec tier(String.t()) :: tier() - def tier(name) when is_binary(name), do: Map.get(tiers(), name, :ask) + def tier(name) when is_binary(name), do: Map.get(core_tiers(), name, :ask) - @doc "The mapped core names, for the census." + @doc "The core names with a tier, for the census." @spec mapped_names() :: [String.t()] - def mapped_names, do: Map.keys(tiers()) + def mapped_names, do: core_tiers() |> Map.keys() |> Enum.sort() + + @doc """ + Records the core tools' tiers, name to risk, replacing the table. The registry is the one + caller, at its start, with the modules `config :trinity, :tools` names; a tier outside the + five is refused. + """ + @spec put_core_tiers(%{String.t() => tier()}) :: :ok + def put_core_tiers(tiers) when is_map(tiers) do + unless Enum.all?(tiers, fn {n, t} -> is_binary(n) and t in @tier_values end) do + raise ArgumentError, "core tiers must map names to one of #{inspect(@tier_values)}" + end + + :persistent_term.put(@tiers_key, tiers) + end + + defp core_tiers, do: :persistent_term.get(@tiers_key, %{}) + + ## Decisions + + @doc """ + The decision for one call, from the policy in force. `opts`: `persona:` (the row, for its + `settings["permissions"]`), `cwd:` (bound into the fingerprint). + """ + @spec decide(String.t() | nil, String.t(), map(), keyword()) :: decision() + def decide(session_id, tool, args, opts \\ []), do: impl().decide(session_id, tool, args, opts) + + @doc "The fingerprint of a call as this session would bind it." + @spec fingerprint(String.t() | nil, String.t(), map(), String.t() | nil) :: String.t() + def fingerprint(session_id, tool, args, cwd), + do: Fingerprint.of(tool, args, scope(session_id), cwd) + + @doc "The scope string a session's approvals and grants carry." + @spec scope(String.t() | nil) :: String.t() + def scope(nil), do: "session:none" + def scope(session_id), do: "session:" <> session_id + + defp impl, do: Application.get_env(:trinity, :permissions_policy, Policy.Layered) + + ## Requests and their decisions + + @doc "Creates a pending approval for a call (a row, then a broadcast) and returns it." + @spec request_approval(String.t(), String.t(), map(), keyword()) :: + {:ok, Approval.t()} | {:error, term()} + def request_approval(session_id, tool, args, opts \\ []), + do: Gate.request(session_id, tool, args, opts) + + @doc """ + Decides a pending request: `:once` allows this fingerprint one execution, `:session` grants + it for the session (a `tool_permissions` row scoped to it, with an expiry), `:always` writes + a global rule with `opts[:pattern]` (the pattern the user confirmed; `*` by default), `:deny` + denies. `opts[:by]` names the decider (`"liveview"` by default). Everything the UI does + goes through here, so a button carries no authority of its own (M7). + """ + @spec decide_request(String.t(), request_decision(), keyword()) :: + {:ok, Approval.t()} | {:error, term()} + def decide_request(id, decision, opts \\ []), do: Gate.decide(id, decision, opts) + + @doc "A pending request by id." + @spec get_approval(String.t()) :: Approval.t() | nil + def get_approval(id), do: Store.get_approval(id) + + @doc "Pending requests, oldest first; for one session or all." + @spec pending(String.t() | :all) :: [Approval.t()] + def pending(:all), do: Store.pending() + def pending(session_id), do: Store.pending_for(session_id) + + @doc "Approvals, newest first (`session_id:`, `limit:`)." + @spec list_approvals(keyword()) :: [Approval.t()] + def list_approvals(opts \\ []), do: Store.list_approvals(opts) + + @doc "Rules and grants, newest first (`scope:`)." + @spec list_rules(keyword()) :: [Rule.t()] + def list_rules(opts \\ []), do: Store.list_rules(opts) + + @doc "Writes a rule by hand (the settings path); the UI's always-allow goes through `decide_request/3`." + @spec put_rule(map()) :: {:ok, Rule.t()} | {:error, Ecto.Changeset.t()} + def put_rule(attrs), do: Store.insert_rule(attrs) + + @doc "Removes a rule or grant." + @spec revoke_rule(String.t()) :: :ok | {:error, :not_found} + def revoke_rule(id), do: Store.delete_rule(id) - # Through a function so an empty map at this slice reads as a map to the type checker, - # not as a constant it can fold to :ask. - defp tiers, do: Map.new(@tiers) + ## Topics - @doc "The decision for one call, from the policy in force." - @spec decide(String.t() | nil, String.t(), map()) :: decision() - def decide(session_id, tool, args), do: impl().decide(session_id, tool, args) + @doc "The PubSub topic of a session's approvals, or of all of them." + @spec topic(String.t() | :all) :: String.t() + def topic(:all), do: "approvals:all" + def topic(session_id), do: "approvals:" <> session_id - defp impl, do: Application.get_env(:trinity, :permissions_policy, Policy.Default) + @doc "Subscribes the caller to `{:approval, :requested | :decided, %Approval{}}` for a session or all." + @spec subscribe(String.t() | :all) :: :ok | {:error, term()} + def subscribe(which), do: Phoenix.PubSub.subscribe(Trinity.PubSub, topic(which)) end diff --git a/lib/trinity/permissions/approval.ex b/lib/trinity/permissions/approval.ex new file mode 100644 index 0000000..6210f70 --- /dev/null +++ b/lib/trinity/permissions/approval.ex @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.Approval do + @moduledoc """ + A row of `approvals` (slice 021): one request for one call, with the fingerprint it binds, + and its decision. The audit trail this slice owns: every decision has `decided_at` and + `decided_by`; slice 024 reads these rows when it builds decision receipts and writes none + of them. + """ + use Ecto.Schema + import Ecto.Changeset + + @primary_key {:id, Trinity.UUID, autogenerate: true} + @foreign_key_type Trinity.UUID + @timestamps_opts [type: :utc_datetime_usec] + + @statuses ~w(pending allowed denied expired) + @decisions ~w(once session always deny) + + @type t :: %__MODULE__{} + + schema "approvals" do + field :tool, :string + field :args, :map, default: %{} + field :risk, :string + field :fingerprint, :string + field :status, :string, default: "pending" + field :decision, :string + field :decided_at, :utc_datetime_usec + field :decided_by, :string + field :consumed_at, :utc_datetime_usec + field :expires_at, :utc_datetime_usec + belongs_to :session, Trinity.Sessions.SessionRow + timestamps() + end + + @doc "The closed vocabularies." + @spec statuses() :: [String.t()] + def statuses, do: @statuses + @spec decisions() :: [String.t()] + def decisions, do: @decisions + + @doc false + @spec request_changeset(t(), map()) :: Ecto.Changeset.t() + def request_changeset(approval, attrs) do + approval + |> cast(attrs, [:session_id, :tool, :args, :risk, :fingerprint, :expires_at]) + |> validate_required([:session_id, :tool, :risk, :fingerprint, :expires_at]) + |> foreign_key_constraint(:session_id) + end + + @doc false + @spec decide_changeset(t(), map()) :: Ecto.Changeset.t() + def decide_changeset(approval, attrs) do + approval + |> cast(attrs, [:status, :decision, :decided_at, :decided_by, :consumed_at]) + |> validate_required([:status, :decision, :decided_at, :decided_by]) + |> validate_inclusion(:status, @statuses) + |> validate_inclusion(:decision, @decisions) + end +end diff --git a/lib/trinity/permissions/fingerprint.ex b/lib/trinity/permissions/fingerprint.ex new file mode 100644 index 0000000..f36e802 --- /dev/null +++ b/lib/trinity/permissions/fingerprint.ex @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.Fingerprint do + @moduledoc """ + The fingerprint an approval binds (docs/07, M2): SHA-256, hex, over the RFC 8785 canonical + form of `{tool, args, scope, cwd, canonicalization_version}`. Re-derived from the arguments + actually passed at execution; a divergence denies. Slice 021. + + `canonicalization_version` is 1 and is part of the digest, so a change of scheme is a new + version and never a silent difference in old fingerprints. + """ + + @version 1 + + @doc "The canonicalization version bound into every fingerprint." + @spec version() :: pos_integer() + def version, do: @version + + @doc "RFC 8785 canonical JSON of a term (maps with string keys, lists, strings, numbers, booleans, nil)." + @spec canonical(term()) :: String.t() + def canonical(term), do: Jcs.encode(term) + + @doc "The fingerprint of a call in a scope and working directory." + @spec of(String.t(), map(), String.t(), String.t() | nil) :: String.t() + def of(tool, args, scope, cwd) when is_binary(tool) and is_map(args) and is_binary(scope) do + payload = %{ + "tool" => tool, + "args" => args, + "scope" => scope, + "cwd" => cwd, + "canonicalization_version" => @version + } + + :crypto.hash(:sha256, canonical(payload)) |> Base.encode16(case: :lower) + end +end diff --git a/lib/trinity/permissions/gate.ex b/lib/trinity/permissions/gate.ex new file mode 100644 index 0000000..2f2508e --- /dev/null +++ b/lib/trinity/permissions/gate.ex @@ -0,0 +1,170 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.Gate do + @moduledoc """ + The approval requests and their decisions. Slice 021. One GenServer in the application + tree: a request is a row, then a broadcast on `approvals:` and `approvals:all`, + then a timer; a decision is the row updated, the grant or rule it implies written, then a + broadcast; an expiry is a denial decided by `"expiry"`. Pending rows are reloaded at init + with their timers, so a restart of this process or of a Session loses no request (AC8). + """ + use GenServer + + alias Trinity.Permissions + alias Trinity.Permissions.{Approval, Store} + + @default_expiry_ms 600_000 + @default_session_grant_ms 86_400_000 + + @spec start_link(keyword()) :: GenServer.on_start() + def start_link(opts), do: GenServer.start_link(__MODULE__, opts, name: __MODULE__) + + @doc "Creates a pending request; `opts`: `cwd:`, `risk:` (the tier by default)." + @spec request(String.t(), String.t(), map(), keyword()) :: + {:ok, Approval.t()} | {:error, term()} + def request(session_id, tool, args, opts \\ []), + do: GenServer.call(__MODULE__, {:request, session_id, tool, args, opts}) + + @doc "Decides a pending request (see `Trinity.Permissions.decide_request/3`)." + @spec decide(String.t(), Permissions.request_decision(), keyword()) :: + {:ok, Approval.t()} | {:error, term()} + def decide(id, decision, opts \\ []) when decision in [:once, :session, :always, :deny], + do: GenServer.call(__MODULE__, {:decide, id, decision, opts}) + + @doc "The configured expiry of a request, milliseconds." + @spec expiry_ms() :: pos_integer() + def expiry_ms, do: config(:expiry_ms, @default_expiry_ms) + + defp config(key, default), + do: Application.get_env(:trinity, :permissions, []) |> Keyword.get(key, default) + + ## GenServer + + @impl true + def init(_opts) do + timers = Map.new(Store.pending(), fn a -> {a.id, arm(a)} end) + {:ok, %{timers: timers}} + end + + @impl true + def handle_call({:request, session_id, tool, args, opts}, _from, state) do + now = DateTime.utc_now() + + attrs = %{ + session_id: session_id, + tool: tool, + args: args, + risk: Atom.to_string(Keyword.get(opts, :risk, Permissions.tier(tool))), + fingerprint: Permissions.fingerprint(session_id, tool, args, Keyword.get(opts, :cwd)), + expires_at: DateTime.add(now, expiry_ms(), :millisecond) + } + + case Store.insert_approval(attrs) do + {:ok, approval} -> + broadcast(:requested, approval) + {:reply, {:ok, approval}, put_in(state.timers[approval.id], arm(approval))} + + {:error, _} = error -> + {:reply, error, state} + end + end + + def handle_call({:decide, id, decision, opts}, _from, state) do + case Store.get_approval(id) do + %Approval{status: "pending"} = approval -> + {reply, state} = apply_decision(approval, decision, opts, state) + {:reply, reply, state} + + %Approval{status: status} -> + {:reply, {:error, {:already_decided, status}}, state} + + nil -> + {:reply, {:error, :not_found}, state} + end + end + + @impl true + def handle_info({:expire, id}, state) do + state = + case Store.get_approval(id) do + %Approval{status: "pending"} = approval -> + {_, state} = apply_decision(approval, :deny, [by: "expiry", status: "expired"], state) + state + + _ -> + state + end + + {:noreply, %{state | timers: Map.delete(state.timers, id)}} + end + + ## The decision, as data + + defp apply_decision(approval, decision, opts, state) do + now = DateTime.utc_now() + by = Keyword.get(opts, :by, "liveview") + + status = + Keyword.get(opts, :status, if(decision == :deny, do: "denied", else: "allowed")) + + with :ok <- side_effect(approval, decision, opts, now, by), + {:ok, decided} <- + Store.update_approval(approval, %{ + status: status, + decision: Atom.to_string(decision), + decided_at: now, + decided_by: by + }) do + broadcast(:decided, decided) + cancel(state.timers[approval.id]) + {{:ok, decided}, %{state | timers: Map.delete(state.timers, approval.id)}} + else + {:error, _} = error -> {error, state} + end + end + + # "Allow for this session" is a grant bound to the fingerprint with an expiry; "always + # allow" is a global rule with the pattern the user confirmed. Once and deny write no rule. + defp side_effect(approval, :session, _opts, now, by) do + Store.insert_rule(%{ + tool: approval.tool, + pattern: "fp:" <> approval.fingerprint, + decision: "allow", + scope: Permissions.scope(approval.session_id), + expires_at: + DateTime.add(now, config(:session_grant_ms, @default_session_grant_ms), :millisecond), + decided_by: by + }) + |> ok() + end + + defp side_effect(approval, :always, opts, _now, by) do + Store.insert_rule(%{ + tool: approval.tool, + pattern: Keyword.get(opts, :pattern, "*"), + decision: "allow", + scope: "global", + decided_by: by + }) + |> ok() + end + + defp side_effect(_approval, _decision, _opts, _now, _by), do: :ok + + defp ok({:ok, _}), do: :ok + defp ok({:error, _} = error), do: error + + defp arm(%Approval{id: id, expires_at: at}) do + ms = max(DateTime.diff(at, DateTime.utc_now(), :millisecond), 0) + Process.send_after(self(), {:expire, id}, ms) + end + + defp cancel(nil), do: :ok + defp cancel(ref), do: Process.cancel_timer(ref) + + defp broadcast(kind, %Approval{session_id: session_id} = approval) do + message = {:approval, kind, approval} + Phoenix.PubSub.broadcast(Trinity.PubSub, Permissions.topic(session_id), message) + Phoenix.PubSub.broadcast(Trinity.PubSub, Permissions.topic(:all), message) + end +end diff --git a/lib/trinity/permissions/policy.ex b/lib/trinity/permissions/policy.ex new file mode 100644 index 0000000..fc45937 --- /dev/null +++ b/lib/trinity/permissions/policy.ex @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.Policy do + @moduledoc """ + What decides a call. The implementation in force is `config :trinity, :permissions_policy` + (`Trinity.Permissions.Policy.Layered` by default); `Default` allows everything and exists + for tests that want no gate. + """ + + @doc "The decision for a call. `opts`: `persona:`, `cwd:`." + @callback decide( + session_id :: String.t() | nil, + tool :: String.t(), + args :: map(), + opts :: keyword() + ) :: Trinity.Permissions.decision() + + defmodule Default do + @moduledoc "Allows everything. Slice 020's stub, kept for tests that want no gate." + @behaviour Trinity.Permissions.Policy + @impl true + def decide(_session_id, _tool, _args, _opts), do: :allow + end +end diff --git a/lib/trinity/permissions/policy/layered.ex b/lib/trinity/permissions/policy/layered.ex new file mode 100644 index 0000000..5d2761b --- /dev/null +++ b/lib/trinity/permissions/policy/layered.ex @@ -0,0 +1,95 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.Policy.Layered do + @moduledoc """ + The layered policy docs/07 specifies, in its order. Slice 021. + + 1. Session grants: `tool_permissions` rows scoped `session:` whose fingerprint pattern + is this call's fingerprint and whose expiry has not passed ("allow for this session"). + 2. The newest decided approval for this fingerprint in this session, if not yet consumed: + "allow once" allows and is consumed by the call; a denial denies and is consumed too, so + the same call asks again next time rather than staying refused. + 3. The persona's policy: `settings["permissions"]`, tool name to decision. + 4. Global rules: `tool_permissions` rows scoped `global`, an argument glob each. + 5. The default by tier (`config :trinity, :permissions, default:`), `:ask` for an unmapped + name. + + The fingerprint is re-derived here from the arguments actually passed (M2): a grant bound + to other arguments does not match, and the call asks again. + """ + @behaviour Trinity.Permissions.Policy + + alias Trinity.Permissions + alias Trinity.Permissions.{Rule, Store} + + @default %{read: :allow, network: :allow, write: :ask, exec: :ask, destructive: :ask} + + @impl true + def decide(session_id, tool, args, opts) do + now = DateTime.utc_now() + fp = Permissions.fingerprint(session_id, tool, args, Keyword.get(opts, :cwd)) + + with :next <- session_grants(session_id, tool, args, fp, now), + :next <- decided_approval(session_id, fp, now), + :next <- persona(Keyword.get(opts, :persona), tool), + :next <- global_rules(tool, args, fp, now) do + default(tool) + end + end + + defp session_grants(nil, _tool, _args, _fp, _now), do: :next + + defp session_grants(session_id, tool, args, fp, now) do + tool + |> Store.rules([Permissions.scope(session_id)], now) + |> first_match(args, fp) + end + + defp decided_approval(nil, _fp, _now), do: :next + + defp decided_approval(session_id, fp, now) do + case Store.decided_for(session_id, fp) do + [%{consumed_at: nil, status: "allowed", decision: "once"} = a | _] -> + if Store.consume_once(a, now), do: :allow, else: :next + + [%{consumed_at: nil, status: "denied"} = a | _] -> + if Store.consume_once(a, now), do: :deny, else: :next + + _ -> + :next + end + end + + defp persona(%{settings: %{"permissions" => perms}}, tool) when is_map(perms) do + case Map.get(perms, tool) do + "allow" -> :allow + "deny" -> :deny + "ask" -> :ask + _ -> :next + end + end + + defp persona(_, _), do: :next + + defp global_rules(tool, args, fp, now) do + tool |> Store.rules(["global"], now) |> first_match(args, fp) + end + + defp first_match(rules, args, fp) do + case Enum.find(rules, &Rule.matches?(&1.pattern, args, fp)) do + nil -> :next + %{decision: d} -> String.to_existing_atom(d) + end + end + + defp default(tool) do + defaults = + Application.get_env(:trinity, :permissions, []) + |> Keyword.get(:default, @default) + + case Permissions.tier(tool) do + :ask -> :ask + tier -> Map.get(defaults, tier, :ask) + end + end +end diff --git a/lib/trinity/permissions/rule.ex b/lib/trinity/permissions/rule.ex new file mode 100644 index 0000000..4552938 --- /dev/null +++ b/lib/trinity/permissions/rule.ex @@ -0,0 +1,93 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.Rule do + @moduledoc """ + A row of `tool_permissions` (slice 021): a rule (`global` or `persona:`, an argument + glob) or a session grant (`session:`, a fingerprint pattern `fp:`, an expiry). + + The pattern language: `*` matches any arguments; `=` matches when the argument + `key`, as text, matches the glob (`*` any run within a path segment, `**` across segments, + `?` one character); a trailing `*` on a command is the prefix rule docs/07 asks for. Regex + is not accepted from the UI; a hand-edited row may carry `re:`. + """ + use Ecto.Schema + import Ecto.Changeset + + @primary_key {:id, Trinity.UUID, autogenerate: true} + @timestamps_opts [type: :utc_datetime_usec] + + @decisions ~w(allow deny ask) + + @type t :: %__MODULE__{} + + schema "tool_permissions" do + field :tool, :string + field :pattern, :string, default: "*" + field :decision, :string + field :scope, :string, default: "global" + field :expires_at, :utc_datetime_usec + field :decided_by, :string + timestamps() + end + + @doc false + @spec changeset(t(), map()) :: Ecto.Changeset.t() + def changeset(rule, attrs) do + rule + |> cast(attrs, [:tool, :pattern, :decision, :scope, :expires_at, :decided_by]) + |> validate_required([:tool, :pattern, :decision, :scope]) + |> validate_inclusion(:decision, @decisions) + |> validate_format(:scope, ~r/^(global|session:.+|persona:.+)$/) + |> validate_change(:pattern, fn :pattern, p -> + if valid_pattern?(p), + do: [], + else: [pattern: "is not `*`, `key=glob`, `fp:` or `re:`"] + end) + end + + @doc "True when the arguments match the pattern (the fingerprint form takes the call's fingerprint)." + @spec matches?(String.t(), map(), String.t() | nil) :: boolean() + def matches?("*", _args, _fingerprint), do: true + def matches?("fp:" <> hex, _args, fingerprint), do: hex == fingerprint + + def matches?("re:" <> re, args, _fingerprint) do + case Regex.compile(re) do + {:ok, regex} -> Enum.any?(args, fn {_k, v} -> Regex.match?(regex, to_string(v)) end) + _ -> false + end + end + + def matches?(pattern, args, _fingerprint) do + case String.split(pattern, "=", parts: 2) do + [key, glob] when is_map_key(args, key) -> + Regex.match?(glob_to_regex(glob), to_string(args[key])) + + _ -> + false + end + end + + @doc "True for a pattern the changeset accepts." + @spec valid_pattern?(term()) :: boolean() + def valid_pattern?("*"), do: true + def valid_pattern?("fp:" <> hex), do: String.match?(hex, ~r/^[0-9a-f]{64}$/) + def valid_pattern?("re:" <> re), do: match?({:ok, _}, Regex.compile(re)) + def valid_pattern?(p) when is_binary(p), do: match?([_, _], String.split(p, "=", parts: 2)) + def valid_pattern?(_), do: false + + @doc "A glob as a regex: `**` any run, `*` any run without a separator, `?` one character." + @spec glob_to_regex(String.t()) :: Regex.t() + def glob_to_regex(glob) do + source = + glob + |> String.split(~r/(\*\*|\*|\?)/, include_captures: true, trim: true) + |> Enum.map_join(fn + "**" -> ".*" + "*" -> "[^/]*" + "?" -> "." + literal -> Regex.escape(literal) + end) + + Regex.compile!("^" <> source <> "$") + end +end diff --git a/lib/trinity/permissions/store.ex b/lib/trinity/permissions/store.ex new file mode 100644 index 0000000..df16076 --- /dev/null +++ b/lib/trinity/permissions/store.ex @@ -0,0 +1,113 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.Store do + @moduledoc false + # Every read and write of `tool_permissions` and `approvals`. Inside the Permissions + # boundary; nothing outside calls it. + + import Ecto.Query + + alias Trinity.Permissions.{Approval, Rule} + alias Trinity.Repo + + ## Rules and grants + + @spec insert_rule(map()) :: {:ok, Rule.t()} | {:error, Ecto.Changeset.t()} + def insert_rule(attrs), do: %Rule{} |> Rule.changeset(attrs) |> Repo.insert() + + @spec delete_rule(String.t()) :: :ok | {:error, :not_found} + def delete_rule(id) do + case Repo.get(Rule, id) do + nil -> {:error, :not_found} + rule -> Repo.delete!(rule) && :ok + end + end + + @doc "Unexpired rules for a tool in the given scopes, newest first." + @spec rules(String.t(), [String.t()], DateTime.t()) :: [Rule.t()] + def rules(tool, scopes, now) do + Repo.all( + from r in Rule, + where: r.tool == ^tool and r.scope in ^scopes, + where: is_nil(r.expires_at) or r.expires_at > ^now, + order_by: [desc: r.inserted_at] + ) + end + + @spec list_rules(keyword()) :: [Rule.t()] + def list_rules(opts) do + query = from r in Rule, order_by: [desc: r.inserted_at] + + query = + case Keyword.get(opts, :scope) do + nil -> query + scope -> from r in query, where: r.scope == ^scope + end + + Repo.all(query) + end + + ## Approvals + + @spec insert_approval(map()) :: {:ok, Approval.t()} | {:error, Ecto.Changeset.t()} + def insert_approval(attrs), + do: %Approval{} |> Approval.request_changeset(attrs) |> Repo.insert() + + @spec get_approval(String.t()) :: Approval.t() | nil + def get_approval(id), do: Repo.get(Approval, id) + + @spec update_approval(Approval.t(), map()) :: {:ok, Approval.t()} | {:error, Ecto.Changeset.t()} + def update_approval(approval, attrs), + do: approval |> Approval.decide_changeset(attrs) |> Repo.update() + + @doc "Marks a once approval consumed, if it was not; returns whether this call consumed it." + @spec consume_once(Approval.t(), DateTime.t()) :: boolean() + def consume_once(%Approval{id: id}, now) do + {n, _} = + Repo.update_all( + from(a in Approval, where: a.id == ^id and is_nil(a.consumed_at)), + set: [consumed_at: now] + ) + + n == 1 + end + + @spec pending() :: [Approval.t()] + def pending, + do: Repo.all(from a in Approval, where: a.status == "pending", order_by: a.inserted_at) + + @spec pending_for(String.t()) :: [Approval.t()] + def pending_for(session_id) do + Repo.all( + from a in Approval, + where: a.session_id == ^session_id and a.status == "pending", + order_by: a.inserted_at + ) + end + + @doc "Decided approvals for a fingerprint in a session, newest first." + @spec decided_for(String.t(), String.t()) :: [Approval.t()] + def decided_for(session_id, fingerprint) do + Repo.all( + from a in Approval, + where: a.session_id == ^session_id and a.fingerprint == ^fingerprint, + where: a.status in ["allowed", "denied"], + order_by: [desc: a.decided_at] + ) + end + + @spec list_approvals(keyword()) :: [Approval.t()] + def list_approvals(opts) do + limit = Keyword.get(opts, :limit, 200) + + query = from a in Approval, order_by: [desc: a.inserted_at], limit: ^limit + + query = + case Keyword.get(opts, :session_id) do + nil -> query + id -> from a in query, where: a.session_id == ^id + end + + Repo.all(query) + end +end diff --git a/lib/trinity/sessions/session.ex b/lib/trinity/sessions/session.ex index 109b041..a63c543 100644 --- a/lib/trinity/sessions/session.ex +++ b/lib/trinity/sessions/session.ex @@ -5,8 +5,9 @@ defmodule Trinity.Sessions.Session do One conversation, one `gen_statem`. Slice 012. States: `idle`, `thinking` (a model call streaming in a Task), `tool_wait` (tool calls running - in a Task), `approval_wait` and `compacting` (present for the machine's shape; nothing enters - them until slices 021 and 023), `error` (a failed turn, recorded, then back to `idle`). + in a Task), `approval_wait` (slice 021: calls the gate holds until the owner decides), + `compacting` (present for the machine's shape; nothing enters it until slice 023), `error` (a + failed turn, recorded, then back to `idle`). Rules this process keeps: every durable change is a row before it is a broadcast; the model and the tools run in Tasks under the session's own supervisor and talk back only by message; @@ -75,6 +76,8 @@ defmodule Trinity.Sessions.Session do session -> Process.flag(:trap_exit, true) + # Slice 021: the gate's decisions for this session's requests arrive here. + :ok = Trinity.Permissions.subscribe(session_id) {:ok, task_sup} = Task.Supervisor.start_link() data = %State{id: session_id, session: session, turn: nil, task_sup: task_sup} {:ok, :idle, data, [{:next_event, :internal, :rehydrate}]} @@ -151,7 +154,7 @@ defmodule Trinity.Sessions.Session do end def handle_event({:call, from}, :cancel, state, %State{} = data) - when state in [:thinking, :tool_wait] do + when state in [:thinking, :tool_wait, :approval_wait] do kill_task(data) data = flush_deltas(data) data = persist_final(data, %{"interrupted" => true}) @@ -178,23 +181,55 @@ defmodule Trinity.Sessions.Session do def handle_event(:info, :coalesce, :thinking, data), do: {:keep_state, flush_deltas(%{data | turn: %{data.turn | coalesce_timer: nil}})} - # Tool results arrive from the tool Task. + # Tool results arrive from the tool Task. A result that asks for an approval (slice 021) + # holds its call: the row is the gate's, the Session waits in approval_wait, and the held + # calls run again once every decision is in. def handle_event( :info, {:tools_done, ref, results}, :tool_wait, %State{turn: %{ref: ref}} = data ) do - data = record_tool_results(data, results) - turn = %{data.turn | pending: [], turns: data.turn.turns + 1} + {held, done} = + Enum.split_with(results, &match?({_, {:error, {:approval_required, _}, _}}, &1)) + + data = record_tool_results(data, done) + + case held do + [] -> + next_turn(data) + + _ -> + awaiting = + Map.new(held, fn {call, {:error, {:approval_required, id}, _}} -> {id, call} end) + + {:next_state, :approval_wait, + %{data | turn: %{data.turn | awaiting: awaiting, task: nil}}} + end + end + + def handle_event( + :info, + {:approval, :decided, %{id: id}}, + :approval_wait, + %State{turn: %{awaiting: awaiting}} = data + ) + when is_map_key(awaiting, id) do + # A decided request is still a held call: whether it runs or is refused is the policy's + # answer at execution, where the fingerprint is re-derived. + {call, rest} = Map.pop(awaiting, id) + turn = %{data.turn | awaiting: rest, held: data.turn.held ++ [call]} data = %{data | turn: turn} - case Caps.check(turn) do - :ok -> {:next_state, :thinking, start_model_call(data)} - {:cap, reason} -> cap_reached(data, reason) + if rest == %{} do + {:next_state, :tool_wait, start_tools(data, turn.held)} + else + {:keep_state, data} end end + def handle_event(:info, {:approval, _, _}, _state, _data), do: :keep_state_and_data + # The Task died: a crash is an error turn, an ordinary exit after its message is nothing. def handle_event( :info, @@ -411,21 +446,44 @@ defmodule Trinity.Sessions.Session do end end - defp start_tools(%State{id: id, task_sup: sup, turn: turn} = data) do + # After the tool rows: the next model call, or the cap. + defp next_turn(%State{turn: turn} = data) do + turn = %{turn | pending: [], held: [], turns: turn.turns + 1} + data = %{data | turn: turn} + + case Caps.check(turn) do + :ok -> {:next_state, :thinking, start_model_call(data)} + {:cap, reason} -> cap_reached(data, reason) + end + end + + defp start_tools(%State{turn: turn} = data), do: start_tools(data, turn.pending) + + defp start_tools(%State{id: id, session: session, task_sup: sup, turn: turn} = data, calls) do ref = make_ref() me = self() - calls = turn.pending + persona = session.persona_id && Store.get_persona(session.persona_id) + context = %{session_id: id, caller: id, persona: persona} # Slice 020: the turn's calls run at once through the runner in force. %Task{pid: pid} = Task.Supervisor.async_nolink(sup, fn -> - results = ToolRunner.run_all(calls, %{session_id: id, caller: id}) + results = ToolRunner.run_all(calls, context) send(me, {:tools_done, ref, results}) end) %{ data - | turn: %{turn | ref: ref, task: pid, draft_id: nil, buffer: [], text: "", finish: nil} + | turn: %{ + turn + | ref: ref, + task: pid, + held: [], + draft_id: nil, + buffer: [], + text: "", + finish: nil + } } end diff --git a/lib/trinity/sessions/state.ex b/lib/trinity/sessions/state.ex index 91d67bf..539c108 100644 --- a/lib/trinity/sessions/state.ex +++ b/lib/trinity/sessions/state.ex @@ -5,7 +5,8 @@ defmodule Trinity.Sessions.State do A Session's in-memory data, rebuilt from the database on init. Slice 012. Only the active turn lives here; everything durable is a row. A grant, an approval or a pending tool call never survives a restart, because none is written here from anywhere but the turn in flight, and a - fresh init starts with `turn` empty (AC9). + fresh init starts with `turn` empty (AC9). `awaiting` (slice 021) maps a pending approval's id + to the call it holds while the Session sits in `approval_wait`; the approval itself is a row. """ alias Trinity.Sessions.SessionRow @@ -26,7 +27,9 @@ defmodule Trinity.Sessions.State do tokens: non_neg_integer(), sentinel: [map()], coalesce_timer: reference() | nil, - surface: %{String.t() => String.t()} + surface: %{String.t() => String.t()}, + awaiting: %{String.t() => map()}, + held: [map()] } @type t :: %__MODULE__{ @@ -57,7 +60,9 @@ defmodule Trinity.Sessions.State do tokens: 0, sentinel: [], coalesce_timer: nil, - surface: %{} + surface: %{}, + awaiting: %{}, + held: [] } end end diff --git a/lib/trinity/tools/registry.ex b/lib/trinity/tools/registry.ex index 4931bd2..739d2a2 100644 --- a/lib/trinity/tools/registry.ex +++ b/lib/trinity/tools/registry.ex @@ -102,15 +102,23 @@ defmodule Trinity.Tools.Registry do config = Keyword.merge(Application.get_env(:trinity, :tools, []), opts) toolsets = Keyword.get(config, :toolsets, %{}) - for module <- Keyword.get(config, :modules, []) do - case admit(module, :core, toolsets) do - {:ok, entry} -> - :ets.insert(table, {entry.name, entry}) - - {:error, reason} -> - raise ArgumentError, "tool #{inspect(module)} refused: #{inspect(reason)}" + entries = + for module <- Keyword.get(config, :modules, []) do + case admit(module, :core, toolsets) do + {:ok, entry} -> + :ets.insert(table, {entry.name, entry}) + entry + + {:error, reason} -> + raise ArgumentError, "tool #{inspect(module)} refused: #{inspect(reason)}" + end end - end + + # Slice 021: the core tools' declared risks are the permission tiers, handed over here + # and nowhere else; a dynamic tool never reaches this line. Only the registry in the + # application tree writes them (a test's second registry would overwrite the table). + if table == @table, + do: Trinity.Permissions.put_core_tiers(Map.new(entries, &{&1.name, &1.risk})) {:ok, %{toolsets: toolsets}} end diff --git a/lib/trinity/tools/runner.ex b/lib/trinity/tools/runner.ex index bc7e7f5..badc185 100644 --- a/lib/trinity/tools/runner.ex +++ b/lib/trinity/tools/runner.ex @@ -74,17 +74,29 @@ defmodule Trinity.Tools.Runner do defp execute(%{name: name, args: args}, ctx) do with {:ok, entry} <- Registry.lookup(name), {:ok, args} <- validate(entry, args), - :allow <- Permissions.decide(ctx.session_id, name, args), + :allow <- + Permissions.decide(ctx.session_id, name, args, persona: ctx.persona, cwd: ctx.cwd), {:ok, %Result{} = result} <- call_tool(entry, args, ctx) do {:ok, Result.cap(result), meta(name)} else {:error, reason} -> {:error, reason, meta(name)} :deny -> {:error, :denied, meta(name)} - :ask -> {:error, :approval_required, meta(name)} + :ask -> {:error, ask(ctx, name, args), meta(name)} other -> {:error, {:bad_return, other}, meta(name)} end end + # An :ask with a session to ask becomes a pending approval (a row, then a broadcast) the + # Session waits on; without a session there is nobody to ask, and the call is refused. + defp ask(%Context{session_id: nil}, _name, _args), do: :approval_required + + defp ask(%Context{session_id: sid, cwd: cwd}, name, args) do + case Permissions.request_approval(sid, name, args, cwd: cwd) do + {:ok, approval} -> {:approval_required, approval.id} + {:error, reason} -> {:request_failed, reason} + end + end + defp validate(%{module: module}, args) do case Schema.validate(module.schema(), args) do {:ok, args} -> {:ok, args} diff --git a/lib/trinity_web/components/approval_components.ex b/lib/trinity_web/components/approval_components.ex new file mode 100644 index 0000000..2c28e51 --- /dev/null +++ b/lib/trinity_web/components/approval_components.ex @@ -0,0 +1,155 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule TrinityWeb.ApprovalComponents do + @moduledoc """ + The approval card and its neighbours. Slice 021, in the vocabulary slice 013 decided. + + A card shows the tool, its risk as a badge, the arguments pretty-printed, a plain sentence + about what `:exec` and `:destructive` mean, and four buttons. The buttons push events the + page turns into `Trinity.Permissions.decide_request/3`; nothing on the card carries authority + of its own (M7). "Always allow" shows the pattern that would be written, pre-filled from the + arguments and editable, so what is granted is what the person read. + """ + use Phoenix.Component + use Gettext, backend: TrinityWeb.Gettext + + import TrinityWeb.CoreComponents, only: [icon: 1] + + alias Trinity.Permissions.Approval + + @doc "One pending request." + attr :approval, Approval, required: true + + attr :pattern, :string, + default: nil, + doc: "the always-allow pattern as edited; the suggestion by default" + + def approval_card(assigns) do + assigns = assign(assigns, :pattern, assigns.pattern || suggest_pattern(assigns.approval)) + + ~H""" + + """ + end + + attr :id, :string, required: true + attr :decision, :string, required: true + attr :label, :string, required: true + attr :primary, :boolean, default: false + attr :danger, :boolean, default: false + + defp decision_button(assigns) do + ~H""" + + """ + end + + @doc "The risk tier as a badge." + attr :risk, :string, required: true + + def risk_badge(assigns) do + ~H""" + + {@risk} + + """ + end + + @doc "The header's pending indicator: nothing, or a count linking to the audit page." + attr :count, :integer, required: true + + def pending_indicator(assigns) do + ~H""" + <.link + :if={@count > 0} + id="pending-approvals" + navigate="/permissions" + class="flex items-center gap-1 rounded-pill bg-warning/20 px-2 py-0.5 text-meta text-warning" + title={gettext("Approvals waiting")} + > + <.icon name="hero-hand-raised-micro" class="size-4" /> {@count} + + """ + end + + @doc "The pattern proposed for always-allow: the first path-like argument as a glob on its directory, else `*`." + @spec suggest_pattern(Approval.t()) :: String.t() + def suggest_pattern(%Approval{args: args}) do + case Enum.find(args, fn {_k, v} -> is_binary(v) and String.starts_with?(v, "/") end) do + {key, path} -> "#{key}=#{Path.dirname(path)}/*" + nil -> "*" + end + end + + defp danger("exec"), + do: + gettext("This runs a program on your machine. Approve only if you understand the command.") + + defp danger("destructive"), + do: gettext("This can delete or overwrite data. Approve only if you meant it.") + + defp danger(_), do: "" +end diff --git a/lib/trinity_web/live/permissions_live.ex b/lib/trinity_web/live/permissions_live.ex new file mode 100644 index 0000000..eefe4a8 --- /dev/null +++ b/lib/trinity_web/live/permissions_live.ex @@ -0,0 +1,187 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule TrinityWeb.PermissionsLive do + @moduledoc """ + `/permissions`: the audit. Slice 021. Every request with its decision, decider and time, + pending ones first and decidable here too; then the rules and grants, each revocable. + Everything this page does is `Trinity.Permissions.decide_request/3` or `revoke_rule/1`. + """ + use TrinityWeb, :live_view + + import TrinityWeb.ApprovalComponents + + alias Trinity.Permissions + alias Trinity.Permissions.Approval + + @impl true + def mount(_params, _session, socket) do + if connected?(socket), do: :ok = Permissions.subscribe(:all) + {:ok, socket |> assign(page_title: gettext("Permissions"), patterns: %{}) |> load()} + end + + defp load(socket) do + assign(socket, + pending: Permissions.pending(:all), + approvals: Permissions.list_approvals(limit: 200), + rules: Permissions.list_rules() + ) + end + + @impl true + def handle_info({:approval, _kind, %Approval{}}, socket), do: {:noreply, load(socket)} + def handle_info(_other, socket), do: {:noreply, socket} + + @impl true + def handle_event("approval_decide", %{"id" => id, "decision" => decision}, socket) + when decision in ["once", "session", "always", "deny"] do + opts = + if decision == "always", do: [pattern: Map.get(socket.assigns.patterns, id, "*")], else: [] + + case Permissions.decide_request(id, String.to_existing_atom(decision), opts) do + {:ok, _} -> + {:noreply, load(socket)} + + {:error, reason} -> + {:noreply, + put_flash(socket, :error, gettext("Not decided: %{reason}", reason: inspect(reason)))} + end + end + + def handle_event("approval_pattern", %{"approval_id" => id, "pattern" => pattern}, socket), + do: {:noreply, assign(socket, patterns: Map.put(socket.assigns.patterns, id, pattern))} + + def handle_event("revoke", %{"id" => id}, socket) do + _ = Permissions.revoke_rule(id) + {:noreply, load(socket)} + end + + def handle_event("new_session", _params, socket), + do: {:noreply, TrinityWeb.SessionLive.Index.new_session(socket)} + + def handle_event("cancel", _params, socket), do: {:noreply, socket} + + @impl true + def render(assigns) do + ~H""" + + <:bar> + {gettext("Permissions")} + <.pending_indicator count={length(@pending)} /> + +
+
+

{gettext("Waiting for a decision")}

+ <.approval_card :for={a <- @pending} approval={a} pattern={Map.get(@patterns, a.id)} /> +
+ +
+

{gettext("Decisions")}

+

{gettext("No request has been made yet.")}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{gettext("When")}{gettext("Tool")}{gettext("Risk")}{gettext("Arguments")}{gettext("Decision")}{gettext("By")}
+ {stamp(a.decided_at || a.inserted_at)} + {a.tool}<.risk_badge risk={a.risk} /> +
{Jason.encode!(a.args)}
+
+ + {a.status}{if a.decision, do: " · " <> a.decision} + + {a.decided_by}
+
+ +
+

{gettext("Rules and grants")}

+

+ {gettext("None. Always allow and allow for this session write one.")} +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{gettext("Tool")}{gettext("Pattern")}{gettext("Decision")}{gettext("Scope")}{gettext("Expires")}
{r.tool} +
{r.pattern}
+
{r.decision}{r.scope}{stamp(r.expires_at)} + +
+
+
+
+ """ + end + + defp stamp(nil), do: "" + defp stamp(%DateTime{} = at), do: Calendar.strftime(at, "%Y-%m-%d %H:%M") <> " UTC" +end diff --git a/lib/trinity_web/live/session_live/show.ex b/lib/trinity_web/live/session_live/show.ex index c28fc25..9128331 100644 --- a/lib/trinity_web/live/session_live/show.ex +++ b/lib/trinity_web/live/session_live/show.ex @@ -18,9 +18,12 @@ defmodule TrinityWeb.SessionLive.Show do """ use TrinityWeb, :live_view + import TrinityWeb.ApprovalComponents import TrinityWeb.ChatComponents alias Trinity.LLM + alias Trinity.Permissions + alias Trinity.Permissions.Approval alias Trinity.Sessions alias Trinity.Sessions.Message @@ -48,7 +51,10 @@ defmodule TrinityWeb.SessionLive.Show do last_seq: 0, last_user_message: nil, models: LLM.models(), - default_model: LLM.default_model() + default_model: LLM.default_model(), + approvals: [], + patterns: %{}, + pending_count: 0 ) |> stream_configure(:messages, dom_id: &"message-#{&1.id}") |> stream(:messages, []) @@ -62,6 +68,9 @@ defmodule TrinityWeb.SessionLive.Show do defp connect(%{assigns: %{session: session}} = socket) do id = session.id :ok = Sessions.subscribe(id) + # Slice 021: this session's requests, and the count of everyone's for the header. + :ok = Permissions.subscribe(id) + :ok = Permissions.subscribe(:all) {status, text} = case Sessions.ensure_started(id) do @@ -85,6 +94,10 @@ defmodule TrinityWeb.SessionLive.Show do socket |> assign(status: status, draft: text, last_seq: last_seq) + |> assign( + approvals: Permissions.pending(id), + pending_count: length(Permissions.pending(:all)) + ) |> assign( last_user_message: done |> Enum.filter(&(&1.role == "user")) |> List.last() |> content() ) @@ -142,6 +155,34 @@ defmodule TrinityWeb.SessionLive.Show do def handle_event("new_session", _params, socket), do: {:noreply, TrinityWeb.SessionLive.Index.new_session(socket)} + # Slice 021: a button is a request for a decision; the record is the gate's. + def handle_event("approval_decide", %{"id" => id, "decision" => decision}, socket) + when decision in ["once", "session", "always", "deny"] do + opts = + if decision == "always", + do: [pattern: Map.get(socket.assigns.patterns, id) || suggested(socket, id)], + else: [] + + case Permissions.decide_request(id, String.to_existing_atom(decision), opts) do + {:ok, _} -> + {:noreply, socket} + + {:error, reason} -> + {:noreply, + put_flash(socket, :error, gettext("Not decided: %{reason}", reason: inspect(reason)))} + end + end + + def handle_event("approval_pattern", %{"approval_id" => id, "pattern" => pattern}, socket), + do: {:noreply, assign(socket, patterns: Map.put(socket.assigns.patterns, id, pattern))} + + defp suggested(socket, id) do + case Enum.find(socket.assigns.approvals, &(&1.id == id)) do + nil -> "*" + approval -> suggest_pattern(approval) + end + end + defp send_message(socket, content) do id = socket.assigns.session.id @@ -178,8 +219,31 @@ defmodule TrinityWeb.SessionLive.Show do {:noreply, apply_event(event, socket)} end + def handle_info({:approval, kind, %Approval{} = approval}, socket) do + socket = + if approval.session_id == socket.assigns.session.id, + do: apply_approval(kind, approval, socket), + else: socket + + {:noreply, assign(socket, pending_count: length(Permissions.pending(:all)))} + end + def handle_info(_other, socket), do: {:noreply, socket} + # The page hears each request twice (the session's topic and everyone's); one card. + defp apply_approval(:requested, approval, socket) do + if Enum.any?(socket.assigns.approvals, &(&1.id == approval.id)), + do: socket, + else: assign(socket, approvals: socket.assigns.approvals ++ [approval]) + end + + defp apply_approval(:decided, approval, socket) do + assign(socket, + approvals: Enum.reject(socket.assigns.approvals, &(&1.id == approval.id)), + patterns: Map.delete(socket.assigns.patterns, approval.id) + ) + end + defp apply_event({:user_message, %Message{} = m}, socket) do socket |> insert(m) @@ -243,6 +307,7 @@ defmodule TrinityWeb.SessionLive.Show do {@session.title || gettext("Untitled session")} <.status_pill status={@status} /> <.model_picker models={@models} value={@session.model} default={@default_model} /> + <.pending_indicator count={@pending_count} />
+ <.approval_card :for={a <- @approvals} approval={a} pattern={Map.get(@patterns, a.id)} /> <.banner kind={@banner} /> <.composer status={@status} disabled={@status != :idle} />
diff --git a/lib/trinity_web/router.ex b/lib/trinity_web/router.ex index 6e7cf67..79b9d19 100644 --- a/lib/trinity_web/router.ex +++ b/lib/trinity_web/router.ex @@ -25,6 +25,8 @@ defmodule TrinityWeb.Router do live_session :chat do live "/", SessionLive.Index, :index live "/s/:id", SessionLive.Show, :show + # Slice 021: the approvals audit and the rules. + live "/permissions", PermissionsLive, :index end end diff --git a/priv/repo/migrations/20260920200000_create_permissions.exs b/priv/repo/migrations/20260920200000_create_permissions.exs new file mode 100644 index 0000000..7c20fdd --- /dev/null +++ b/priv/repo/migrations/20260920200000_create_permissions.exs @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Repo.Migrations.CreatePermissions do + @moduledoc """ + Slice 021. `tool_permissions` (rules and grants) and `approvals` (the audit of every request + and its decision) per docs/05 and docs/07. A session's grants carry `scope` `session:` + and a fingerprint pattern; a rule carries `global` or `persona:` and an argument glob. + """ + use Ecto.Migration + + def change do + create table(:tool_permissions, primary_key: false) do + add :id, :binary_id, primary_key: true + add :tool, :string, null: false + add :pattern, :string, null: false, default: "*" + add :decision, :string, null: false + add :scope, :string, null: false, default: "global" + add :expires_at, :utc_datetime_usec + add :decided_by, :string + timestamps(type: :utc_datetime_usec) + end + + create index(:tool_permissions, [:tool, :scope]) + create index(:tool_permissions, [:scope]) + + create table(:approvals, primary_key: false) do + add :id, :binary_id, primary_key: true + + add :session_id, references(:sessions, type: :binary_id, on_delete: :delete_all), + null: false + + add :tool, :string, null: false + add :args, :map, null: false, default: %{} + add :risk, :string, null: false + add :fingerprint, :string, null: false + add :status, :string, null: false, default: "pending" + add :decision, :string + add :decided_at, :utc_datetime_usec + add :decided_by, :string + add :consumed_at, :utc_datetime_usec + add :expires_at, :utc_datetime_usec, null: false + timestamps(type: :utc_datetime_usec) + end + + create index(:approvals, [:session_id, :status]) + create index(:approvals, [:status, :expires_at]) + create index(:approvals, [:fingerprint]) + end +end diff --git a/scripts/dev_chat_on_test_registry.sh b/scripts/dev_chat_on_test_registry.sh new file mode 100755 index 0000000..1b641c1 --- /dev/null +++ b/scripts/dev_chat_on_test_registry.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +# The chat on the test registry (the fake provider, the test tools, a scripted turn that calls +# the write-risk tool) for the slice 021 screenshots and the owner's manual queue. The test +# environment's Repo without its sandbox pool and with the check_origin off, the application +# started by hand; the port is printed as PORT=. Run `mix assets.build` first, and remove +# any stale `priv/static/assets/**/*.gz` (Plug.Static serves the gzip in this environment). +# Its database is trinity_screenshots.db, never the test suite's: rows written outside the +# sandbox broke four usage_events tests once (slice 021 NOTES). +cd "$(dirname "$0")/.." +export MIX_ENV=test +exec systemd-run --user --scope -p MemoryMax=32G --quiet -- mix run --no-start --no-halt -e ' +repo = Application.get_env(:trinity, Trinity.Repo) |> Keyword.delete(:pool) |> Keyword.put(:database, "trinity_screenshots.db") +Application.put_env(:trinity, Trinity.Repo, repo) +endpoint = Application.get_env(:trinity, TrinityWeb.Endpoint) |> Keyword.put(:check_origin, false) +Application.put_env(:trinity, TrinityWeb.Endpoint, endpoint) +Application.put_env(:trinity, :permissions, expiry_ms: 600_000, session_grant_ms: 3_600_000) +{:ok, _} = Application.ensure_all_started(:trinity) +call = [{:text_delta, "I will save that as a note. "}, {:sleep, 300}, {:tool_call_start, "c1", "write_note"}, {:tool_call_end, "c1", %{"path" => "/home/me/notes/today.md", "text" => "Buy oat milk, call the dentist, finish the slice."}}, {:usage, %{input_tokens: 12, output_tokens: 20}}, {:done, :tool_calls}] +final = fn text -> Enum.flat_map(String.split(text), &[{:text_delta, &1 <> " "}, {:sleep, 40}]) ++ [{:usage, %{input_tokens: 40, output_tokens: 30}}, {:done, :stop}] end +Trinity.LLM.Providers.Fake.scripts([ + call, + final.("Saved. The note is at **/home/me/notes/today.md** with three items: oat milk, the dentist, and the slice."), + call, + final.("Understood, I did not write the note. Tell me if you change your mind.") +]) +{:ok, {_, port}} = TrinityWeb.Endpoint.server_info(:http) +IO.puts("PORT=#{port}") +' diff --git a/slices/021-permission-gate/proof/ac2-allow-once-final.png b/slices/021-permission-gate/proof/ac2-allow-once-final.png new file mode 100644 index 0000000000000000000000000000000000000000..f4759e7dac5d23edaeb627acef4a7d0df5b67853 GIT binary patch literal 52410 zcmb@tWmH^E^XN-L2q6Rr5ZnR;mkFN16WkNrNg%in3_cLtA-E0`+}%AvgS!M62=0Ro z&M=4PdH?TS=gVE|-gVA=sx@ox?ylX{)m7EM4*#eshxeTFIR*v>o`SrzItIoQWekkR zSI-_l{DaszufxE2iJ>6Xnv1+1n#ib{y3>_-IF z`2RCvecZl2ZBEjJi1`o~p%QDeYCJ7{*{IDRT+^#A#igs(!6+o!od1UKbjaGu5)fCz z#N-9RvF3dO{8y)PjM(`Fh2bxfKos2=va?}8*VtHl)Y7WQ!nS|=tQ0bos;O+vzuc@b zOoEbEata?=*L)zcznWt zG|7861{j+iQ@2XIPcK^v@ro*JeXEAmop>Vd1O&V<%w1y6x}F*L4bff1p%DSQk=9G~&rB+v}k zUjXP?`v)r?|H@xcU0t2eM3G;Xg+c#8Rv9xZUc{X?Er;{lg{+-z|6Aqe=6HRoSSLHX zLp!?zd9$R%S1C(uq|c)2I3s8F&zaoibNShRPk7@s3EXn!LhYd%r;$glcc##*9>)hO z)sHXs3FKJ&dlu~T2*yvxsPldh*;z9gs_P(0=d!S%G%wn@&vq@&!<=H!!W?ZaSsJQIo?Ck`{yoXK)*j#!@X5v{<9UIX z+tjLh9auppO9z^KR+uNRV|>4(sZvVTBBhAO2?st+hPW;;KdQsr!WP;pxVFF95J*l+ zA@s!##m^hC%ASRaxbIY~o;61_BWq+SE8^adLbC&L3p-UQkxIuNc4*%ZDjo9RGz<*M zTA~PPH@6G^r}P9*qTQt#;^J)artT_>D}tk=q1ky)2xA255~HiDWp1gz2?mJ^n)a++ zjKAt<{VwcU^e0Y#JxuyVX<@8g6w=LX<3`W=xV?a9_eb^MVWZ`D*=8{p;r$61KY=V^ z-B%OENwxh#b|w{ASu>AVAZdBb^PPd0RxtAZZ40^JYhXj9Nz>r!;Jc@s%WVz~I%cEE zvn^`ma-CILi}=(iuJez>@vrABK7Z6PrwoXCMt8DuQns_$d^uIoxL^Bc6$I z|BzC^f5&3}rlP}Fb+4z#j>h`6Yz6f}>2NGFfgG{AuRBhR|0mn6cfF&qR;IvmP*VgG zZ?m!zWv=yYP#hb|$6OC5JcUD0VT-t$S3RxT4xtz+VIRF)&NVmTs488hu{Y?>z^5yR zr2(@qZE@k`GAcW!I8cfgBFrf@r!e+kR<b<<+MQr#-9#7Dfiuz&7;B}#c5<`JZ`{1cy_ih6@w#BJPL!hAJyrIU5ZTq*2<-OH~kRa80*s}=OY$%;%P+P3?^c9JL!KeG607Z;!O2&R%D!|IvA zB*zG|<&0LY#f7MmDi?B=qhd$ZA%pnL__=rj&8ESnh6_<+%ps=(xRiviQjN>%U|zGa@zWo(zw?5f<{3V%E$#Yp zB>?5#TL|;HM8y!Zs7_}F171!a-CN9=?d)p=ENw=;ht^n+xTnqBZ0`QZq~3Gcl*qu} zrjTcxZ;8!XOCmcnN-y|SEAjThJCb@4VpzegE}*w+<&M1+z_n|98j&6}vbMVIMqy<8 z1m#`MvcAV=wP}a9()w3stNp^wRUm7=_Vgs2l+XuOp2QowB zooT|e!>D5zWkxryEyLP_kVl#>AB4TbFQ?ojP^Mq#4>ou70#(%fDf)lpuW(%?*sLvQ zw7lkt)$Q3rwOCA4=5cE=OTnuzq)LuK^m-Zbe42*%WQ4YiJG?n$!vX{iqkMtw)U8&k zoYw5sn#@f4(f0_RuDxlB63*h1+40=LQERxe*dzY7F5QV>8e4R)VXG%vS9UVjy%E^=?=ZeH~DA`GxQD>2Xu@xUbZp~ zP4OoW@sfLs-1g~In;m3Qx4xPK`eAQg;h=aMkAxwuSf<%zCO$ks;Pu6!H^5?NJUcLU ztQH%;Crx7VSoS9|IZgoex7iADJT@c4S0@rQOX&4Sw!}}Os8!P?OK0wpXYVQ5pg?bK zlxtrMlxORNR*@;%$;wH~J4h-iB?&i3`-r05>)hvp!cq8R&Rj|&f7y!P)JT4!S`z|W z9urWAM*w;%VS61}p_WjrMtmWBz5Z+f%t%}quR2S{`+ErVU4yD`g5_#tAh+F!L>0tC zpFXw1eXV@Hw};g+SvI0!Q8D67f!fM@?P#txHHXA;lARpo+BdcSgOU5pxVql7=6uUM zyuI6<4zCb%ArZV1S%^BfuJ%&9N|fo`a;e|yFJB-M&@EX$8O_UQ18YAqef2&r(h}Rl zNnx_Ic2a%aR8R(8V#@Vq#Zi48`O-uv%{Yk^eYkgCU7#;ZWIj)}U+5VYZk&)r*=T;= z;^Dv#ea8<{{hktOSf*8Ys8?+TX3)`Q(ul#wgYF#VzudNDIW+7P7T)Y2;*4||@X492 z^qdJ+g70ozso2i4lstpeQ!#G>GV9*~SK9E_waf9exn3B>6_lEh%n})bAJ2Ugl47}G zC*cOM38|P4x6HJ%v){>k-Kf9>#Kz}F!Z$4QnWP=>g)fHT5ekDs4R1Pr;T3m4fzbs) z&dBFDP?EL9mGBMoH?n^14vyy_+G6P~q9z}czaT`Y^1ags>9X00(^Dpt6vIwVq5~*> zZsf`WaUfu=MKtmb&-kT_-6NVwn6VgSYs+qJhY#qg|J~7#tXPoaa1NR=dsM6|B=(GD zG)Ur&UQce#$BdHp!@NPZOsu@m^xnTRW{& zNVA>nmVmIUS5;?9hGyxYdGFh1 z0GuIYF~@PPJbcraC|qZHD>gG{C9PFShBLu4xLlv~dnfl=H@R*7TGq+ke_Zi!s) zG;ZM(Z0$q3Tj!tKu$vF}_fdPmPuJmUE2(qEXNygKzd?24Q9DWjd- zW}bmqDK~s>SITuN?|CG6_d2wmU7hcKmb04sHTpfp_xeJryqu|Ke`mfnvgM>Y5zHw2 z!Vh(>fLuY}cE&ow*Y>1c59Uwk&{y7#4o2r*g7ozMsrp+FK^L1nJXi(e=ZugbDs*3D z;f7z-cZ4@n5n1|_Y-_H{eZ`k@@2ff5!P0VjH#^VFsxATLeSv_Zl|)^O5ZBghG3T@I z#K-XY3FgCk1qIih_5!0mT8&Q)0p~_2t$#fD+@~@GlV3wvyb_)!ctxcN_v!dvGLE!q zwZnNpbKiLUjVD`)MVhZWT7GJkKxru)Pn^rOp$U~NH+M=Yqlv{xwN@Zo`>S}9GjN@c z&2%{qXbm9fS6;i`dzDm-T>6 zHSZgr<&ylhWqH z#4rhd1B5Ng>c3gb8(S`(oN0bOXc|z8V5?pO`UxEtRQ-gq%VxhwrRA}GZ?zni#BZGF z5zK8Q9@0}DsUJV+6%;fQuFpOd${i(?G_`5zLk#p*F=vibZM9qdJhR1Ao1+=EpE~|~ zb12Wnwl3!LjPub*8Rt%dN3elj$I{H$9GmTK9!|JtlyqO!OiFy+*NdgpA(GI99`H>~ ze)ee{SV=0OPSxzgwk)U1n_33965T$5tK7}0JZFw=fXXMnia?g&5$ERCm$$c(sBC(pxFq_JV8HE{k65+v2)&JH4N+*~6V)!Dy^$vBxHF-F?NK5m@T|2pS zzPoodsWh~VmFBnYJ=)&i9(e=Ee9NY_zau7QbB)wX53=9yBF(oUF=HSd%_tvyUTdte zj{vZJx{~3DR${#fH{d8#;*xXIog2{|PN zVNxZ2>ydn|kHv(!&E%{M_l;m6SY6y5t-X{x5}qbu`v-2Nz1Az16|Prf1*wtU+Y;en zF#Qq~A|kD~pYlwd%s+`VzP5Xr^1iLp^D6jT97FcQK)ISP>x(Y))b6*)X_`-^38!X6 zzRvcnLWC!Hxf$XNThWgadmyeJ^FhAQ-5-dqtV(T!GT^PQs;n5_H2QXhR*prEav)V= z(xc$Cbf8j=hhY4QMa`)F32gs!p>ePb!zZ%X&O3;L)2E5x`SV2w0`D_$CHDmbVX5l% z*v%0yyOPAgji>|)OxNx2D40)r>3I@8(CrNZxHW<4FFMipn~&E8P^c3c0-uI0rz{9; zyFc2y1C~i2GK4)_uC_@kaeoARO0k27oON8BLtR>B{hEc`9o){UD<@3+TCeW};PAdO z3DaxbwKA^lrD9Rdi=h>W2;t|iy57k}=b8-@j@H}G`Q4VUnY+5molq^hl48)lc`p;n zL(nDK@w74>3 z%7TA0eSW0;f`Uxcb89fL7+XWrRi6xCLWa|x&C!+!;_g!zC~+6?N}icCBq+_r!e7+3 z8~lEa?Y*+n`f7cHcuk3DXZ@^h=-Ts7c*ZQtt`RD+AbkGLr=o#G$#R((#-epIuIU7k zuWGT=61)s+G<_UyFm6Srh1}aQsXaT@vi6>nv7Cx3Ge{b#AbJesHp>22Iwj{;psu z`$`qOzz3;M4DT28@cpqq;b0&;77T%hgF)TT)(ZKJ?)3oMPcab30 z0vVF#B6ZR)e)N3W?c2z+um)d;b8HVsErI=(UOS)Rx=kUB$eY=@xkMP9heG4_T`~g# zhRRwG={*!P7TP0n>r? zCHP}6D0PSWy&tljtx=EDrM^xT$a>|GFZg%?wJpaowp;tybz;>o?drw^O*v;DLMiN@QGDU1WtaiGIj6R7a=wwE1Ee;7K55DI3{G2t)ci$x9(AC{ zFrSVQ8pn_fkOA?a_brVUa|d^a5aBQ0qY}6Z#^2F_U=g}+q!u4bYqRf(Yd5JFa?tHrhPyQ}KI&0blxw(zq{VlVf z!PAxPu+o8=kfSr{ykNnzBL&=jzn^$?6GwWmRQglfI7Vj^qYj6}(|uWLpAKyb|2d!ZxgY5w!oQmhk;(_pW)o zrPV13Y^0Dtf@HR1NHt0&OSo@DWv}Qv4_m!us4FmBL5~*5?c1;d4k?PED&8Tre0 zEB3Ni#Kfp3rDk3RRHiTpix`x=(2S@RG#{6n4&2udu75IDBgJpSeZpH^d?J+4$g+;$ za~C{v{U9h(*qIUaNe31g$M#BGgZKbC6ndO zW4PfaQF&yBaz+nBQ%-82BO!tcG&k3x3K_N*D*e$)wF?M}hgX8)s zQkWCr%lw9_6N8iuW2Ngg$NGH=%wLqbQjkbS=lF?Sz}OzAY4JKPVcbnr(otEM&J2iQ zynAv%oKU2NJyWzzh%Up$F;h^Bp#tVX_(Yo0>5#K4L zi|=gsQ_kz2AqB4${00vTt&B=vgHI51n|f7czvm%4<;Dzq+18$V1sS(|Pypgxyfr%& zCu@@gO4;(#7yhP&p4ft5ZF!_`va%UBAp1|kCpyC;sq+{Y1kpg!`aRLoTt|~G>(NyH zRRCKbA^3pr2Cx4NeLXyF+BZAUZYd`+QoC+k$YjspjY-4A@N^_eneuHIb*L8*E>7ce z-4JX})6YL+AKB*Rc=q{O17ij0hG@z0;M&`r=E+sckMNIyYeO-TETAB0~%2L@9ADqqYu z+Q_rMYIH~-Ezokgw5e{QZGK|pW@vixl^{RE&lXqMZxCb=f4q$Mc(EJLxW-BG!7y6A)xWiCYS_YeX~tzRMBwK54Po16RV)4vu3j zI`n5XnSb>!uqRy9x>V9+mGoRnjqGe)OqbJIILqnbj6zn|v$|QU4s;i;G^D51QMsMH zsNt>rK65qLR$*d((NdyndYz`g;*awP6)rGk%b2ZcsVwRFyPETxyD4jS7W3ncpM0>s z=^6f>Q}I>My@JvQ+u4FrV}9MuXT?~h5hlVM6B8VtPmxu4Q-z332}_yh);L}beQKZ1 zh8KJa7T%mMMeOab-8YNG_9{t>jo$|K3RTjG_~z8Kq+jROGdYp?mD7=MdY^wrreIf4 z?kPVlhLxS^1qTO1;BectExWDj^qHAKWrKyPThoV%!;{N)@MqMV+*ugt2HR}d46k=@ zWt8NSmiX>q6CBz+L;fO#0Mf`dvJgG6X9f)P#|;Y$?5(dWy9>CBy>}eQ>BZf}&n6s2 z;Z;0?e=_&TcqwV{nIBYXzM3>Q*-Qy(FhhE}z2p(-EWSu;cCSA@?Yrbv|1*LCMjQaw zIRF_Pt&_I6C|&!x0NfP8n?1>H;GT2fM4lj1V$ZQN?#=;;pT?(7YU)C*7I@(N!fqshV7b-cOYAah!5_ zRBcST(k2!ZXy9M#-mz5XP-@6%v4I;R-gz}^SElvKlW-$`Y#} z2kx_9IRXN#=p|M0=PZ7fR}>v~G`9>Gk|?V#Eq|Sw^5DwwtMp^jGR++1dHZ|FJqj=o zR=D{N*$je~7K#0;&)u|TpPkV0Y-FZe-&s8xwBnsM#KcY?GA(J_2^Uw>sRrqoq&#i2 zsh-`O`%qa}N~*JEt5?w;rM&y8*(NQcQoUeA-P-jUXhSpSTWpa-ZhM=i#nk_%TG0=n zBLt9B(N~Nawb^TiRwB#Gs9Bv)PLr#Fde>z$5M!>*kspJApCxYGS*^kbK+E$}1yuR{ zi?VY_JS-)fnS0p*&+CMVEQ+Uo_~%ysp%IUet3t`NL{H@XBv@r76CqN&ch1hIJ%-Xg zSA^9oNkbC#29T9{w=@1%u;i~*2W zylJ_ULu36~U7NaEHs!-2XXDn*plHrj~_Y4S0>hTp?vw!`L9n!g*uNE=%Rx7^5`=1&V9e>$E-C4~d^7v(b zkdobJ-J%ph2e|RgM*7xqO&#ybcMO1xT0X%X;|E`x;Ze?ho!l;#>*mS4Ca>!&_Wj>n zb2WGRmP13oC)ol5P)RY*H(h*GI+lxSg4)laBK*dWl;ToQxU1UzJNZ8`UJ!R zgprS+JowiV6gYUR>JPT>>Y&xvg9^1D5?gwtHOjeVw?ym*N?6Z6uM)%?Kartz9Siu zqd1?IbBSm0*1L{OY=;B|fwa8>KPlG-r$?{`e(*7(Au;y#MU}n@aYlNLE=5H-o9&=*-QQL96t1=)@qVclwD@%K@zN zNvAA&M{>l+39Gvo)3$NnSoaQQzj9}}KDa9u@!XY@$57;c=-fBK;zgX{eBIqyVEkVu zDs-!e8ybPet(tt(Z^LVoPDdfLp0*?b5)%{ci>5L-jE%Wlk2Ms2Utck!T*~U`1U*q>T!px{#y&csKX+0RIjLiP)<$4q{HWrDUGIZye|nEn$J3YBG))w)cON# z8RD?qmIOkQKOCVsR8+Wb6nz5BiurkZ7N3*7v@~gQMSAFSxv=C@4^^v&btNaCs_4|p zwt-rHsipN4^8VJ`H{mlH$gxu2{xHe+yZhIc<#F4U5QbBIo zUh0&8tyoh>@zh10KvhNh{7G=pj*zx<8mvrgNZinJFD6QhrMCcUMDOa4T?L?QL*SE= zyk<{;KqZLg-lmpl)+aR%3WYUTs~iM`<=@6?i^k676<9Z~y{`No7Cr>+DNrDOC>4rF zbMyEe#mnyo$b5m>r>QhWm_MX#UkkN7hkgV%S8Q6A85m{NBHibcpQ^YRZ2 zDSM^4P-}(OOMrCZMh1|1=5E-yxuZA0@OG>2@8&IOv(u*0LgofJ$=p{lK=v%EEWP2k zPW#qW1d21x)B9R@%g@`71|WDer^c9nMyhjQ0PY$jNI|UK%+@rFapkq)9A%b)nmTAS z%u^7C&HBw2#yw>{dP6m@#)6*=)K_1gZ`y-lFXPENK^^bza>Hb(nnReqMs}}AB8LG2 zHR;c^x^7f_IY`SQd;@7A1N+;sin6%A-|&E~pc_bE`3G1+n?25)gs@VH3arG`C(z_v zRe334GRoeKGb{F-ZRks_S!c|}t=(uk+-1i%+<+!6&J4WZGn5kMrD@DZ{z6%=SaSSl zWb>*i(wpQke|~>}V@1K(6Mac$n$o6q5|J~#gH|d>)fj8*YY$RVP6NkdQjLh2+qCQD z`<0=k_rCr3k+tMQiosniN+88E-)p;1<^;~YWWIWxMGLsNld}Nc6?;4~Gl}9IXT*-5 zgoGDbdVjgHiODv`AwsyNcu>dPvM^40;fD3hX{3H>^bV15*~v(N4JolOS=7qdQh9N8fr{UJD%Ca$%!0jdUdkiKb9$`q%4N_QiH1= zIYrSQ3wuV+vzB5)gjixLHpdYa=b6^`y6etDJw$7d81G7>3*BR3e!#>l+xU8lp}`jn z6+ryTveh~MEVD}%c}x<{)WS>6_`Vw8i9w;7M5S#>Ish{Xi~H8i^M_%(<;9iEmaqPi z_oEoWDv*bLNQ`g2#qDE&^X%4%#$4_DOUUMqkn?EW-(R$<>gCKFW=Dm%b0GRB>%tIJ z0g%@8eDse-a>2Ant?s5dCD-Ij$_4Root_2x!qnsI>XgM(o~|ZU{WF;=o7HywI0HJb zKe`PF6*qf`aFT$8Xf`z!j#55!8HJAJ@ux5h&lhA`U=PynMFwE}$np>^mcn*nQ-MMmxWn%LR`=7E-g%&I z&hv*P=tr`>FZ(NvQQe}VA_rWiC1-Z`S538Nbj{6RZh!M35x2y%;QFLS5uh6``Rb)K z9ofz27~?$EJm?M6s#Est-qfjjZuPN6hx~6aSusZ&eEeRMQp05a%UNT(+I^)nT=MKi z2>yy)d4G_dv0YEqtuZ)@j_mq_;Ra-?$aL#Psn4DvIQ5ntsmEcm$>b2Oyrgaq;Wfw5 z(Nckdf8-!YC5d^6aK3~yyfv+m$ap7_ts?iXKv1^5y>M%D6X@#nquX<@ZP1`hpl?z=dwv$#Mg2-cSJoXL zHfE+L{SL!k8VF(imDD%Kg5CM`kA%Wdk=J#*+u>M=$qY*u{Zix;4|k-@Mc2YYOzByL z{r#Amy5o(A%;QI7tBJ|U0y+J^`?fOB>z}(-U0depa8BikMZ~hb zKvL)f9{?Teo{T4yBUb!-N{B?k)g+9q5Fs`>4x0!q{ON#-iP`0jyk}%KLp==*y}iQ5 z93IuLF{X)2=N3WjiN}Kqp0@8i_otxxDvuw1!7H2hqO*M zipV^$ZcHa0KK>siVfi>uKAi32r$gTv>J3fttfsr2l^VP7keSDPRU2m@uLGIVx)gSJ@lq1id zER}w4e!ibCi{!@`PY$=Yqo|(O6dko4>ILT2MXAw!_%qMnk!I!WT2teNwt38+Z#2VV+U>TQ(Z5}Sh!Abn(Ni0WTLk6!`UtfBeU0VbskEvths*z%9A z;tnbfDLSmMXYZ0dm*$^eoeJyMZ0N3k!w*6yCR50JQosN&PouX+>=Z>ZOa4nQk}h%l zR>U)0mRyX;j~74X;$%`0uHV6}pl23|w!;UDDHF*T|+g z{x_5Rk-MFFz}LSY{WBmdnL$ORNU$(HBN3mV;U&AF;Z(@t&N2I5X_9lLK+(?YzB}50 zh-lvAiQ|GiHpi3-oc}VB8iSNObaQ@r@(;A0XMt|Er^&aAkL1<^i4#^OQI>hDnZG_; zg}YbM|4%>pQGL9*9mA5xi1m>FcPLY`HQ+V&zaMIWB)d*Z?jOeV0njr(79NB?uxt-M zNpJr>n}4P8ivQ8!n;X{uAMo>k@8iD)@qgA7Evs3fs;u5NNW_4Fh%mb4_~b6jRP{&?~qJtT2C$eu@yj`nebOy3?WB1HrJ6O)|%Hf0}UjL)82 zNx%N#xA{VY+hRwG`W_EYLMTN?U-s`8$$wZ@uF}kYKDT`vSGToYSJCpAnAaE>ht!pZ z>})CWSIsu}_4{og!%JHJe>58p7{m(T6`BLd_5hj`1{HBIe&z-O-VO?%ArhZ)8*U_J z%WwM=&Cdg0VqknD{pet;u~11jrrQT#m8|E-@YqO9Ig2=Y87{^(vbEAN!qFR;g^fKT z_6XyLOd@V@J_PQ;#MEYB^$iyzwhUza{!u&8d6@Hev2kr$ zmqxm=;!w1OuCy`fh-v9Or$XleV=3%6qrg{iroc}fiiVM?;XnC;7yLaqX!a_ZGRc+cdH#}LBZ$Kv((w~ z9=pZ`w9^T11^Np6`4Y(W6H`z`$s<#$%}l&c@~a>DXCWXW3N$rZz^!JBXxLlZwV)=c z&?s56&3;%yywcFayh@g889N-ze>#@q_D>Fqe?Xl*eiOyyM;)J2tZmjy@Wjb-=H8)p zeqVLV?Q{~$#$I^t6)y%atc*er=UT^hR>$0T{vNN;`M!>xe9sO!%umUr+qdBqy5IIg z4>fzu$lCF7zpYY>MTAUF1{gFp9xNN>0Ez|Y64a1s0={dZ=$pF+Z6yiS7tht-iDY!f zyYErEUpd{ybte%6GQ~0k$e*pAc)Sr;S{T_qCIM(S=rgx9tMwRN=~(Op z91c@FtoHvf*P>tbjV692CZ^ooS-o|VDW@H;H1V?73g$?G`K*QiGB$oVzq_`Z65@ZB z{Yat51T8$hD8j|ac(x`p>9j5vJ^AXD-4#NFvayYj=rndrJa=ML3yiqDy_h^+kJd4v z5gZq}{~cFSJ4`Kcf8r41dYEL^(A$@e-6A5aLM6m~a#dY2H6-kodFF?fQ+_mq{QEiX zV-tWU+a)xH|D+oNv6lXtWfyex*$r!tWA$jqD(MG2bm1>JmoUuA&Y7{-;<#XPR8m@Gfl1SG3vsdwRIQ_}ox z^WyM>w?V~FZuT-}?y}dAC~mYT>HWUTth%4GnOw}>>NZT5!)Rc_6qZ-VFGNNr%vs%d z3uGHW|FN_#GP|)tM-^_zO>1I@Cq7s*?!O*`fDVtuS5Yw@ytgyacvL;L>*;r|Ah)o% zFzM&`>XoLd+xnKuO(is%%lcglKjrW%I3zT7%fi2Hu#~-Ja3k=k2Q&JDie|LUm7bY< zRP-KHvFUZj9V_8rX`2z3WNr^u5AWG7F02KV4wsI$`yNg=53h=kO~(2MhEl7FefsFZ zD(f)w-&(-pGCutGV~o0I|1MGXyUa{iqXacvUAMcdTusvdw(V0?jzw6-CoSHQeCTxv(7{%LfW7{0J7y0j16%@kT%kdr@ z5$QL~Ex5sVRV?X+1M`vb~x1+kHT1&BY>md_H74R-V=M zXl7qR;-KN`u%@!JLQs~|BI2B>PF@kU4RcgW_qm^xp*&06IXA6N{eNb!d^&BV7GTu8 z&}tbQy9^N$k=tA@bjL16-t|U4tb&3SW|%0j%l(*&p1!cQ=D~v95c4M~iHQqj9*C~s zxIk?5@syhDrzm-8CH-^q-l!f&f>f*6mM6lSY6xPpQ0UdZ35GcT@3S^}oBWtQiz zpH~1l3H?#mf^Gyf++Xyl{<#?-87T=Ccrf(#+51b0&={E0clj)c%{OSY%7?)T@M2?H zr@BdJ$9?Nz%1kq@gTtn**taEN8Ql_P*_%b&|Ova{U;f^-36PcJ~^8SXciJ1 z=5wZUBV>E`L|A=yPtX~;qn|w0JyC3$t>@5OWvl0{AkA!T8JFV2 zwxa*EGI!~LD97L@p53PSmBjJjkjq&2Cju3KvOk!zTPXhx4*ow~0r|fX30ysN|6_&- zOef^{N6r^c@%S*Y=(ebF8MgT+ybe(B`gzS z>2rM^!zV$fe7kkD?j0+xp+V$+i!< zw_KprbY9CEIdO`p#j zMV2X9E4Pu_PT6yd??=gm+IS!fR3^-K*^J;;$8Fu$2yv^OpT77+>ib?|{a7ztNd@dG zo;vR=FScj2H__sR2>yE=N7DPJE0w6F;&Ii}r$L6J;J(kO<=FnVyRHPl7>XaoZ2hEQ ztcgv7rN!OB`((cwo5lAQ{3<95)=T78$7s$+1I zL8tM?Qo|w6L&mP6rXp-SZojmqf-}_DJjZLscR)R{o<(e-M!r;f{ULp!uEm6ylED6- zD?zkI_;73_1KAwxoqO?b$=@np4=F2HA#?qX8Q2Dv5SH#4BbY3LL4~Q|=s+@pzibs@ z3ikVIJW$u^mD`Y3a*)}OJ;Fp@_TisMi~w4s^V1uhxhnC^J8Sgbd3CzFr+wcno}0o( zbsj8zJUl*u2^Xm)n<8$oTdLVNC8Xg3!%jv9!!gNo08LJuUlt?E!_#C6!VBA|2;cp1 zw=6hbC^j8gCSIW*iM^3_-_$)w zp|caqrZ_rs1I`oIGZ6AcK8IPYKmdfllh_O?Ufrp)lhK1 z#50uB9Jo*H^WMQkAZ&Lo&9K#pmEL0HqDN`z{(ztV3ObH4_DD=PQsGzj*mh_A(^QTy%kJX(dqa=zGnHm zFh7YtK3Md zDC^EGW<4~E*V-gAPjIui;O7>3y&vigAROAr;_J}=>u0tfN_Ws+R4*F-`;W*wQ`5hE z2(gx`xlyApbSbZvP=m{G$F&3J`|cap4(HXYjzcOP787%oT$bSq|i@YN6$3g_xKbI-?vqH6S#*LC#THxXu^S{qjFs&FP%f_jKc00 zg3VY;sJFG=A)nn?$h{PD{? z%WZ@%0x0*y3x9zB6J5|Sy1Tn~v@m_Wxlo>*flv93E*|;K?yh(G%H&3}OG9PbP!j>m zX}02cBCgRCZ*LB^wjYKsfe5jGBBL|Ma zK@_P0QYIl{?HdKl9k+b`eB$Ys4T7iZ?P%=ip4XMf)qja{e{~ zGH+W@wY>+A)1Ddt6?-{qep-tE9UDs`|MW!`IZwVpud>isIX>Ol$q0k9&RCqrvhi^R z_ht8?-&c#})VEg%UsCWcf^E)76kIOveYlrj`bNjyggq5;k2XAxxt*D3ii6#Kk$8(d zEQSGIJ4%Bx?7%P`HP57O(BHq7(k$Z7pkU>>!!(>DUvcNX=)6>cI2iTRIr-(qEv|*( zKxQXLZOk1P@Cevd*-Nb?Q%yzDLN>@tjHINw{w>Gh$!3JNwj47+)>Hcfw`F$8ay6J!p z2Yq?N5>8SbQFIAE4->_-RNnUmgEvBNCoA_wz@YK8!X`hjeT0OjaCDKfpM7}o>v~sl z&=BXldanVNjIrw2ODe<7cb#ghN%QVUvdxK03x=}*!g|Cb4lv0fe0%uz_Fa6H>AZGsDe=_$mZ^GI7$L>G>kr@qey&Ydc z%`eYO%{}K`H*NZAB38|j%sf`Bvn|YC6yAz&SoPVW5;?Yf&#Pbt4*f%LjC%m)avSLL zxKY|P7Oi$X3XiZrU5Lp(X|cU@FoLG0d7lY$rOjuKit^33M|#$CmbNQMVPT@2-47Mn z4+Nbg8yBX!UwVhw=D4g1yT4s&E4J<<3Tq)U+x6ie^EjKV-!EIWm|1V5Ev$%T$orH60rL5bx%v=UsK)X4A8#J&8TwS+bZIQyJnzR`Qw}(qgtV8M zV_h1>yOWR7+#IRBD@yZnO2!g@e1Wt8U&8T{omrb$nWYmbT7f9|IMxsh7*_`nUmfqw zC@XTQq=nPcT^TRM9>EP{-v?kyotcoN(Oh`lY#EV}4(r~J{3P}!HoeR@-lSz;yrdOc zKhz7nMIt!aI9Xp4ZN2J#E2HBp>})?RIkwD0#>a$`ZRJZ_vVbA{XYpJugu*#X1*RUL7DYsb-k2j%qAQn70uoFx;DfXTL^G3*a^@72N&>@)bm#9-K4E!?nOzq3+~&rtNK%g-d4|46yI}4oJ^T z&xZ1foUW}&CCA-1JHJNIZ09|~V$>SNFHH$kJYT`g;f8pLyn1l9?mqY4SMUu z3(`N5p4wtTRZ=KHO$~WhC>J0w4^j~b-pdEy#&*}b65(B zomFnH1K%6)2)m4A>PRTm-9Ne9Ix)gEiP;xpuv$B~oC~$^J-O(2_Ciw-1`a$>|AK`k zEJoOVbq8?n0+O%H%$qj^w9||T*+T!UH!dnS;MwVm%u*x1+q3mqUK{9BUDYbE7iAz% zlxM8&V7dXs*F;Xy#?*$pGY(3qt5i5+*HpCso6S+}ARYPZpbAz=xsm0F_V#bx#g*C$ z4^qm-l)L!jrm&6RZobekKhVT9GtX;Uy=`NL%ou%&ZO^g9Rn0eXb|XmNgEjZq*k*bc z=Xom|n7#Reiw_ZRw6GWM>)PwXlYjr;TEHHHA*Mb3>WfEwZ6Uf2hp!X*)_Jl2EF~{K z`7=F_z*zrb+RSzdC{yUOk=AyNM|e@!B<*KgBM&g1c;R3A_y6XjVCt5OxY{{Yqe>6r zP+)6Wr`syg?uGKv9^?&QJfi&#R_Jb8qvCsvti|FV5_m$AZvcm3kdw@2NN zvEzq>Gz=dFto9|9-i)?~>Q(+y_YSZve2D484+YC=p2igIfBOaL!AkRUQo-E;k)O1; zYq%?Nvi@j=HW9QL&`0e5baw)P4wudsRw7J|1vFw^No^~P=G@)fEA^@)b`O@J&57jh zzcn$-zjGDYA*C+QDwHjX96OB>h|^Mq{z~2Ok9Y+uDFycqC@E`#F-zgv6mHU;a>Usl zn`4Xj1kI4~!tKB!6#zfA`tHmbp=}~9l>kxM9*0jgZxNW^0KGgf5R>117n?qpHE{86 z6!ZhGoe-hB@r3WQMstJ<9aS%(vFBba3Gc^fu$3VZ@G>I?8}8Z#+P|6vM|eWqhMWfn z_rs7vwcJrQ5BY!d($ew#Ms$-uJm2t0HIT)OMSX&YAl~!s6AJ^7o}Po}Jzgnc^2?CSj0u8>P9HQpZh6zh+lfRfPM7#l7fU zqo>C;&aR!Ixh(M6o2_HYf`hF5AmD)QXhw&>enN?^w#}`ZasyxW`CUFE7~WXqdLj&f z>DSHm-Na~83Pt0-PKG-qg*Ur#^E4?&(Fv41`CSeXd@OSRfOEmzs{U?to?z$CQ_w?? z)%R&1IcbPakG!v8o%WGi1}@9ls*SaG5>KS%iRI6kMtj+vrG5*5X0CF#HO}3`b9#sa{kV9 zIr3FfIO(Qdxi+r8AZ-iz4Ro{6Zpojf_`YV1hshF3e7}U>D}8JRP!`@VQQW3apRM_? zAoiOd#6~-l^6t$AL-zZZ&!l%3LAf`DDR+^Yox*{2X>7_Sej5LBd?7 zJw4loJB&GjDpYD2KBS>&(3t)Ur3qmHI5<8ZE>+rHd-#=f1agzfd} zkDvW~G3NE|7S{>lp~4ql3eUsUBRYMY=x_bTo#*8Zn-AKBf5~I&6W*$GGaG8Vt@T*x zsC@l!Ww{;j0FrXK8xi~}wAuCR%v`nAQ0HzlbZdWZ$UDm5v!=pq`z^7OQ;7A2BMX{I zIW3d6aqAa@&X!x6%}_j{1(?e>GusSZnM)TO%M$v)ZBkE$Zo<57A84ER<@dV$yO($F zX6IA{==`s`77+Wt&z8&T2)EYdF|T%J@H{|`65vCLop-7Tb7-((Q+HF<%`RRG&U)>B z7u4@vMzW#RSI!rSF|}o+H^cYd)k1NfBNp8l&)*RV4vSJQ4V^)N9)6Raa z$#parnI@cz7&)~S{#6yezm7*ByXSPZhC6LDycm4|bp^yw^1MHs0qN>}c^ER*m8yE6 z{9kxcgx$zH{e>P>jAXq9tcs@fW{YEaZmp_!qSYro*RmZWxM12EqC@i;;RrG0Oqo;8 zP|VA6?DIJJq7w1K;!{Bx;9i1ON@QX`6vT(~%!9kF>dQ>oiY;&3lE=mw*(4Kp@2ppG zyfNQ7@pPJCLR17M#x#eTCQwQGHX%Faa~3VPJ@l#rMnGwXIbmus zc()_)TVCT8Y>0ESlm{2R00VX2xAn0C6c!r!TusvxO<5lYfXoQWXJy>#p=fAYe^)?= zPZmb?cqqup7)RpG8#J^pFPgEmRIr_RP8sI`to5hZvJ;SX2_#dpztq$ucjo1S4 zE`)Gvns$eOcLq>75zumc{Gt77qTD;6PP!*u9)2Tif6xbe`ri}#FEsBLzmo}FX`!PP zd}sLpjv8Tj>zfex5B?(_`m%Um$l7P>90fFNpmcf2P1E*<&hFoTg@=JiPc=)91n`~& z(16c91Xtq|j_!Nj{SUI(&A>olW){yb4}BC4LRb{H&;m+;D*39{Q~tL1GfLS;Pb)uZX!%Sv49uBe$>%`R}vZn(<#5A9TlTH- z#X}4Vs?JWyPD#FpaQc7fxq!n7+i*o}m=GrGhISj!7Xhdpi-r)(FI$)UIQ+x7?}YRh z6Qs!E-^!{)8FId@{gDBc9;}R6rbaOx;EHo}%zI-{_6HV^pRWpFp5X&`!rnmxM zF`aZ$l|N+X)uFDn_~HvA1Hm)mhX=|}fsq(s)Yk``$|pdf^alUwg%?HSU5%QkF0Z7? ztdmJnRvhjN;Em5B=FcUex@Y7m(QrN zCx!OM`yVWb(pGJUSdQoVHGkA{#es*OE<8GN5;A!D43G4C>cj`8-MY|3W|s~4QsD!1 zX1%6^Zc3K)4{;2VB{F{3{=vb)fdSjAYRd($D!SW~O{=QW)RVZ@rn@QRec#Yf zUHwfZo5^x{>xgf!07tZSlnOgT9&H7+?>!e zxY@I(m}Vb542duz3CS|O%PC6e z`3RTwM8B7UPk)*IL`>hxu|GAIDUTD><|sF~^(H3Dah>sYV`I|x;`ol7-!=F8@@S1= z!MinQt3#=w(fa6k;KktYEO7yWxL;5s~+sclMA07!2g<>H(P-0OXmR zKgdGX2hDFz!(TCIYU>Fx6;Cx^WAHua@Zi94iiwGFa#C9__Yrb)$V^0lhHwO(FAn5b znnjM6h40+HX(4xZ1h(=L?`k~4HHy=CSIUKigy`t#@=WuDZ}uTjs1=Do(|KL1I+l~3 zzP_czXJv=jC%o&dnq>z1HCyb*2XS)B4$I26!{$d8TrKP&}x&`Ac&v{~)yUA9Y2#>bF{H}UXCzsWpCFh&6 zx%=V@buIT&~8_Dy27hT{!SiUrYc7M_U#;xBWam z>#H;wDairI)n@)C8WY>q%`qhJSKfqPa%ia71oSvM_p5dB_3rAYHg^HUF@W-Q)*fT#bn}gmK*PXjzEs5 zPq&TN4TOJIV;6zT4QNM42Pl;?gv4pc_#A{7bUPeOCFVSxS=dP|{o0u>SLwL9HRXCm zs!(2k-w6HQGevw(7)AFv<0vXwdDA$gw^2;QAe18w57O5$?c&sEk}N7G2b zv)>xeeS47Zdgi*-B;e_Jot>Rc3Atf?^W_ow{@(ogVA^t(`OpY;iH=#_BuU`=?&%W_ ziOsRX6?fI`_v{VSBxf&)<}}g61Gw8W&Xp8aYO75GaXF555JTRgV;Cjr@sl$MJvuzj zc+{s}2mgC&E%KV2UoqFI^NsmnI_GQIQiWP;1aopTg`m|-%Qp$8=ljT_f_JoeH|{G^ zKh{fiqz>D#SbDy)ff&fQZY~+EE5fyjpiMB7NYk&Wg_q;1N;pA5KO1c}V~_zj*IU~z zl6>SiX0o!fifOX>{=81mendACzSJ(+3D|dV)s$q5?tZyyfcig*oU6U{ME5Mu_~x_c zy=hm@m!$k5_3CQdzYa@PB|;-?*-=spQGT!Og;9uIN7K$-*4$-XOt z2wdAle>^cuUGFoxf;Ix*TT7*#`6AV`-EAq_V$;vhB=JZJqOP*uajn;0OUFcDKKg!f z;by#7rJ_7Tr9VVOI5j;TM#_ISV><&Z7rKVz8eAp7fJgC18o`S(?0bF z84EcW2y`B%Z+(4zcFzBKKu6`6Q4MlFFSiXiRZGhdg}_Bsjim)~Te@I{ed{TqB`XvP zy*}H`xa)EzartU)N-o%^KBYo`4da6Wl63uJ4#4XPaPzZk^8=>JTeq8zr`DlPJL_(z zR^H-lI>znE^IRq$<9rU+G~-ubePJB$I54YuG%YO)l|K|s>@9R7r}8sM-o(1>jTOeK z6o$>$&UJQn&JWt16eRW&6sQ$>|GM(*yHiRZYGAvuh;$?UY#rAq`vv;V-Hej^*lfF4`JVWN~ z)fa<{B1mc3#I}fdMF|Cp+E;Bqf=hni^y@tu9$r!L-<&)k{W&7;ei|v9{CX*l z_zH$9eyUxi+zoZCD-k9KU2uzTjO zW5h zY6NfcTHgBVe-^?SoU$I*rjMuBEqzytzQXn1StF>D&K*+7# zQADLBKnn;}_gWfG!YV@7JMd9Ie3K@Ub((%A^`hx2zgh0)>v|-9`GGw|NBFZ5Gw(l9 zK$YOE93cEy@cII)zB{E?j&fHpyxdiyE2M?UP1m^_MKN&4N)Xrjlg4^*+|AT1JHjJyP{u+hcGtld5<6P2dP zmgL5T-Khh=Sf4gduq5q)!GGB@3SQfd)2g1?XcMpJf7xTAcG$ejnbi!On3oGU)qX80 zvKsKyFUOg|XAbIGt5oy-E!K>dt>(2qlWyyAzG19IG9*O1&P^rW$|5G+rz+8AN{%S~ zxBW~=Q0CqFdIH_TWK7Sy^}4hdzs{7{);0=iobhPMryDJ&I4GrG9-|sZ;5jDHHX5;M zX+t04o~iyyc05w1Uwy{H4cgOPUtjAn%PVxo(R!1E{VXL{xfBbF9;Lu-TC*H2B)&9f8 zI%h2}wI{o-&%^o=Ln$4D}@ z>|>AFTavcUU)JSOF^o9lBZ5N{6=L(tAm+0_>99;b!P|z+u6zE?CDlBScx?liY2R@g zZW%qZew|dTQa1ivI^ptFcK|{y*4|oRw={la|WnjZ`!=?R2CK7fLK` zTcv+8H>hJ~VWQ%a++N+LDhFv3ni&OY$(yv5*u0v1TWkFNT5Gav3udZanvjyBh)<9* zQ18x=tCy5uAJod|;xZPq5x28boyL%z@D_jnxv(6Q<6Aq?9DTLn;vC4pAWRcbQ4^&p zn9y=d{L9vv0Q%B2uD*s?(Zm7*W{ET{O;Pz35;@^8tS%sskx0CS5 zbn>VsB)8*Yvc3bmEC_IXOX8vBaQmGS8)w1ENHhL*7+auNHbPYa`w$eHoA-i>{4& zRANqfa+qCmY(UTbvy3zL!~qNW0mt3g-u6#^O6q(Sby73>i%+!iHS;lBbyS_Z z4yr!DT0VNdgc{rb`e-ooHbQNJ6OMpsW+^BRXym^$V>R%Zf8fKWE+(~7Ib>rnJ^u9BV>Q1+B!>C>~$Xe_yN^F3faFzOqmH@&hbHE{7GjcL=6TKxAL1 zvz@h~ga`*TBk&p!(R1JLLjz(K%%?gWB8nyJmxu+uSsWhP-aO8*0WZckm>BzK~= z!p_F0HYD%!`kWL`SWaLoLr$+U$Pr&omCkHWAvrdd#ii7y=ihXKhxpNCkKK_v!3Tu5uWB3vgY(-_B8}CttPXIQLt#SinZyy zuL0-vgPgz0dQT2OX zEg>kDo&B#K{au~2@60SJgCylAB~SFu zY)Y~{Mf-YZc`6I;{RiXWuHIQOj{Fr(#y(|rTjbC>t-V1;lhe`>)8CWpv9wTjwj(Bc z;*`YScBO3eHY-Y_^j!r6V2uuyZSKobt>5%lIN6%Cvoh+6U>crBYa}14fUD1 zZAH4$T^PV$)t-WmMoa8X(wvEh|5s4FyBtO?m#vZivsNat*3zZvyr>}D*Ev|5U*l_T z*SS)87MVB6HA7SezSM;SZ|Ocs)Or1L-BA$1&DHi8g8z~}uBsw63tp#+?> z==+f*9H`5fc2zp%RE#Oh%J4owl_M2r-h7qtO3!RcHPFI&7ho)2=xgv5l}8IaKbgvo z60&|7>?cM=LkOaZ{40W%Sp(F-o&Z%iVy&~<+Hb&Nf7(UloU}BQ?)xd zY0%&#S$(R-QY?jMDj51kS&F)-GHj+x=DF#Wv^Y5py#`vfEKuX%v#j3|NobEl9iqI_S3vpcwE_m*4XtS}8UVt;v4CuXsXe zimGsy5;F~Daa(&J-lM^jfwR);)3Zb2xIhS+IX-HMwW*&16j#5$$>+q!d~AW5OW_)E ziHTT#8x@3^uSBCpNeo7XsHiqe{XGB-=Hb zhP!i(2sxIPjm=H%T?W7ibE>MnzkT$V!aF7tAQ>xfx?!`7`_(`5QvF<>2Ai0zUOJK@ z*FT(;dr;uxMv`cIARgqX*M}vNSbREy7i2aH5f?X~nwp8O?Vo`$P*cwiPSiT}liJHe zwoADe+^=_wVw39XB*RHKttR@DD19y>`3O{%6q+ssRC2uyb*m3v3E-f+J<4j(nMp`; zzbmbq_o*}#PNwM%3E8@uG;z+2j2r?Iy#QX*-I{0A;8$%GKd4z#G$+PA zd-NS)n9*bko9JUD=W}JGqoWEp1ym|Hz@W)<&Yaei&5OCKTsJ}zS{tm*BW@G@3<3Ll zI|D;QLyxcN0`4&!8smcE;ofWUt8sDLh;jtzY`)pUn&UFpAA0V>ju%HF8*XYk>-i8T zd{a6%OIK4})wQNYLaF}A6Tp9;e<)*P)O=^MqRwt^8LK|fc)|PrcHn!;s;FgO0IH}V zCDoNiPrJ#zVB@h<(QSb9w2&`Jjhc$dW}(IV#E`^Mo!pX@m5}qgGe65MUHp=z`7d}+ zAut?D6n@=Grz9*-L9&@id>n|h)4McLY_^jaG4S@>B;TllHvFossR7*l zBbQ*f>C3-_Yiwl=yKcs#pw_OGe4i2>+-71bY7l0zXXK3>>pXRQ4St5;aRa4t7Zn3j7A4+}4RH&M-cy@M1#9}~=gV=EA zcimWgW2=(aW#zeEQ5MN6zwIqnJZcrX_Yy=BuVmFX!D*_ABywfc3hpo}QPx``j+6F4U~`g2QH4=`wU)pT@yE#C%`m z9@vEk}K@A>sSy+yrRJ&))IwK8hUj+;0ZT zpF4nhKO+e_xET_H{p9SxXd7?lB$?FT7z~Z0dX>i(rp8QUJ!HKhu2*p!r5V6~^IXVo z!tv_etyl@7a_8;N7CFQ@31!VeT0up=xs9MwYJfDeXFlR^ zjh!ej6k{MLwUMLJ!D=;f>zI_*V-Mo9769ETvW&*yj1P^*OKPN_W%u6Q(TuQez)q|9 z;FTpM=qcV%Qxg+RK`N-4C%1R$W=OBl8sr17Gxds$R!{`P^hTr%RR>9v$0Oj7EZ_xmv25+Z%w`Sqt;jyM8ASejAzXgNt%IS{j zUxpwIJa^A_b!)k5tNW?U5X^wUzfCIQ^?X%+o0gpb;NLFwq)t;@?E7Yisi~=*ot|hn ztl`J=5~AC%3OoX zHEg>a(qR1fHi6K$<^Hbe6@$izZQ*6R_N>0M^y4Q_WXN+*EqVfZ21=;N9o1ox@7Ha*^%J2;*6JByc)@*Hdvm3WJdn0*rgkVnc*E`$%UpL?z z8}@*)L{37@{w%TTr9G!u^uf?JWaNPoUZjuG*-Wi1KRE@f@uS;wWCkRi$Ea-$mT0+2 zaLeP=feEbLA=G2NHJpPnpgfYMgkFR$O!1M{{-ogZ2{?~~T z&m@(u7=k3)!tdvE5s727&qp4ewqA@m4RZM}=4}#6C#1{QUk5u93vqkN8ba0RC&;u3 z?>fV&qG4?T4n{$DBSXc6;%VqxtqfNiWff8=b~8Z;hgb*DJ$d z3=D}lbCeX9D>#9^sziesi-T!J+#}qKx+mUzj>P=nrGC*_8s34WHBjPcr5+R+#wi?z zAWC0ouo%Ykz$%XQXkp{Fxe+nP@HWbtOd@-GDuOrXXwp5BvEPj@+;XxkN6zm&TjR+M z0O44oik_Kj^!Z9DX4dA{$kT0D0#p9EX0lw4602oziUve%+t;%awm(8V4mk?-u}Zv^_a>jcqv3Tjno7`Uj{&(Y3su2`&^77R+HEHagXZEePQdQ~BUmZVxZjn+g7>|+q ze70{`BSna#A$)nF+7>@}DU3XyEz@tDo13%z^80Y%o*AmjX1OfEcL$io?AX}0UTqb# zntZ>zpy59DTCW>)=(cf;9+QVb88_1F^e+^>|oF!FRyi9xl=F8iG z52Nw|-fW~~0(PfcoF^N*QsOlDD@^V&dk*aeBZ~0d{SSJ4r+j(Jd(wpU82H z@_Ju!9LHJJc+6d$I%moyGLPmf<%^=cg=J6PaS(IJY>ejP&AlR|A+v6@25Q(G6u&U= zaXjbU^I1z7iz@3~0GAifY;eXv3it5u?u7;6k8i$FU;_nlh{=^R9v&W%|MCu0KH1GU zM5$=ks%pmHpJV{X!!PzpOz)brFGo=?V)Z`Rt!Mgck~T8qi0lillSQ>ijz(zgupW>1 zv*+aGx80Nwf%91qhs=DFDHeGvLM=bkgY)fbVg3{N#lm!enmFv$W`z}ico!$aAorxV zb*%$gq7j`W#uM<1)k|dH%=Dy$eP|iPPrM#3n49?qa(jiN4hyxi!?gTxgDBay@*?=$$MCt#_{zres#6mJllV{|=|lBqS1NLs!7sp`ni z*sn13?uS4cdCO46Ylh&o>$9yjA!ArDz3r*J#hSC{7B-Is-J>~^GNt--K9>+P;tXPr zpoAwu^+bg6IXLI0%(Fdg(a+I{f0K7`LT?;+mWr&wC@H|yN?jB6z8`XP17kh<& z3q<$%Yr;U3S(;2!S8GnMJa@N+&Q=h(O{l15zQzCji zl~}G<%QHn#=3Qpcd=yxS@YIO=*YIhrcOu{xh1qzbeyQ7p@pyF_SZhgK0 zM_7-aT7LLLXlC~`qjpDv28%I?2Cg&)J; zWw*{HfSJkx`U*?)N%o~~a!T%kPD-MgyJbWmhc>_iu!IKkY864BflM8f2m1mC0J?#? zs-!vNh=zbiE-{NoY}wffqJMPs*h@pBCR!m0(Qm=Hl7cUOPsg4xE^h=abotx7`3bsp zw6@>6@Y$BPIxJ5*a!*NU3bJl!4#y~7M+j=qv#*^q!Kc%Ki01L*$H2(ki7OOR`nu|M z{HTytWx;D(fyCm}J$opt-KDy?tf8@9{XjR<+r<4ej#Aj?W@9*K{1@9f5$!f(PQI6E zbG?(C?ws={=@<)lYVyq1av8N-HW9pG)%=m>=BAL4P|K`>8h^Fhqzw^mVzAjM2)sXk zdk7d}-=UD)&`(O@BY$wR0t2C(pVjp){vy>$Rc+mYlu~WWhtBIACkN)lt=Gopsm>gZY=Uti(D5hjIIHnbIbHyVn(Z0+;Gdp zQT?FTAT;5!)F$bC(M^f>)A~!f{&nZBZXNx5htJL+=V~@?roPVv$R!iO(?H0ix7IeV zYdzL^PqEPXW5)s4KPP7INHjwV~P1HGZF$>Z1MD0jto&bmxiBL z<;D6$P%i-bu153aAk(DT_A=WYO&#oU1E?1p;>J1=+%_9&5u+e{vpQ0J%D2`0ejb)b z#3WG2#}dxEao6g!wiO8wW0saX`|fI(_K4FIk${tMUA;K~bh}&q`DVo)V%xzSwm4j)YOa!lYsu1_9)2n)|cljoD zb|WPE4|B-`i`3{h%Xrd!rl-Y#TqiXxb(7$cvDJI$+o5gA25M5(g+7jt1zZ)KI29Y` zSVXuKCG#tkObf2AP365l(TdWsOf9W6HyMyS_wK=;K+aKAyAK9|Qttm^pwg-u&XEmj z%{2a-OJs3GbuHCP!TgO^je{LyY8jzQOh_BfG(NDg{Dx#?daldfeC2J*7Vn7PfFOhi zaT%Y)qP}~QcW|>LH$ugN%XW$j0((xi&FVEDivVKEr!~BRL)#b%m#{aNw?vM%gTP8F zRnAirdPvc|5hq)!XueOK8k+f^7BUnAT2#EL&<=t`KPi&B0$sAS_F%5{c6ZgD7GTQ_ z(AZmWWcV~t3kamn_cH4@I5V*fP4D<8%aL5V4apS~>i4~%L<9u#o9}5L#+Rx!Vtqad zd%=~5X!NwBxo&&h%QB@hQet6Yl>8INJpp=`nJsT`Wg6alUxSg{O;ygHmx^$%m8{A2 z^m3<92#};&CGF`8t&aB$SnbG`E;}Ak0dqgRaZ0@tlTLz0F@;}Je4rhNAp&8-1~(pS zB{JS}p%(8}v)x(K(4Og1>A~$a@3cYZ zM()ia{rr=Tw6^*htT=6Nhal1sWS0{uSr4j2!{4lUo#7NSNi`ESLr`}$IuE_H<51rz1)V&$^l73*|wVZ7g+qV!~0jq3% zO&h=&UtWQb5Ru7?6GzKPP_AkUh2=ly*&j@*0x#SZS!ca_J4e4Mk$wRPOYLJ5gqi~<46PyNQh4B`8&Vk+QW={{yTX12Cw z@a7nTGznDSF61jwen$7S8BL6X3;wC`Kpysmcl~@_CjOn2+b&h$a%KUT_RxXPe+lEo zh*b?oN8Sq`rfy+D*hcITf>x;kl;5Fc&|*oDs4wKQ6{j){D3y$lW)^+)7B{-3rvu!`{%_or($9>_{6HZeVgSe=WOa3CfB_2d^YW(M zJUur%&XX#rAA(4`!>ptdt5C4qC5A-7g&$hCM1nW5%Z}>@qJ}Qd05i+OrDipEw z4+vaHu4Yq~v>^V(z22M-UJ|ydr^wDPxnJ(2*_U6ldgD;;q)W;hGQWJ1c*Yc}b)s*Y z+tGs&frm#b?4`_t;k~}sGld1=I9)n6Uagc|!QgS=JaQU^Xp=y9GN-LBUk)^Mc6K9d zjEq{1?Z579AD3s?3vDI9(|!kQADY zDl~TIyIQv(HZ-P3qKcu`!*4K>3)CO;o4HxmLKdS zJwShgO~MnEPzo^2SX|Ed;4iB=O2oTytDgr{^P>=lif|kz${At;@o65CeqqipB3GNE zK@Q2}-&3U@Ik6qUsd_9O|It~d1t0OMQ_-U1kx#EyOX-2dy?n4-B(6U?x{PSZZ>%}o zYu$#g6q^m+47m$@e2n(3Hh8{fvl+lxihTi$g)JdI#E&|`7R>aHvs+V58z0fMS(Y5-EochcEnisnPn)h*`U zj^LVF0M@d70BDmZi}U0~JIBc!3PU@1r?98K6A_KrXCJ!tQ4Bux^^QwcI5) z0iWnvxWTdr?61r83QPN;tyL>1*XC&_wczg6|P8Q(4K_A0$@tQN+jF zG~+Dgu`Cm$lZs*v`Cj?h7mnp40Ixatc5vzC!9o~PFHEsCJkxMDNd7PZZlk14XK;jr zNBljNP*bPx*<-O<%iA(|K|mbIqlZ}{Z@zRGU!4RQh@$u+0?(yLCgKuC?n&if@I;+m zKd}ei)N*JP^uYZG|By(W8IO?F7h4e{4wKV?!_lgxPIztTLZFLA;sDQmqaC{iEsq)a z{Xk|B>*7PNZy;{znhqJ$^!o5U$FBtxr1Y(}OG}Ym_|ak(iW%=F04QjpWy0(-fqj{2 z1gy);G5j3I;{Wc5*Oo?|rrdLIIXMHI2)9eR$|M-E!2{U)QM*1Oc5{7o6)1rX0G!5! zr`?vOTt50o`2Y4A*0=YPh~1dXIfhaybCC718ZPV(q+D@%~g%d%*R;LIKbsJbHqzo6Qm}Lw@09psh`edT9&m*A-fC z&Ft2ZRlu^z)oe`>PUa8sf}16*tj(oEL4e<*331?E=rTF#SX(y%3d283DR)ZUvvkb# zV)nyu9jYGpi;Wtw4=;mX2i(!Te0KQ@3q_U_*%qbj0aoBPCB7vKTTP1U(){ z{W!YaFAzKMODF-GJTG6+6QJ`;2PnU#M#Fmr3`JV}5Q||ZRPS(m1h3IGv@ELHW z96a`ako_N;?6EJ;pM8!&$4iP5!2;Z_fkPv4lXn3*x7)@68=R2VWkWf4e8Rjh(ZK7l z=5VE4zfnV3S=q%45CEv=%M%Ox2#~h`SlquJSlS1JLHi@i43a3n5q{sYD(#8A&G5Q$ zL_$FeDV!j)wH||JJ+q;7pg2bR3=0d7QbXhow%mK5OFux{~0n+FFm}O4s3~SE)whm0@vcNJs-OpJIkk zI0rY~${WJa;>dWs5u+v-qH@W71&U;!~W z9gcK{jpoNwP&i-s6FtNu3(7%fe)jnGd?%?Y`Q|2qod3>t(8iO$Q6X2`QmH(d(}{s@ zEb|L7FtXz-PWP4$`c&o56`g-JdsH0+#)4JK#{^TfWP_iIn^U7jQUGuzv!T!FsjhwV zZR`E*{#v4;D|p}9+8RcLxp86cot`G(e$)s_5noCDo>EsbIK&gKe>}Q(iJo^Z)f>n% z*O*4y&V!dxVKK0N8yJy3BmfpVUOj_SIOoDH1~yMt4#lNiS;&0K8%RdMU9~4atfhe> zuInz<=m`Kg8W)Lm@!%vinw@9GIzJ7pV)R{SxxsK2$0i~wg&R(jv?ipO_tgSk; zvTNG$yX}0v%KC|OY{(j!h@09f?7gs@HMpl*m-=zQ#bNXKmxR%xQo{e#0$7<@1{Z$s ze^9Wx8cLxtbQU$`0=n7DNn8~H!poTOMjAt7@&BNR_-F+{XPgL1SSrzOUcb34xl;FC7kuZ zTwpdQS;kwMcc$9nJKcGS-!S%xkmx!-=2HG4Di}fOHlkUeudhxs#dp8weYk{D-e8%K$ zcQ5yj${$--v!^U;tAHfxV9Gp$6LR8yrhUbFeU9}gvs5%CRbvZam}8R=NYoFm%YnUG zS0)clJiNWj6ieP~<|OjL(gXt=VQHu0*L?Z>p*5RO{}VCk2F}5lmU!e!0{jTDp8|b@K9J7F+`m{9$?VlT&Gka2gAvDV{nT> zAb`fAe!b(NqeingZXKnTe%bDWk(ib40o7{nYv3IvYiV4)j=db@GZ2I33HSH zh+<)40CXK$8;go^jPC1AS0-xKd#?J6Sp*;-)37~|X-kP)+EMMi&Ku8f!EkoHJWi6O zx9{E&eB;6dWPORuPM6;cdipSt$PB!Z0<-C{LR8@#Qe`%9a(YsM?2J$xu6a$|Ppy z^uZE7K~2Nxmx9o8Ve97if`Oa}5HNeV<-WXgs4R=NvAg;!hua=_vbuvk3 z`_nbW09t--kkY<#YudM+o=#E2=r_J@Fv5?wk;j|vLw9`OzC15i!V3{M>@LCrjeVfU)((R@Eyywzu#**zQ_wT6Ieie+M5M0M)`V^ zzBsU8Z=G?F;Iq2pXK`<+$0io$?q>&I2efa6bcsQs{zqBmVH*sI=j3c&L7{Q#lnX6} zE4<*TY(xOOrojzh5jHf&Md^rm^;E8;yjGLQyZqEU5^RAs>x zgcJ@EvfB*)#R2S8^lQBtsi2MR`MF33Q{kPwTkBQ_Jkr)Bhuj}RAn@wW3UVA-CoS1W z#EfOgPoJ9b18GKaL(O*U^`r6Qm+@;&CRc+7zhaCCd6WGGj}T3^w>eAQBs8kl?e!L+Bc`Yc^WAUx&_2Zu}V z6{i-wl#6Cd8PM0uYMMuj!~Z9JKS6T3q{U86PL^Dp#Kz?STGXl`q2tZ`3O567k@(& z5CH1no$(~tVp#>=7`!DwmMVslLT4t)MHf_$i2#|4Gu7NOcHWa{84=)jG>QkaRr=^w zPJhG$-sE@2S28Xc2?K-i4~=j4N>K$W=u6rsG-u={Iq?X7**pmZYa;y8>;feQkwp4{ zo(2d!>p}TiAMk<5A9cBERgPks=g%x_1JML*fSe_2h8v5|c?YoI2EPAv$>VfQF0p9U z58a42et`1pW$v`NfB14H!~?oyK$!eJVX5b%{R#uWZ*Ie_R^L>8LI}lxBZt>ac#XqtA zi~8a(-!{TOHom$ERJt(Fy^2{~WPw$Xznm)5Fx?&Qa~h0e78NDshexZ+AEgd61FxcR zz>I9X>Op*-++@JaG6~tf&VjdPh<~J z6BO~y&BH*YjHae(L;ZHM;X92 z`P%;D$^acOHCN!Kz9|nZRp_;fNZz;+(@WeSrbtQ$7}$QT!2IvjN>>t2q7490i?GQ9 zs5%FZ=${|$a)=H-1AV_SY}B`cQ{8@;V|>*+!#B`^j|`LEwbpuh0m+MdLc?mw<3Ezv z{)a+*@9gX_zscB%9D|;$Tw5DA(g${;udWKkYPh@S_W_j!46km<@?<4d@{$4jtL7k5 zw+eVyAjyfi_AiGjssvXDR#<=oLKI)j-JIMsfi?j452E<)-826B`|1D@IFCD4)W*dCnEMxVEMP^ww`!qERh_6K z)XpQCM60rP5BQ8d8~%{lQVt?HOMd(9HQ;KBsvdVfh-z$T^IEpzz5nKk?r75{mb!m4 z=$AIhjRWc{zxf1rRxyeNbJBilK>Hc~AhW^PN#@JlipZHSEnK@dHJ@5KJ3E_{4g)(P zj2xz5;rki-B!T$yKSz<57q)xZK?*tU^Vx0OJ>VNhW1?{14cU-udia)) z_0Ka3lxf|C?N9Z=SDqupIU*?RCcYfMy$wC{1ASfGT0YpU`tp_dT}p*Bkc1WEq^dLU^rp3b_BeX&TztCwS0tnQm$cm6+_cAugkl&43E%o*kK}d7JYRpfJ^v=Px@v4c<+Hq^o8frMAeG@SJ@jtWjt0(PDouu z81xc9q&alW*cwk*xl~bCMIeP}Xs(k#k9x{#Vlv~#t~vM+=#F|_PD$VGG&SCx<-wk_ z5kNC}taGNRt?W`3h~49Uyi5G)&oaN2*QFapkNz-oj*0u)0xR8o|9nJ5)wcf(7dzbM zO|$QTc#8RbTz{niaO9e-!&=S8*xIWj#+jZ7g{yM`uK+;jYpg;Fz1n&vs(u0xd6*kJ zfGl^$n}mdTaA=6)Vn4jiLF3|(KJuCZkf0m4GE*X95cfRxn%{c&J9v;dh2+M9BMhiy zaW^q>0g$H64rIxWxXFI*7Z&@OmF0=4DH$N#7*ucOwFgZKE$(6ki5joDnw0 zE}QDKv_n$s+-{IY_z8OI|3s(Wy?Zy&Vt{JkExdl!oV?n+8G`oTF*CmBdG?pV+mQ;u zyTj*jV+HkOokSm_vbp6{nh?S{{7-M+0whnk^C$*(ZKP$4pdE(pPTnZnRE-l2+B}+3 zI85kXPvz+mNN+eUUi+fSJ?Aw}pC{+Td=QPbKngPPF8IPPsb;*rB;0g%xuQcrpl|qW z9T1Dj$@QAmdUk<+2m2o!G%%+}kqWZ1vgT{#4gGqIG{tT#f>w9uvllGs=~IpMwW=7@ z#!91so?vAZ*L8Ur&6UUTrg&sTCgES9d@LYDEtWbx8)H!xocpf7hjm~y_$r?RUy%6V zeKj@xkOc}KxM1>B#T*=34mQTFwu_`dSmzqAtwbT{8570h=QSVQ%1!F(^$(2GYx_6= z9}aaETHO0OS2MTS(wkOnni;u6j#pAIZMQEOKG^EKL-|(Sot|m7{5V5y_;s1D;jMA9 zpTBIeQqsw}&&YX#f zS=Uv^00389nn>sdDUX=ErJJ<#c)2l~s*+O4B*9R%^92YXKiDO}o6jh3-5{s??hfS& zSzFnjMS}7rD}0MJChE%Q(@T=%IUY*dXUeRHB#nQc+GbJ~m+8@5SX>N63aY<$3GqbJ zP%}t+y@X610yf-3(&_;Lj*jb*(wDg=1I6Ba734I09EqB?85kkWO~3@=__p+b35|)E@^p9V`IvlZ0?N%Pb{1#!Mh%^qZc}^8V-KC7=m$uaxh86t<5i ziGGst^G8w=-M@xe$2CtU3lr%(~rY-*UDi25W=Ne!p7X6IQKcSMFuH)+Z)zbfh zvI9;{|8sS!{zqWHA93`{l(E)=-GSS|LJ6&4Pu*cTzFVJEB3eiI>=*EFnL2`ZG(X&X zD(SyQA+#pe_C?y&#C9Z7g4}&y>bXE!xgJ+O)VrqFZaWDb8z3!7u~rSutVi7D_fA$gjh8UDTy7@!DHCo{mX#C40&K;SP;%z8n1h zWbc-`f1*^__s*^8!QDdNbmy^H>&fH@t3TQ4r=yyB3wzhD@*MeK%ZJxMW9^S$B*a1X z>vCm%MG?^R>E9f*Z%y;vRI_QP*8@4`Gz_G6|KfMGlCcYVMvrfb7%9>Nybp|f;@S%_ zDzquynaOFZRSP-+EwYSkDNdPXpYQ2;mc z=$%eef7~pyiW8i>(0Izn!Vlm?zC-)!*KV`mZbOA7m&Dve#kA~f9Bj1XUeg7+-!?_@ z#b7P)>m|cW-@(P+dM~%~KTYPAul$te86T_- zx2}RW7CGUu^`vNs;5cSVR$+KT*?nr%CCosNd(>g~^LHz<)tC$X`dW?4qFLofR+E(& zO*>wt-kfEtc`_N21pF<8eqsY?`4^Z&FF*0wZ7YEg7!oDIROHGcn>Yabfy! z{X@SzTL){gVYW~t=+^9qXWvf~HS$^I$|fEL8W~i~DTZiJFqU|NEQgI8IDAE1W>bA0S|(CrUs_O^Qfwb`$evK_cQ{IR6Jad}H!u^KEnmilz7 z!6me)vFqLAW)gqYdst!b`l#yYTO3HEH zbiz+3gH(-mLF|`5kvySp?`4bJ>@=oydmIddhFOopVV{wIgExJ3XzUDA!(#~=PzlLz z+X`YcGs>#i-pImb73~g(zGv+SV+rM&7}xYQwOghQ((gGK2K6`9w#R)z+C=Hn(p<|w zu)-UZd{uCkef5)7v$by4PZ>qGLc2 zHNWceMoJu)s4|wGQsF3?kZ%CfP*&1aZgyCIsGY>vO(pH0NM3hn|7tGLaq1h}Vu5ON~a)d%e?e^l-*cx;@~cR4cnv-SlfNJY#l3Sz@d#N~5dz@NG#_ z4{CWXR_hpjJAG+o3#-KUH{MSz%BTghGPAL9?%>N_ak<|(WrFkWdIC0=-`Rc`PBTC0 zN{#;|=-!8a0?Epu$tZa|stk2|hdhwBS#JV$HNh3p=}Q~!W+a*&fz6&q&WHXcf2e8* zEcvV6*lq0!Dw;6mPbfxHR@sA3gesbLi&9+1bt3e2APvFdVx9zjK}rf4c{XFG=N{f6 zwQ)XN^+|Blx?asf2!qi|2C=bNVCVI<9$`99eYkAByB#}#ig zl*E^6U-Yc^88J&TW^b^aH{&_y`(M9YXeZmH8Eu6fHf%{HaolDaYC!Jp^BbKias@0+ zg=GfJb>){sPCJ?)-m`_)QQi!xi-tH_DsteA2B<`@9`y+jjs@Nqb40k4}B? zay%3pvUa1TE1ad{`ynIxUYT*DePxRbEHSRgHsMp1v`ORhT~~Pp1-OtNv`0e?>)LZ* z!bYB&98lpmN#?4iVQft8egH#xF7CT0wv71qB#56}zYb{}sQ=0v=lXH%`?ox@&uZw* zHHr$ywkCdjpJugjd-a(x8F6uK%xDovS4_;vh?6I|D#G}vE$vC(3qD~nlbt0ApS=dX ztaH|goIv{}Ym4iW0r8ZB!*U9Oq~1pbt!;cC+h43N9S{5Z)D`vQhD<{-@EefEP9q*J zuomjM|C-%>xJrf^=0^dm>13{PjWIi@u|+al-|e8rZ}LZl}=t5AC_bUa8Q zE~0Snb21m&(}vZ0x+iRUhU%#WVjyhU6;;-EE0CpJIwzm$;jGm!X{d|1rISSsp+LvZ z&VkjHYNZTt-|_VDI1tcOGC(h1U)ObVEX}0=As3X$=Il&afsZnNh;sPyA zV$eVD&KUy?5`_XDnSoc=?+|job@IdiQZ;4gH5XCOXt+psw}Nv=u)ZdfPTc|p?vRf1 zo$3cF(qRZb@#DxGQfWbM>+J^aw(6k!i7WR||6Wrt@&sW<#dFSEqaG+7PV;UYm(%sKMF=#Z0a-BC#puAdWuaQ6LF(ECqe0in{UN*KyER=!#tRQpcGB|5h?i-L z?OKF-k5b+Z89ZGP-UOa0>R$kbou!^{vfQAm-|?YYY7&}pOD|9CZgJ0whp}^jmq%{~ zx58R+%&Kl7{uaMKw>4A+yS|(&8DBEk)uec;Dp;Q{S9Er^nZS^0HGErIn&wtA2gQ1s zx?vTwxO`%=CX@b_a#NZnUHHgS0nRXq*KVh;{$)xXO&uva?4CtjxvRSKZfXwkT>vi_+~$-(Lkv*kVh>3xyKY&?|czv<}fkQHPC}C(}+JI^)+#f zw+7SmT)7g(rzWaby@H<`=8!&dV(b{~aQYVuq~wz&{fAPYR8Bf2cxqL)QPvjk5E<=!)Runrzk3wi~2vItFzw(UHr}J1jGYkLjmvLs*2?+|yE;B*a3!-Uzc=h=DpkYNPr-DkPgIS;?)!{e>Wi@v$GMzG zGvY}cI>BoDi9`9RpnOg8R6&qqE2D5MizBC$?5daP&J_;F24hm_9#c~LiwZtRYP-!u zL8FkKq$H@SZ6HlSw+xu2%;XC7s&*D!SWh=`aR%6I6Fi^I@bICdhu+_3lN3}&6r;j3 zx@pDP`GPnyJv=~GLUh6HBGVL4^qw))NMIxkIx>zdS@>=uQbY-GCeLmy%r=t94EKHV7X0~ zYpI~`Ehfe*qPMfYVO$o4sph1su54(ku1{~l7U+fY?|H5)4cxfA<(QIM+*E4z#2}a_ zdS9z7%8=3*nT6S{;Y;sy?2 zpx0bR;hE89IbeMDqkqh@#%7#?gXZ!sO3c3U%yO?i%LcF|39bXZ@{38ltGSKkqnZFKn#P*UoQw62r->-ty5Le^fLqKoKY^ zVr8Q*#iH{p%`^eFMOIR22u}LydlTVlsV7lI&opkRTor7q@+d`3jVS~vE`}t(V0Pbc zb~`Yt@wzRyBTQ%w-+%?%Za#eKWVWmW(oavyzD*9t)Giho6jq@ksSRS24_!PDo5Y+@ zyXsNl;bJi!gp0@aCFoL9b%oz3zCC{HFm z+uyD#ictA3B_+W&GM_?sTIefw_PpfyrwA2J2R63w+5GfY?USLnrlyFOJbN+PU+*_^ zE_qS{@f`)GFzxk@?%ptrTJAl1KYqdSrAakPO<{7VEmR}x`&hto~;JM@Pa0nN^MH@`=5AOr1+h(Lqdw{WRhN; zfQoen2GMjAJUSyK{rC7pjnj1aRn+PflM|B?^1N}YJNXHD*r7@)$T8fe0AXzhbVm0X zS2*qVt3Le=l4b2%=WW)vH;Pg0(k%S4(x+mgMwX~?y)NsWP#aRNHNkLa#Gq!EZCR)5 z8{WNH2PL}a7Kup51YKi^o=5PX`2_#gsM6c)6mFp9;@f}+TIADJdt|;LXU-TY?^wwQ zc7qnOG>8*>H)KBdt&?vQ&e}HM=V+XfI2Yo+zVmBot1v=qqG{;X#Ae!sP>ikv)oakN z{8MB@XP$9nuu@xoo7$JKngj8gB=_aP-+9oH!IHANlEXf#)z_kSpQM~tK2uoH9S-T| zqw_Zo;Sy=@Oik0${BpdQA{&knY#QCqj}G$=dQb;F2j@eT)kFsDUJJFQwZ4kYfi$Y? z;QJ`=s<+m>t^zI!#zV$rBCCCQJz+C(udIgu-3@LdRgvPQD4VoM@%lsZM!RdT9soK4 zw0*7LnD&WbAG_c0{X|gpkp2c-zIU(Nf`;F6g_dEBw%Qq;3SZk7T!^oUy-?|R(fms@ zOWiE?wVR9pC^EdTr)Vtr`4ROKHZ}B_+JksidjgS;)(x5X3UR+fc(7+jo}D^D4Q@Ll z=FbB%npNo8AIfH7+jKu5OF6+Vtgg{=&4o{c%O=0}Izd{6>LL;ae;wLxJneSiGPpi! z6-yapk;xV5PD$yAoJg569eS>4+G5rR6)`l8-4Y3`_lD(7qh1Z0oNpJ z?TX+Uu!l=KSP9!tWpx6Mq+|6m@H_Z<%g4OmDx1{cwNDMtRj~B6Z#6RGMXWmF^twu% zIyW7@EW`OcCqhFf;w2MiKS|9x@-?iNEVZT?NAcq>N>KXn48#`lSxE1pcYI;4l!i~} z#=@iIHq@*Jhogmoh?69FJiTr@9yL^+g01|Jq})UYg3kRm`zWNWDznnA%ZHB9Q%ymw zM=eEJbJT$*ni6W>J*eY2XVaiCtMD~m_*HJ>uCF1Zn#w9N^5=HyqGC1+yMJnu;$vW~ zC{mflS3a-(n^HO5saRY!z{@eI^|#x?cWXUQ;|CeS1C`gBeZY`X2j%HX4zfiAHTU-i zHd~c$1n-iJgV8yYH!fY3yN$zDo_Vu0^I@q$DQin^D&L1PC1{GnEX2762Dsktyr0!#y~&ZlEfo(Wo;MU>cWny}D3PX|pd~2RW~hV}CnkS+&b#Wep`_j# zVG;u?3oK6+K@XEr`%mUsE|;Q&dw$mVOwa{WCs&(_zAX_qk$>E5NAI*Gh`Ao2i}LZkRdfWR$f&&S0#|Il=pjK%vY}SH#TE+Ra#~!hg+7$ zo;e!l!u$hg$#JoEj?A0%nGZogO01CnUPC3cXPP;*w@WKE*3UbI!=WhbQGP~`^@wTV z-K>^`kix;l&v)N%IqQiTLn5F>*HzM&yeaDaMrcd1P1DM+E8`#RlnU`onNkR{c#TYl zUa-uD_GOXbDgIEej!XAXt)Zk!oVaz0yZ=}U1x3TwL=&Hp)b9&7hb0*~;B*P_GUCJ$ zkMf9knb(RA+I22rk(z2sy$#9p)>R9&toGlgy+_mdUF9@28=M)AvXeuHzR>S-YHk#l zip->Zy(2>+=4QbT_6RmkOv?1aA1oKWwq?yIj3tAwNV2$&7q+bEk^1{0$@gLY>!2_&9#P`i`T}y?C;+`v>Kso! zXw#9x^rqZ69hJ?YspDnfZ@-`~$E}>yjC5{uh8fqQYPm4}<7dF*%=r77evk0XiA{@E z@U{m616oOT%Op``8Z;3GD;rdqIrDcyy@^&3 z+jDGd^%*k7Jy=BB91#lnC8{1Q+-hAv?^!2;o!jI1D@x2W6&$TCJ zrjWUpx$<1pnvUzKnQJ*s>Fxx^tl0ZMrEaJ6YOO7==^Iw*8#Q-~f>ep2Y-N`re6_YDK55`0~t@fe*jb6}XyjHHLo?ZWc{c8mx}ObPa>(YY{3q<$!Dnzo zD)ecz5h{NB#*m7rJfZ96kf8N)U1P0_aid4u{a@ejTuSfk(G zuYzw5U($=5waxeYUQpfdK|%x__`5juv(xI|`W&ZS4`(LcIPLZU?`pU-@J0)wS zLhW5v$itgHVaip0DG^`kZcz7tb)VqKZ|!R1bx-~}9_3r=HpnZ?GynUw)NMrri`5X^D<@;jFthmCr%@lCy&;zoL#+1}Lc8|Tb*mnzBe_3m+MiSIZyW4foC z{F@Rh*;>l^qv?8)9hrwLlx`l1Cvj3(F zK*YzuY8})|M!f+mXHVGE9rHgu_P81V5fkf~sk3Hd9WMU#U<}qeE$>@dEws{m@H6c} z-BZ5-4Ly?2lxByegn3m8Yj=iRWc{-x_?&Vt)iVM)mX0*9%|@u2Pg|d=WwSYmKVR7N zR&029j;=EVJK1luUYSGFcOmpTPt=8ez;?^%QAO);IA3aVJ!B0^Qivz8nxP&fS7kSP zwrw7v)OA4of1%I1TH$tQcYeD>>t;RP+*#RT23&b*$MPL_Q1-&x=0W^qJx?2|!CD~E zff$+fB{@NQ=&)PPtV#T@bKcG6@t~|7L{wh%t=#GLUIxeffnzp4_pLbfE-_=I;@kdW zD?e*vaGyhIu?UXMrnNl{+sCUu$XGh}5~|m&l?qAI8}Vf~u>cF>k=}6%-30;a%eT>n zV8^DgSioyn$BEIfp<2Co(Ws>$veB}ZH)DN;lWK(h?}-Wv#i6rN=*($$GUo2CeZP(` zuuJtt14MVLY%XE`nAEJZbOa~Ul=eu3FMw5YXxWO|Wts{oT?h`BRc!3qNPixxHZOWm zWfqEeKKF5Xu54Pvd??^VxDD_57G?a1Jp&b#`oa6F&U#qE$aL0E+a04SURjY4dKhHC zzrlctJF;kkZM&4N+Gy{VSX34l&GnfhwM&obutZ-x3M6y>m^MZ6&HFbsV|t?=%Y{FO z4bYH8%TYTM%fMM0T-#@di;-|}2{63ek)^SJU5nTyvxDinTDW$S7% zk>1UUB{^ynho_vb52D5PW$!Z?j`**9KhW_e^ zOe563K98w!kN(3(^5Y9oiYt?U8^tQf#jAA?WA)geB0GNx%CW!c- zgnNJ5UqYSyk8Tnf0vv2xg);}!l|Lzw5SNt2+qVOOBp+=6e(Nz$*FSYaiR{hs_lvR~ zvWgKUT`8jhJ!a|LCy#$n$_RVLFGL?%0oC!>g$3qzg?~iHP!bmEMqd!sypF;Bc}TN%?3Zx`&jBxTMbQ11zql0Sg+Df2 zX_#H9m&m>{C#(R6UdawzVVfT|Y^AP!Z1^95n*g2pDP69Jk7Ja2mW}8Q1@NbczkK2u zNLI?d>nBxKT@s;q^;O(ft(LLhktr}tC4`vh;P*cg-X#jz99%p+IhT|V zcYt$W7X1fu696}f$N?Gce2xKs?3<_7a(IhRFktp)- zr@Q3?8_5|LYpPdW3^X0>|7(Kif4=YksS;=ZX_@x_r+?M%<>rjPv-OeD>K@F(mMs-R z>DDpR&fB_JP~n!EzWh0Ty42)nX}4LtZ|ds0NW*+sGU|<9lSsj<>%@EP+1Z)enb{8$ ziM2EJOhR*so1S>d1{vgfsV+V&H(7AMMo+2f)%D%kZu7vST?4AF?Kav-TZUW0h1wW_ z`g+AQa##J%(`bmEJd6d@LSLBy?&aefIiMfzg>?dBOXfa6H@|wu3@CbT$^#l8qO5O# z^8UY0{;$^fuY2RaM#_IZ3jQ+>#?A3h^rS!ypUou2OBarc2h4UI8e@#AfM(d7^?&j4 zYtYgD$pAq<*CZuWZ_aBsCkiRkBqB0}mI~T6P*XS36wQpZO`jQvGnpyB{}eTg8hh%+ zoZOSg1v=!ZD`WEW@0f&?p44o&wQc&Yq+BXpeKc}*wq`$aW0}5cX9a}Z=0k6v4s|^o zo18SZWS8rUGE-i1#^Z+r5A!|9Mm7R2Xa6Gl5k4R4?RPm@7ofVA99V*y9{$m zt&0+#eZPSmyW`yCaoLXYU-JNGNKO%s*GdD8IM24e5HJ|evlW}|!63OljnFiP#?8)& z4>oJ~8*?p}BrO@2r-48S+4KQg*R+ktOjlj92NdD(DGbefeme)6sDsP2bHLLV)-qTH z&M3=4*6tizn4hLduhmx$dHw4Jn>xE}U*t=l{WNI7DFR)vwYS4`*?Hl8X}A(^$LD^I z9rqp%-0u)AZ9YSy^EwankFzLNn9?+oRhKq($ArhslgC2=|Hx{P=Gg+q>~bL5TM}FJ z0;pQr6?hPP(l{G{?rI5`*OL&>XgVz&VYs8;VHD%_+;h)>XwEna?$Wh0Itd;G%~+n$;5`8J({tQ?kOIZvuG2{&Sc&TOuS2j&y=2ONis$3keAc)&rQs&TSOntVoeN9TO8gu z=0%D|<`);aPZ?&T8y>jS4*2@7BuZWYr>KtkV0)3Xvs+1}6y)$?NB|O8#cWBHW%0(1+YW_>N)CJq8dWDhnwfku4|FhpTGJOD)`#LpwxHJFi={mR&2f{e z(G8-^bJs?mEx_as7BCuaab~%}mAWzwHh|z#b?SbvHFpLkHnUi8W9hj@An%Uf__+F9 z6lQc$JbuhETEx|6sVN1clHaJw@UW@Y<~UkTJ;+;^6%@p!eu>K1pU=tp?e8BnY-j|P z1T&N6`2{X_&Ue4EsOaw;P0N71Mb!$^(4mVs=u^0Pdet!8Qj%2cbVu52Y)TaNy++{FZirwqXP6cU(Grmr-yf|I z0?&c4@@VSRm`r(1|MG*0rw{$w{~h+R5m8`UU0zUG;AI?L>F7-uPR2hk@2Y3E`& zA3?m+aL5&ip@vi6UbG52!>SPW=dBj~dxqGhB#rp)L_B7My@+Fr#)y)3wD&k{FZmzY z4a8v}1rrdQeV$=z#!GWEbC>4Y6k_z`=2EjD+IF3ToRN-6T70sp3>>6}(iPj6%pnA& z6c%ni(7rroQ0(?^n^-OhI{`{n&=z6N(EcOFf1h@;D6;Rz$5UARqO~SiUcTk9Np(Ur zAsUuI(86$-eH$9X{bqP$=kco#yBGqKN1FC zag5ldcasuTqbsb|qAy>#IQ!x9xVYBp0=Oi1UqR+h2LWHa!#e{=@1<~pj9_Yguaqg* zo#;FGYV&obzV;UsXx=gU$b`9)w2b}EH$}C<9L4An?oivJ$iX*-H6DNGK@hb*opZg` zI~s^lBgBY446;>7E_pEI=;B^#j5#8Ih(j2m4fE;+a6h^x&_6Y*CO$y6&VKB^32=Zk z)cmw{@o}}S%{Wlz4=ilaUo4D<*q&mHM~y2RUP?sk8Mfi1{^hI z{FN7h2X$3o;K}Tc|0mEOW5A2%6-mU-CM}zouTmCxcuuW&B!v1dBO*anbwoQajaozB zK!@MAIR>L|Pp#T!X+h|#Gsy6<$kFG{9a#>sb#i+w?WO4B8kZ@f-C&Q)Myr+)XDf9a}NVR5VM~{C<^!c7Y3r$lkA%jLQ z2b}XMWAxcZb}^zwznO)c-B>Q;yYl0 zNu&Fldz$FPZk8JzQ7EwU@-Q&?C)XE-&%-GWD42>O=ETIsMF|sy#%uk@_7+>i{_(gP zTj2H+;rIKgD1;(p2z zGKz|pn0sQr3Q{n%J~R^DSAfRw>an$R9U!}q=mCWsaQ7HC^2T}%gp(p6tg6OM1ZO{5 zR7Js!D4F%azeVcKh!+D^%b=UPAf?h@O?&;=7!3rYu+voP9MkUiXBHhxOMoZ8cFH)GK1*G@|W>0bw!IuGDC^Z=a5HmE*jo2;Q~0r+AwQSp2qk z{``C^+33;ddwj_g#A^MD8}`vrb)P#MNwbI_X#JRG{4K$bZ>o?LakH@uw^?B5GROC zot(N+3$n1RC7BFn$s%?pv3akS%JYmQ4^rkN5)Uh}`-PhR)^0n@ME8_MDv*2a!*j6P zL9MD++aVua5_&?DpZv2^vLGhrG6u%>D!9236TLOC4l%z9lT;;257WEFVSWMwwm`(y zKtny&Eed%4d9_XUza3*4*-G+qos(|N!Qu60KP8g@;gA_w_y!Qbysaxqya6H$pW@k? z4H(#7JsATym(aA@4RgciUDt@lg(tEM##qRvc+mcYogux%%Y|f07dDScUeU`D9Mbga zC!}G(E7+FGnZe@ON6dCK-+&MMIp>|KR%tdZo&v4`E{9Az5EEDIj<{2_Tb;~U3%6NY z@3WULW(ccRp&}2&8s7l{M5+HqosgT488K0&3pB*lsAYcSlqE!YSC zmwTmkh?(7W=injt!wm_D6|T18#5cfmanipqT^#n(_AKIQ=|lzuJf1wNx9`k~sX;I=c_|Hs(py}$jgpSQsg&4ue6 z?6S=!K-a?IU}ncT!e7xb`WK!C60l;G&Sl`41nr#Qh^?|h(kuq_)0eHAG!kl7g1a{+ z#?-&8KzxDDNQQ6prfe(zvnGq?_Qd$-;r2R)5{(*{!A>_UUc-)ASS`;;l;g@B?^S<%&}EEGeBLnC-?rdTX`2` pL`0XDB7a)3gw4Iw#eYL}?EUzI~D)aX9e*>O*kR1R3 literal 0 HcmV?d00001 diff --git a/slices/021-permission-gate/proof/ac2-approval-card.png b/slices/021-permission-gate/proof/ac2-approval-card.png new file mode 100644 index 0000000000000000000000000000000000000000..b168b1d1a74ddc251db1429b275a4c5a18e57b82 GIT binary patch literal 69769 zcmb@uRaBc@*Dg#AiWhe%Uc9&y+})kx?jEcZcXxLuxJ!$>yB2pRXabw(dEf6p`}g<` z_I)(RJ;qw=%3RYjbIpV)%1a<4;3L4mz#vOWiYmjve3XTOdH?YF{o9-KLvRBO%oi9b zQ6W{2%+qyvLCpCbxJyp2F{e|q!E{3ZT-bb4{Cs$;SgIst{iI|-49l4!Yoo~7fs&`H z)yq7}+2uo$HZf6lDr}hrLSbn5-*@?h`|n2>2PgDjIonG=w`aZ|eS$(D)2FApyu9tt zT{jyYXr3Mb(YM3j9-E-h{|HN80tx?>YG^)l|111Z`Qr4i@Vofy?!UrMIiaC<|422; zk%C{b!-B}rdOza^e-0F$xju5`3Gl~70x}d$PrY*jk^X0eCQ)swDJA-Pidp}OueQPvor{oh)ti!WiaNxF5;co z1is(F4ak1c_-bOYU)$_HSG!U-qm1t{)cG^^!#{|AFlh36g^3D})FWT0ms=Vx2hSXb zZU{bnA^);I5YsJIQu4YueM^pxYti7GIMPzb(%2TshAWKn&)T0@KSDbL<}g1X-TFmd z`7tDH{FuV~NH1q|hw|P(cc#8l=`j)LV`&LrqQojnZG^ip5sij0A}uZ1`>$RaJZ=L) zlJq9H+R0y(8LHW3I;U0Ed9vg|i&r1C8Qxj6;%@)_R*+-xQe!uK6@1wmG)*ANk~W69 zR4&ooL`YPGUZodzU7XAuirc9F+EK*~g{gBIA|lZn ztw~mrE>hi+ALux`-^=gRyeb@lct3I4p}(Ei;%-r0TVG$oj;Adz_wx%HU7mkQWy5V( z*~ohW(pvW)S_?m{3Kx1XqO&>!va&vuf$Hkw>t@jN6ctYDxEi(f)TNJ$gh(ZbX21ix zi(r&Hc6pj_G_Eg3jTBoXZ$1$vMLWGJ6WTfSgPO{SP0EfCpMhpRmIYa51T9HhFdd$M z$NJ*ip0tc57};Ov<9kwTdj$m;&YDaQdw{gM)7Vef{G?ixXk`@~D+ZpN6L6%U?j%oU zxP?!&x(cnyt&4kNX<{1?+)S0&=tK_w{k{Ak7_*aSLiv+CC2VaAeI+$iz-+Pz0|v(8 zqfuU7RYq4MhGXKFu+)oO41Dz}~viz4`vN=?`HSIX~s zyrLCbhZEBdx=@5jh=i1#1q16^Z_JF|U?dTZdO|V4>^D!^gnBCDxcxMm1c>!8G&f0w zZstdWaz#T!;yJ$mPx~loz-Zz5F`kq3b0AI>f!Oh_{CA{#2kJO7gG|pf7?|Jud#Abg zj;xYat{d>@l)&iC54_fz$;LKpC9GT9tR8yOnIT(@qSwe(4jLzz%Y|Rogt@o$Y>fbs zQoHTIyRlE++Lf+3HN($&@nHUD$>1JN9$@OFjDR&m@Y>gJ9HxS4pBHm%fRO>Zh(bo=>nt zdyQ4Pc@gL`nw|cyY%}ka-ND={N{~6207c2;{;%lR5@2(MERI*U)w_N*g3TjF=KD+* zxATaLi=iq-gMJ|FCr@dLKF%SPf#Op7d6RW^tzbS1mOg_4%KlTXECu|ezQx5&CKcga z@tG#WxOd0oj#7`V<4<+WML`JaD<|lE0|2 zkA4n2o}d~a>;yOVx4EL8oTt&ON}ivk#Aue<&mxEw?JpK5=@*%?wLO{0*9Q8jra39MhgcHHWgM8C^uhA3wgrAeL=%^xej6ZsI6N*b9L z-6_7ny?dCYQ`YXzdeaAZmDqpP^4vX~9IkOo8kk-NGfw>KAt=mK4YN-1okWSHsEV1~ zv*N_NBH%T=OZ*z&aw|D@1bJe+4DgBpN2YQylQG{&W(lJhIAsy$ZE$&s%1Wce)#`SR zMA`gi#h`w$ljDxBwlWM6>21zb*)J?9qG82axE?VT>ZR(W(n|8!b$XOh-Y+yY8<}xV zY|Pwvzi?v+h_7>9?<$myHqqa&s7hw^k*hm9v&@)b823PRLpfRY8M8Ka#v$ZRUmc=W zCANX^WGf0V#LpDxiaO$BX9Ay;y}Qa$=r^L*FM+f>e>tws!+@ z!8hfzzoH;rrxhz@l{VU(3q9blhiT-;7yMUr`^6`X{ma#X%R$-T_oN3eVi6Y*zw%DH z2@EKS{ob0@Cdo56cw{i+C)({P-jnF7FETtgOWJ97y*UxU*L!C_$I@zK^m&mjn<@cE zqGPH+;_&o!LanTvH>;F$iox(BSp-0A5(OAfMabj8c*a-89w+$YM__|=G8%fEX65wU z8FlLfX$d`B-;XAa@d{MDV_CNTT}33CJF=L2ifHBQ8ku?cqf^s$632%f1y;l@M*GY! zc6^9qKv5=$rEj1t+Ra_+vSVu>J>xwn>E?xuz3e;QO7t>HntdpVl#Uk#WdhR{S?xjq zt?ACGWwFo+#Ka-ReJrCcfGtsUpNd>M=xKqur_4#2W!5BZUOWbYcd%_a3>hWLz|b37 z=K*$&uVQsMFF#VEc-e|)PH^~@=BjBER zc_EorjKXyMco00>z1sAuZ0W5D((esMVJ30VOO3Zjynd_2?k#wWrV_m)FYV(Ks_)AmnyG@TN!P5;KGOMNz zA;VmNklxbQy!DK{8A?%)4#zl@cIBP$yeydpD>g^QGgPJhbKS&DeqZ7)nA> z6#?|P9I0Cf)QP*!Us`o#354aM^gVf+=e1aeIpMV#4!#~A z40K(GQXJeL6&yg5CY#eq+H9be4q6k*oCa^fdLUS^(*AbrF#*nHi&H8qAvqDZ-u7&u zn}wS-gXC(v(6P7o{n}ib)U&T{tyxHIQXHGb4371HTilmMG6rTdX!!i|!?eqG7;A}W z$ipz@NM_+?%9sw?;G$aVC**W4M-!7!5CwqW_aq&QAZ9}?z|@VgS-*av(t9FivrR?f zu1c?!iZNk|=z2Wj(V2P-5N{7e7D=hXPv&;tj;ByVuBd7FgGGHwa=FqMXDHO=>x2i8 zTWgx9Yf9mKh--?%A$eC&&G?Xm7SiT%jbT9G3|-^ZDdkjdN#1ccbxI=hkk zSt^ihdChdC`NOI0pxG=bxD0DYUoS&s%QJ!7D=SpC@Py?*~GGZ&ud1Gy#(`!$3vZXa4nW(iQ zal9=EDV@ts(?s&8Y+9O=$>7R-Ml|k0L(61^4Y&JqO=Rl#tNzgQcU=&=38}ECFcn~M z(6mP1HRy0~p3eQ!K8(#|p$(Ovvy0o-i;8)Y!DOaR?8CLjWNQ7mas}7ub07eFpzCfM z1~_$4LbTp)w|Cq!stcC*>?5Uw=q|y))>U+)?*V`gtI?5dn{~9EvmIcw*ex{RJT`^7 z;9NWdxAKXO)QWSOX1%i*M-}cLtG^lXs1DF8KRv+?nN%Jvr3%L&?<|J19H<(t4a{2` z&Cs0@vgXjwwjFJmKkZTzmp#y)$37xIZ=)KI?q?F&$7o4c6!P^RrcBcFB#`ag#@Sk{ z+jP3>>O6#(#uXW*@mn7*%O9BXon-2L<8qVI9AVGJEHY+!L|_jnhjiyhS$U zuZVqU7s7;}k+G@yA+Z^!jjf5pq-|l9ERHd8M@t%#PkJy&!lB#h1cs*7(?;VUd}=(h z9uhitxVa8G1#TE_>pNaroRm2h9+Y4B3>|HDZy04 zK0sA}tv9Nx@RLiZZZFfGpdy-38)zH(0zU+5~ljCf4WAb z*6tF$&KgV-c~MB9vw1)9j$%s}k1wT9l+AF+c^M(=fg}|BWM-*-xS0JQGZg4-Zqf}p z+wozbfvgE?JG(#PT}c1a3#gpYWFzGEoBnQhGQx?Ixz9(E!DW4ZV0S}TEoo)P7@t!I z6z+@n7GM>X&%B$UH=Sqzr_o4p*S$0BnjwFLSQo01Wgp*GrIq7r2&Jw64fm4Xe%3Vk z>2y|DT9sC5KlRg*m1-#GO9S< zn`eTFzWYtz{v5NFp&Flz1Lr^6)-riIqrb*8oZm?6=wJOrj5wSiPUGF~7cG*wcdW;b z$;b^|Zvf78h!$P2vhH`WaF7635+{&)N z(Q^USH8MM<6k-CjE=!q#sErh+8`Q9LF6V(tNT!rKk>x%>%Ox$maGv!5n%d(D%kOqy z(IS#odj^G%uq)EC{OkubTm9u}9sSMZogumTSSqi`ACmmcJ?C zTBQiV6NW{oT<7dfx_vItNoRVyv*)Dm%Z34eX)N@clp@(2DqbHqNdiQ)VV2yrDhO7c zn#(&DN}Az#x3z(YUb#X^AspbR0G_Fqtrc!~QV?n`X@Nththhn?kgfVUn1xv$RuC!$ z7_R1{`Ibj1-+C96t?fs>eVFS`kIn>@^RDYbbn;ZZd5bOb3`?yBgcTg3;JLt2WHz~? z9L!gjunD`v6*Y`?^^3oPY#RNeDDZM}nM7;sNlj7Fp55Jd?|LvRhNJkV6$V9Jn$t** z@}UZ;6Ea2)*euU?^~^~cBYc+Zg)-PrGYcGZmN;J#?vXZfe^ zq6NeJEnDq{3*=OMvwxJv!tFEHU!bojrbz~+WZ1(Z;vIaYuE&#`7oC5Ql z?u4kU$S6i&=UgAL8#dl%J8|qpkCy0Z--hdfCBnyQhYhiVE3-DQF!P{j8yD zp1vJr5NV0n(9^(VJjdyk$3v1Tq4R#ims96v(Pw-LriCynre)X6yK*$@F=bP=2u#<1j+Ckj;I&l=x8H~q@>~HBRw^{Q- zZe}Z001&-Ck9#rWbyTFT_H^F8%-Iu@k!a0R-iEt!w{^hhv)u& zzG^Y4nw|1#biu8QFAn$U9tGw8&Cys(lJe$vgLq#yIjtMo&>-Y$;j-`NXl=1o%&m6o zB8P015=)no&3#z)*fxCW+1U-Q!#d>HJ=BNnbLTl$(i~3K20;6H0?cz zi$18WhUtSx4<1%DU%Ja7$DmCIM11VCG$}-o^^SZA^_dQf^WB2?>(=y(vi3q0{%%J7 zSv?j+eXp2gz5UE0C_=3K+&tcsf+`9*9Es&zs7yi;CL=DjSaolZA?x~h?9BZD)>5#q z24-)fl{KZGqNt>=Du>lsF4)|q!E!_U>}KTfd~*1JYksel4;bP}&Cq0%PC1vB@#x$Z~ zz5lt)*ZFgmyV8Df(O!Av^Nv1;LLtdtZ(r-fxVvZZt`WM!^MIKi>IemHJnmM)6oV5D z!%V59w6p>iUp<@ExCvO7`y{QG@UM-3f8?3$pIMdeZ*?zz>SxKq+04l9%4mQ2)AR&q z(K;@4!GxJfVnx)atZAr{UmG%;_KGqJJ%v;{S)b~vu?hacL zl(Wa<52^BL1u^b~nmkdp4+H9t`hIUf5j8#3Ak(OBDor)d;YdnxnHQ#R6WHx(y#1W- z*FD^cu?0qdeE2@1*^nnM? zt zjoD#oG$0ehveTV*k>ePkz(c4BKA$VQ@U1H-RB-_qc*)6c-(C1V-CWDn@|nzy`ZRh0 za^!GWPG+;bF}UO=4Cvl^R8M!2rf_{eutA6OrmgU*|CxSWmIK#}zh&zrYs z(v^JAgv@bsFp>9q2;(D3=XTEagB90m**M9ELHjH`(7XJ~eR0w=8MXbEiHHhfsS!{{ z@@s_kFx7@qWoJ?CEC#QJf6vstcsbhtt(TU;cjT(#ZuRGno-BL_F4J5dDxKVqus=(9 z=|$#eXJ>Y(sK8_RxEd5SdT$U?;A?G}#E@lnyCG{jtcH&B4 z!NCz8$LP}39=2Fyl)?M^JV?3dj;GnWH70D1T^+b3@Lk;~`@l%D=b3?ap|wYQw|1w*|w=QF5(Y znE?Wo7$|x^=R0v*&L@98se>G2?_mFB8dcypC*SnQ}T>xgQ{iDkJkOy1jLAvRw4s zW~_1^sX`@9iG@NnyRa@GEa|FNQr z^2ZFIm9$^6UQyanmr0lu*o8%}qyq^r)q+mEBw@m{x}=9>A*G>1KT!6#31$JWN6BJPmyYvfUx6fUY+8h`9;@k+~ z$-zh&?z;mX*xazHx7*6znHsuj*mB|++8~pUgA)0_@%1{c>mpNw2q5cHKy(qhL>@pT z9#$z6jiL7Jc4hh;u2cG7Z~9G>@?`D{K72r{GSJ&zU%W>PtyCp z=|z6}jFd*GIf4r291p`vL~IZSTDvt0vSbS^oXIOanucS{?E?PByHhze&FCx)y@|GC0`p%i z%3#^iHSJ=lEF5&$BhHml7APqxQBd}%)pwnm4|2TRZjueaZEfJ61~Isr2eITGjw-9# z^7!HoJ5-h?BZOU*q;YfkiMi4-VKRPYGKzwIKXWln-3{QCh@-09@xphy-;L|WmrH6f z`&_R`k5{b$qcWH|zM39ANb%09&E(d~q=+Ti&n$TE+&$d^_xo$>7Zrwd`5(`sq`UU~ z#`33~@3mwN%=Sl6bGV?~lP%oF1O28>cBHdinwTc(Yz$P4)U^5S7t!9$`g)Qhi&D4X zrYcV?JJNm5mUO5P;-_2Lmf9(cY74uoa7)vHCeA^6>2jI-Ay@4#%6;>e`4E1+kTfUy z6EsUVfOBgY^U=^f<_rs@ce{w^#lLK|+$fWy}YWy3aEZ$-{E3(0(9l`ROH*QbNjD z(OGRHygaAUwS-Pic~nEmQxB4(bCU`UFAZXePCaY5k$&gg-kN^2rKjLLb~S2p7y$Hx z^KmTaS`eEpX!N(X9_pfK`Ex7|o?DkR($Gi$!ZhyJp3p|SfTqo4^5j{z$5^I{-Nc1c zL7+O@l*S)aT(&3eI<^%t)+gABGYzQ3c)8%&`MTKgMbgNa@)@(Qn~rnBf3CE00YGed zFcTgg&I1dp&N`kp=d6}dapc0|FQ}M8_G_tNG1hltm_Q(gTZ8O^(^432)?$1dQKDWu z2+3!EjboguA|2Gn51J>DGMJhOu>tv8=Ih67kzZAk$XZw-s!=?x!1@2ZMMGRH)WLHf^(aVXOK$H1rpQ_qmj&ah*M-J)@f` z1Filh^vb3qezbeGTh&Zgwpc>dMRJMNkiwLtYB290$y!$oOrXoJ-JLw_8Te`4YIqRn z5_W5jMZ*pGghD7`{87hnWlUE7oMc}kM2A7W9b#2F?=m01x~Co8tv|p}I(nwo{weTN zE6pqmRyib+5X%p$JRfDmaAwYUGt}h4_>H9x@U>4Q&V^0H)bZpoiv-iH-7$BLsj!_O zB`$eVYwaMZ2|`?YiQ-vqIZ8rwA0fQsdHjy@?}+ zQw=Z8E&MwD?&Dkq}QtX?mNV(m@}Jdd3rI)z^G zWUjv2#S~&p4bzU7F3!fPG`G)(5fSyLXK>2UenJ_K+RYI#@X9-z!g=zDJxNi}vtPeY zli;WA(j)VHj`kbi5)jcD4Xs&%*9r6t0*v6y%~EEsvKNI(WN^VP41 z$D1v52>u(wXrpsLxe976@EJUQC(7ES>|@~*?{5bD^&Wz;?IpqYwSCgY+M|1*NFU3Eb`=~y$mZj# zkNqX<2fa+4w5$|^%GyzX;Kx>;5W+hfTFdXl!zzVo-=d-(DSb)xydM`1?TEecB1ie! z*f~PJOb&fZcf<^1c5SCA%J5Tl(bS>woA5b|q=|8?%`l1z(!+`y`rv(p(6UybV|?8% zo5^jg$z;IE8Iv0us{f+g)t8=D;BrEYrF;Z?RcQ|@{p{yET1f2s;*EjJu2f{Rn)nUx zyYWJ5=vP$Em?qLrpj!I)m@XUr?w84$cS341=>yWRo^!X0!gE*5Gy~$w?4X_**hSbV zHS1=56kJXpkJ!Y`rBW#jkwoSS_Zim3hQO3!7eoSquYJw7icDP+fsj61omsx@40dS$ zXTLU@7t+q2Usm53H0mK%=A&{_Dv#o*5lGjU$Uu6sJ`qoo^%cx!9O@Y4Ji1-p$_(uO zfvSzvK7-e8SDoU6nq^klD|=!&Z@aqd_crX$+yKjyXh<#&H4>_Fe?Oj%YptE3F%Er( zsrHahE(Kvg0R%e!46(%am7AFfJ`PT6Bt zAcUdYTgCvbQORt}yeQFldm_x2Z)C>LCD&@viZZBYhcXyW`eRAbSk!yNV9|qA>Rpfv zJ=!TR&E6s-<(;)#-Nqj;F`tq&OncdWt0j6c3# z+YUYS{qaX;xPFR4o4wK*kb$cED8{SF(Eu-Y)3{P~+MW0EA}EpZ+%gpKO?pv_P-{n; zUE0tlJFhs{SX#*W=KhXb|V(!3&B8sk$Q*Ga>ijEX*9}2Q zYg!xh`NM84T8x)IpaBSeC%4Io!|)2pXsiHu)GQ$&+H4(vVCQZnP9gUCW#S8cQ} zOYNRe!=X2xL~sp$3eMCfVg2ESRD7#@R$G4&15IHv;8?wkk1kZ`KV4P8H=FuhVgPg$ z4Y?yiK(r@>KI1|q;NC-^M??M}a>_k@1B9#}tJ{xo7@tiv8Qm{8Br)e*@ADTH=eOjsGao9N0zq6-gcoB=sw_d%{E zdzGI|79yAFa&~wjYQ_E4nF;aP**Ohvd(q3R*yk_p5bq8$W~pHfxFDn)W~bVcJ}%3( zMZ`slY0CWz-R~+KUK@pziwacUy>*3EGBXLZYo=3Ux}J}g6&jz$({Im6j7O@B31&uBax20{p8_2^Gqv=4LZ5o8~ zq_uYb{9vs1rpHO$SG_Bz=&dKy!*}i1(H@19^1NuyYI-rowAsvED|0}Mbr%&s&*%`e(sx<2q)?WWSq`@E;IMB$O;HtBH zw+Y~ppq0x>9S%nJs`k=dyO6lpV&^pj#59(TZq2xRcQS9^(9rp%3E#_%g{RTrVV8_^ zzG5jw3|NmS7pofAfFzccsFxlypcB`&Se5I$HBAtBD*mJ_ts@t8Y~I=14~1WR>dJah z2knbTrP2(1>)Sh*R(sP9meU60T{1h_5&}|B5yZv`nsF>d3;N3$?vgkzCRi@M*V|4s zEPPYwuuA#%d@fZHUFlggphg(eNTOuOx{WHejk?Y*W;PFXmMIJNlaSQ2S#I*_3q7Dy zKT6#-Ie>JSMl5UH@>EHxI?GM8lI;6=TWiX&j+96N*1?c*BEwMteUuA$bPuin}Q&H!~h5YjBpj~2Z){}FhrNl#cGr6-BaM?&I z3$kA`p$tYPZ=b+Q-rT8q)Ph4bz~*XKI!u_)yuFC}(TdO%&&uiCfF~;&P+Wc{%mda< zKhn>s-}Jlp=diVlnH(N}+?_2d{F9lPnSHo<@o=?MGMPy_kPRDJo1}eRmbf#B0egG# zdXQ6FRAf3&?~nFHu2HSH`=zVBwA4cIbx3-rk>~6MfI0xhvbPk^k|*D18Z>lq?FbIp zq(!|5ktD(z^OYbX6g?hg+#*StOkQMDo6qoX6JvOCbWG$sxF2R3V+GFw7m*zjm6}5| zib@Yv=r|`);tH$049D;ppQ=mv$i(IGc^QwyxRx=3>j?O<0M+W}d zIyn(P{UCOud#8D_pGwErciK2x9O8GoNvLhcdO(tSqfg;T`VA z?ukAA`mdsb^xB&ou1a?GFYkOWN0KUvw}un+OZ+sdpGIykg_uAU%j|whPMLp}wHUvs z-G4ef+7ih1>k}b@1PY@;O{gfcAgp(aaWmV?PF4B_s;NxaS3VTw;dTp+7;#U5gjFde z+p{spi^yyR(|q6eh=hFK)w0-;CUj}CbNnpy0a$L2@aUdJ$9_nzQKs1nwV#V@1$h$t z_^p(;87SMyEj9I~R7J{XyzY-sRQM3R(bH};Oh;EStIO`2 zNT}IcqbO(2)EQIp;?(t5w#mUOzqGK+eZ_W&`2$C<5N%PAuSiupuf0vPwbL;hPL%~( zty^?-<1tP{a(G0Nwp^LwZ;QsZnQiT6!nPs-(h%CHQ?DKHRpEJNx2EyyqM;GL#kB2w z8=lY}j)OTw;AA|=l?N^|_5*ecKZhT5#+)yV#dh#lT7;1{J@6`cHtj++7zT^!W&(? zp|boUC`CZK(Cb!G*L1O_J)EOtgHSa`#I#y7u#9h@{l{+C>F4=PtdB6i!^47Lnan#2 zi2RFHb;YZ(5gMM%zNJs8bfZK^AJ4GN9jJ<)I8dP6QI2c_Hw6M;zqR5L5}Xld^;_** zy_=;UMA9UE5^_uAh7S@pYWt)fQ8YX27g=E~a=~V-teDDV(je?FSTc`Q5q_*RuJ#%$ zQYJ#udbKaw8Q>G8f*>uOrQu5{#Ulj+lgnI7*7-q(kRlL!dg)1*3Wj~>jqPeIJ^$AG zw3|q{YEU#Ww+AgAv9$;cN{&h6<|*o_&s?%@-`^FO@c)A%PjUBa68^=FjJAtuv^>+7 z@Uz0`=t4u)a7xe%Y25P+>jn$bP_(J~zwiBjqF6U-ccSRAh>Vig)|*qJ z?=*tdoowa#EnVNgb#x}GvG3)ZatjMZdy^3Gh}JPOwcjW-l;D}ESmPeo;~`g+ITs6% z?X332vGCw$1iR2`C|#FB9Dl+{HowFhc{i7NI$nT0*YD%4AChzT9M+U*$xcF6HWgo% z`eMFJh(k{Ozck?i49tZYcp<0*&%4oudI1Tw$~g-zG!eik645t08d9*U{eQUAFl>PV zs^S%t$bC~i#wgSHAA$Ui@$-2k@3oP23Ol5%O@aayxNhgf!pbN3%hf0n8_UP#&fZ|W z0YRH?LnPgNQ1&=^$z@!_*SsWgdT3Wgf`V@T)Dc% zlrwwd*T93!eE2}11AkkbvK)KjKr8%TCOdXRs6qt`g`1mjURmx$YJT+5ax#{OXr%uI zmKcch&;>tBa) z*H}F_MiQ~4gk1&LS<9TAJ-{6$-s|q|2cp3Hdj3DXfdApu({$>WXq>QpY;I>5Pcj7@z<9L!r-z3?1*|`}Z(YJzhwOoS)g~2DHw_ z-T>gI2~o^>c^>JEhKctkmf=MOAG$yQ0ogDx4K9&CKL_3B_?sf5CujGe>1uqgtH-N~ z7IYSTyZE02ray2yy$Cu}s0);trLl;F-XocV&-&s#|X35j3g`c z4oX$H83M};gjn(XGlSu9frl$Dff21f`Yqx!%x`Fv67A7F>84wX;b%7Zf7IP_f16DV zt3LJy?9HFJOLC`v*WI?q2`2pe8NJ57Vo#Ge{c-)oqx=D;rC+cc>k&iHh}nN2`A4%}!+%f55);3`ziA`^27gsZ#Bm(rqz*Qe)EZ!NWfXk!Eow-dfO!&3xnv*w0?fNC5RUr zvUCyVh0}ff_=Y-iVpYfCMm)>Rv)JI(64W6JH^a(uXkhOiGr8fnIoL~1N*RO|@ycp4 zbfdt}Zz8Db@IwM8O$BHcY*`J@^u`f$5*_;!0PK9Z>xEuPH1IIIgQ?Mm4cJ)L@?g&p zG!~Y78wp{nUow_>4gnt%q1W*;MpGsG$Dz6Gc8P=>ZK4Ihf{z!@%;K(d>dko?FTR&< z?o?@WLoZK2h5FjVCX)bY!{P_qTUh9;?=!>B2o`VH`c!EtiogbbRny;rad0<8xtOtn zP2(VhN7ln|H}h4;SEZ~FRYF|i8R(go9pBzEK*-Z@ahbP@F`31eHf!e_WA`wW$2z_jG}Rgy_`w*rbHn zMwOD?xj96w6kfosqKD*A|EN|D2$~)I1z*yv<61iBd_6%~S(!!gQsA(P4@?fel2~UtsuB{{=*gfnB@lJ5X;}I zz0Rjod5(iIYMC43%bp_=BxuID_?$MWniMNoI43J3X?EV-HQ&=iWfQ=th&TvA^2#)C z)*}8h`pq_SAJ4cwY9z~mWF7YjKF|2K!3Hl60hemuUT!ZYmH={i0SmRMwBqkq8p*-J zC%=p$@%G0a5%HrICRa0dT13LaiV>1CI3ozp9vNevTu`&XPbbA%7W-+>exuyZ(0*jk z?J$G;*FRc^($VVAebkhn9v-I+%L;m59v+4yNQ#sOAEs)}9WJ-}M5)Un|MBC0{bygI zpoiq@%8qeDkH?MAjh6d<)9*-9!prOF9w_wZY`7W+d!`%3?XK|raK<8)rppzTM9k2? zqo;~?rDfR51zF&F65zrGo(ZyLW-h);sUL67xc9mgg7bP#Y+#eANRTS(Y~zpj<(_Rg zKDG9wo-DpQ0e|zs#oBmQG!hn?mXm;UAxDIn`u0zX`AvHYK=+f2Q=rpqI$bu#SJ54T zi(ja&ZZ3&yZ<*>A>!*Fvu>bo^@Fik&RWCvm@>Aa+C3+oq;MRcC{9w_*`|4o59kfSx zC?Y0gxKboDKl$VVs(C0BtydWLK5P6mTRfh{#=SF=l;!s#6&7kNftRdxpe3)JKaHod<_i)$VdP=X_jqN)aC9Z zJR2@T6H)nOPm7z)>%(*PNWC6jEp%%A0}(Idbc_sGVSx?TeGT5N5fwd}Omh>fUUT&U z8qfzox~=3{s964Qx3ib~6DG49y<6~N(tsp|O;}r`y3`)z`GSC{%jJAVEZuWt&gyO8 z>mNw}jA8vu;_(rHDla76+4=}%^04!hv(|__tFtV(M&K~%cgg1PJ8g@;)?B_BHXtc^ z|7>gP_!M$5T`LkcVAp?*?QfpcQ@p?odJK(+fEcp z^%i75*_~h;b!Z1K?DEZmUdI;o3tp)@zW<6wx<d0RJVsD{vBCDGL;|Yxg_UUQDr^Y)CRgaIMG zmwP8$PS&fNQ{VqdT|dT`+%||-TFH0jeigXqyhG#HJ=RukS8?L+_B#t%Kf&VYi}pAC z@YD>_C{sD!U}bBmkYVlYM_#_Zrfk4_m{?gVB9C+|ew$>H)@g5(mh_R-{qP(J3!HaO z3ElHY6Y1?RZI);WoY248NnRA$`)9yI0N9Ck=6aQpG8pCaIJ#6pt6bmi7LA8~LF^;U z%Pl3Uc31ow?q?efN+=Hym~~h`1IqVL;GsVex~Vbt52)-1oaj-!9tL z*|}a}S@e8ohN52!)mtF``?9yY-bmEiLbY{TWQ0r_^lfEc&++;$X7f9;wz(Jec+y$U z_?kSv^!DMgXgF5p{(_O3hDyCM5l9zgSB$`0VrtT-Bgd!OmKNey+hu9eK6Zv zfg?{GvD#{;1EG|ghhM!VxjXI?%JZ*Y>)%}hZ&q*m)}}@$e~NzfJsPT}SHjWd!fv-5 z4sMw<+UYAOnFu{z*+^m-;cbPEDgbz$qOiC3{6APkNxc3bk@^!9z{^R$oE%%#>Sau} z0da6K(IBBwG9_BQ+Vdhn$1EKG?ViFA<5FVY56YI)ykF?_jvSJ5@%pX2+A|DYgv`&f@%Eyzx zlr=Oe>|T?Qr_378U)@tpEc-?w6Mi?l&b`de(v{i>3aDLGw~KD?yHH3G=-tTV`r1+v zQxS+ssQdDA!ppP)FIMTbS#~lZTO_hJY){?U@JMFv$!ofShB1grfV*}ir0#kpoZOcr z$Ij44dD~kQA@MY2x|<~%ss}xLf@(KcxdZ@mVgA>6BFUFW8_s7y;;@f$qKv2GjdX!v0cM0{?+G(ZxSu zi(ad7Z^$Yx4o14Q9N)_t-zHAPUIUIWe>d9Q&5QHlZPD*`@Lt@v*C1@|!IOx=RoGlc zIa}AGEbmAdzB=Kk+;pvlQ1atGZng})&gA6>Dr7$%ZvXC&$l+o+C>k%zl(`HnvyVhR zn@ZoS&W_T1^vkjD)--+Mey(HRZ;C5Q;*K+b;!4SejO^}-Z3y@)8`CjG5U9M($UX9* zcl`nqc2jk-=zO z=ESa@+lsQk4}Rto%ic;VH|7YHAO0=Hc-4t<4_!^6myQ`KQW?Mh4$;_mJhzSxg1p6M z#XcFOyx4nlwfh{8Oi~ez8MmVVjqf0+ORe6uBA$k;CzDkgm>8hnm$jhoHV>DrQc%29 zNgQjwZj2wdt*UqVua+S#tih0wyqvLU^$W;d(w_PJ`BuUv@LncG;X+#}gE(O@BwOjYBW853adf?BHiJ2Zx7PucYfHXZ_+Cn zf(OMsI@~rY8Bl(+B(=GP8!Z@`Kqi@#+W!R?>7hhncC@`4>vrj0kO9 zLhr%BFgD0}xq7kQ^IE1m9cL;DrZejDguW_M{^>P~^u3U=yefSyXdhz#POq7K=?F?m zNHUV(9$i;E>)pdMo=nmqXRxClw4Y!75Mhix26@o*Z?JwC!Yf!GHK*lkH+o_v!NHbU z`3PWsidt4tTXyC!kdx~aAcHLUVmIHRBv&wIkI|{`>$SQBnN*ywAT01+CoJ2;>Mz&+ z*e}r_5~1#5HhZ+WzLtHV)Oq_2zqzBw5D$MtCG&El4}MVfoL@p#Przvm{9sFG?hBON zW4(=XH;1j5|S5RB$ zN`0EyVT6|iiLzD(oBnmjCR6C5VpLUVKW{_q|n zVo_bKtAA<3v1ok>4&Cg+N3DqnWlIcK1EZ1L`R~pKotvl&^<_68 zdxOr~Qj>?5aO3QW<@3p^WNsH2MAF-UoTt5s9ULa&m6ylW&1@Hh&KrG)pv?5m7o(j! z9o2ESnX2O*pdmPA^HjQXpgX3Pc@VLMmub1BH)%2cbty%0j*4wbt#T|JkVt)ow(!Tp zw4*_!qwjxx7>t?pmRzk4^5ZrTEyR6lIV6aG97&ADtYyJ|HP5$!jZxq_J@^jZzfUEL!&uc z;qI5v`XCnLic=FO&`G0vb?vet$>|dtc<7GO6!iyist#_+!ikryD){s$N(9)>C&V z_dO?Z$x)J$aw+^Z2yg5@daoSTl9Q`x7e^xE4j5`UR99wN`x-?SJDS5AIl}m7#UTr0 zCieD=*az~W4ygvI&sd}}KIa^$$A5HK+3Nt~tvKxmgPqGF@an5hZ9G39_7lKXiyGpe zituFmbl3gJ4j?CW`-H~fx;O5oe+Q??>Tyet=wr!damemEeUGsBwR6QDKNjsxGt{W! z*$ww?@Xl=Auhy20btHb>oo6ZESn{eGdF(L+Q+6p#vvtXLiv7`VWzESi8mX3HtgTtT z7Uc?a{JwBL)^MVpQR~Q#`T=!=2~CozF~VsrwNK+zD9^TcrCC zexoU?Np)qtbmqsWN$=-St}|=|;y?=UhpEj^?`w5hc*`{8E8HM%%i+{6BGjgIQu1^H z;MwwNepZ4+=Hwvl*-;G9MSo4$O{@m!C-yGU-XL88WYQvCtuy~wEWamcJi($n0!N|M`L|%$3Nh2*Wf#*QC@?p^?7;iVQId~8+**u zi_Y$rF;?+`xp>Iln~y7PrBorS!K{|3?#!x5>Mw~HgWJJ z0`f%x zVlY|2I`nI52Jo^M-%Qh?8hfJ8b%(os7B4IvGmbIkz6tN;e)_CnKV>h4|K{Dm^{S&| z!H>!hN=is~o!GjSl3yJ)1nPG6#5pk;iuLr`Qndieya`Gy9GS))1^P3 z_3u9@nekIo-Ms&PKxzP*SGYQs=abUM?^1jtPnx&#hwtz&?aD&A`?^4sM!pljS!<^I zapw;#n2HU4A8juq=I-6$ty)v#kfo4{nptZu6DrBOg}6SOxd|AmyRr$sGd>F;pK9%3 z97@#+nfHu4toBmQuhCS?w$?c2FRj5L9;&obc_$SL?ooSdT4JL8xxVVqy!Nroy~@s^ z)lVkHb#a#2y4|AA-znmCj?OwOb4K4+TBmdQ0Zo1J2lM+h9}ucO@0!pTj~rjBlIg?dNb6KHw-ias{6W(K~^<7(Ec%xf1{2EYJ8xxPi{GWKFs zg8;Xn^8z(e+&qp_+`yX~jjgvY6SA;LS6evoua7?9IT#sKSiCsbpF9qZ$HA&_rY5eN zc444D)GIBpiaFjlC7f$=(7v)*ZButBm5fepuxd>)vx~~T&Gu<*=alzkoj-Fa8V4tW zzM**Z%$4_zw;8i`*cta9=&U=J)_N@KN1E%w>jebLmf3^2Ztal66vs?Fhxai8Ua6b|MbLqb!)4x)E0Tqj%$;JSeGU-r5#UFYspA!_D7$!1+# z`Cpa%v+|J)15x_u8BDZin_57rpo9?Myz{+3}lvR=DaLRtzeNEFU4AcB@eT41< zPldvgc6D7vMQdfNcA#z}2cz|);@BnbGVQg(XrC|jT&l{W-M|d{FxHDYk{xJ-f_B3fGqP_|G@*uVLNZ- z_L>8-7DtTX?l=*Ms)=5;?$0HvqOEQ%8C$Ps-jzSY_C8ZJZ*x z-?)ApT_c-uvfa8sHj%;svC!6R_+~_YIgEw8$LXSwkK|6yai?SKZ?t(+=;cu;&dPZV zAy*0gX`?Z3B_{c0=kN8-@;Wg>?9z+ovo13^ndK(l=Q$Kjr#otly0ka>i_ytV4c0d^ zsr-6>l#ulP@?@9ZjCUDJdsSGvmeP%x{a21+OJh!|C{&~w6^nUtugXA1ZOre(sjUSC zt!w>BKh1r$AmvH-tNhWid8{ywT9l+)f-{>^#3XvOqz-e>_iak_9{F<}tHLL|zQc>i$WW)ppv@_8=skMQppy zDw$7xlv{2c*u@$2w7TpyP5KhHe}OQx{n4?{B&);bG&nv?O~*2G5zDVz!qm&x@MGe& zSJxrj3|1dc6JzCr z+->7%Ku|;L8wxheY2-l?S$VpI3$yVWOJ~s(Icof(gKc#?6Zd-h$Lck+yrwCNaYcTV z{nRyMOLDL0h^TmnP<7p-~IUW!Eu!(a8 z@IfzE-`#QLgjlhijS^R7v;<1WZ9#`)!#~Th>&HO^ZV^8j=g+%{17}~{>P;ISB+uA0 zV4Y>39)Ardryff9hkT+H5$+d@4JVqG;+jFr48-dgMo1XtI{b@1ISCSYmB5q&Ik9CpqFbP+ZLt|1tA*R^EVIvaZJr3 z0F9<#LritgkbMaD5V5UU${)VRr&=1@O-;L7!=D2j6BXru7iMMapnY--ZVY^j=7p8H z7=dt&68ay^R$#47+tQK{a4qQ-R?q9#FHH^q!p=OE)eo?Ev_<*UKySZqv#ih0~9c z9{uNJh&;Wt9LMjXPeH+UXiFXv&6rqJksmlihj%eSn3<_Qcz}yr&Ey3+h9$wadqbdP zdra&rpe0`!SleV$O4!rI0z{qMKaQ99xu?xwr6-mxw~uV+FJAqY_p)d;=@??rT9WK> zs$~%Po(?n>4bg!k;|nHt!QdA~zQfyr@&HxvorH0izy3{%;om*duNy`cO6Jgz^0{E( zeS_G26n`O4#_Fq=DPrQ-Qj$zTA>uNK?vH3gCz!rZRAoh}eA>gNq%K~$Og@_CeIdUK z!u$6>N>D)*e}Un9hL_8b$$cwZPee!r&z zh%w;M6ZyZivirZ}qJhi)Z!zuv#S_oW<6)*EjlM>iIt{^dG5t(Mq5D5A3e+hbRU%GP zZ39w29_n?xv`vc6&h8%^_TIW=#SZc?|21yZuJ`u7=!EarH&93%Zm@>;P#|SaPEJjZ zx)@p!?kW?KYG`e1(ziUA1pF%Nvz;&HeR1aJjFA{(D=p#es{e%rkoa9f$9BBVUd{0G zyfTFV{%48N<#iRl6W3JBz!gF=IiuTv+%Gzsqj-JTl;@$I98jI4;6kmpFJofk-V8AT ztOXi`9g;9?P1+~DM@HH!EraPb-okkx7eq%|tlE~}2lQt&FS(4zB&n*qdkpkws_2xk zZ5|%!Giak~_P=^@`4U*YfP$HKUZU-KMU09*dYIYhL%m}ST-ZW4EF9+JLrwh>7me}$ zT#EL5uXGU5wb8sn8JOSO*f`LlsiINB-t$NsL9k$xyZ<@GKL26tRp>;^v$t!Y$NW#9 zqC9wjOVGGNl?(UDNHK-%L;!O5VP?b-1L+(NfMBD2Co|YnOJco21A0MF3&97uphO#x7R`t(V=5e_TvI3W|LUt>rubIx%~fd`!_3w+6Z$~SlScXMToK@d zZJ8LR5MW~z5C1dN@Y0r;44jzR+GtZ0{Hb3$X@dr@&E$Qi7ls&Bq-vW;J)lPTZ2>8k zXA+mg262GY%HPSXS&|$;r0p9I3;J7thPAwg~1JPN?Yzt6Glg)!adHS^ZqvhWD ze)EmP(bDfs5mzMk-Old#_Vza7J>aOdJ-QG!U2TOt09VuV+akK7-~xpeBd42i&+B>Q z>E^)r?wQ@@z$Q-JcQD>LrM2mc#J;`p~@=D);phWj=M? zx6Cr>0H6V<7<|0{)2yWCF);{uhfF-A^4oZ^`Q&o|l4(pT9{slMOb=59EtB#)_P4fD zzJ04VH&wRi+01o0mM>jC8im-p3%PQ;yj$PgOxA9ahlOA7vhod0balbutdwkJH8mGk zXS+s5MiO@@es(IVA~jaNRv#UlCyyWJrtzz}|J@#@u5dbBI6pr(+Z?o*uSyNWJQ(qN z!p!gLS}acDNh834_prw!M1czO}r(aCj_fVq#L4&Z;|jwY|xVPk%uA=2thIn>MA%9qP1=YuKYtaMbK(m6`(v93yWW9;vy&4yWUA9cz9%YJysw#4!#&s6X=UOQwFQa`FW2LBw}lWH zpFnHvU0o)IhDm8No=ZZelHCU3XS~i^L!%0UQhh6~=X;i_Rsg}&AjE|>^r-) z?#Q4~86$Z>iOXhjL_J?8mvXW5*DrmDc6551pyYBxbJP$Aj8L4dvXH}9jQc4{l_zbo z5H2BJaeA7axOSevUU}8tv&LaESXWcia6I$K^Dbay6u#)e^=@l;slYGs zKw9zc#txJR^)nYxSg$;q7Y2OtjM%3W%T4CjP8>bgErJGn|;Nu&->zKHnBg<^$IZN86NP@<0Oj)4|-_V2!4* z?%6I)*yN~h8|!6zj~AM!U9xu{AO`@HPp^dK`%V|?fzZ_9+nCpbo}QkksGHF}5IyQL zz}SmE&3VQ9DI}VY&-rL*AS>DZ`aBb#-4)rXB4|^nT5QQ3)Yn(Pu{Tz*Qr;GTmCM!x zYH+`1C5mTxWnlZR!KQ6*1W;V3tJ1#et8>J1w6^c=8E~+-XJTPlC^vz7J-FSzXlV({ z&80ONOv(JBKHhJ6{*APbH!ctMs-vUhGUa%O4zG@i*i|~{@SC^zs$6pyHD2_E+Rj`7 zzFb-=-{ZlwGjiAlAfNoA){9{s3<4g=OWZeN^aRkQ%Lr5HV%c8x6NQSKoBi3JtsY%D z0~|7>$ZSZfUAY%U_a$$JJxg^oNO5y>kAC4BtF<$W`x7cbJ?3BbmWkC~dD{!$*q zr~P!4?XBL$Z^~q@yQ1X-1m4j5-_-N_`1E*zq6Xrj40Rgzh^@u->^Du%c4sO*Wh^VZ zfT$16E6>;57Lq0t&mI+p+8)avEr$!ZULg{tCo3286xR-?>nEKbyQR+8w5nOY18_MQ zke^QnIFx(^T$B8``waSJSQ~#SF*M)om@Aosq30is4z8&5zax$6=r*|mMfD53d2u}r zFMfXwQ+ki}*$p{_8@SGSR83F)7c!n@zcpmJ6=A|{dDAm?Feu7IaD8!c(_}Zf&ju22 zLabmA8&}Qk>;u}PWO?~wTRXevTT5m+-GUYUMjb0-j{DA(F`PjM6I-eO#BZyzvo%$1 zwfK!LI5f0y>Qdc6lGlA>Ie@>Ohd;O@iySPhEPs6VA@w1;wzjs%Vp;i03>p8Ep`HSb zn9@=lEQTCM)6mfEncKGG06*d7CiiQMMWftLiWcdyl?`7b8yn|`C`CNxDtM_m%2)2Y z(By$-;komg0bi=+>c&7dV_=D)_N!-)1O(i0mMR`HFf%tUB;U{8XlFi2DRDbXnIi62 z2<+#sh!*eLxV%gUjOM$h)zC>@`cOK4e%Hy8`Bfcq31tZ=WMz6#V&$b#I|^(^>dOu9!=Wt5&VjtfaX4cb?UGV-WE^p{|F6YlA!trYS6v zF!e<2xWy~nl_s`xMtOtnI}o@vSdH*JC6|c z*L$G`@hJL1T5mEphWgV?$^JiQwOHlqOdf}++kGf2v0R;}J3*^s|MU&BhQ%p&1ARaw z^Au1@qO!)V>!6hc&v$U`*LTLB(2=IH0|Fwct>qf^Q~^o*35O!)8p z8!&x{!E2qKwJp+TQ^Rw=XlptDUn1at@96(?D2;(J^{zTXsxK}KGg6h@(zr--YO0pw zNrlmU42UL_E!17cY}sgBbnSkN(6PMvE#XyKDyvVd`?cnMnbO_QPp?q;qp_MoqNQ&Y zH1-LX2|#c8vWht$RqRO4`itRU*oZjZx3j4S2Cr(M#q~;3 zmrM8oz4FHyS=CB->T{|&S)5$TQO_HL0ZCoufd{jW7X^#l3OJE}P^%OB+JfiHkT36Q z{6aLZRw*R#6mIaE&FAM#Jw52mhH}ns655-Qw>96c(3&!dc3)L)A+=?my39d-X}15+ zo+S`pz}*sO8B&9z`}}xEk^AcS8*Ht4lRLu&hk{ zn1>F`be3MV4=+x#roLY8ThI_4`#bM>sz9dYV8X!!|9gdQyvh(V`R~dA<2)6wxrwV&W|G*7}*v zP3KLyga7dreRamCa@Aolsi*bkjF^F|OGeUtJf0!-cCF%d3KbZfeuj0zNl>5x2Xc6A z7bDP=w`ZB(w)@D)^s0=1_5QAi$RTv+P*VsxIF-DJ*e(n+w6!l{uo$hN|62#fd%m(kbeSq%e5o7d0t&U1L-cnj-*9jZ60@6LT+g1=!y$aGLa|XF znW216#OGP~ zXOh2Md?AQJOTNDd1~m58g44*LR>|ML1A{BW<|{E>l5-8i3cld0_NiJD<(N5bO~Vb& zg+`OPzf^V6WTQ{~k$e1ZGdrNgGCPwPdN#A}cE8|&Yh%k4PH1~b<$FtbKg4;Hb`$0% zNS6gz7zMCODM{T*4C;bZ(`q&bGT|X<^**BTTQ^%)?tiP-P;5$AhoTXwTz|X+TPN|v zfS_cF%FFP#t731J-~qRiGm#a1+JSAjL^3h8W@fb@V!%D=GLJ?mK*j!NpIqRzI{=OS zicgQ}lj2XJK0dVURZ~hTH6)UH4_X!dKf3`TyCK@1+5P?fDmDdkh?-&&yg;jjW;422 zv-yI#oGCJi*tDy16r5?B({d5&|D%REk zA08=XV7s&T4cEFXz4pMP;+0z*4)-~!Stoji64+ew@-hU%NVNYX`AcyjkujRF zQd$T3Q}&j~@a~}Gy(x_o{r%|a)#;m*LLeGT5TAp=Fw5^7sf=J_m>V#AMFya3FO}hco>mRx{q)tPY!Oack1SfEj|7F zUswQ#!FQpJq+A7Nx)oLBiW5(F z`tR_fQDf^AX}ODUv=h{}D~QdH(E=oR)BBM}uQ;3x3(S)ySC}rPNK8WBu9r5yeBAFzjr)m5P)%+xvI!wo+3^En4;xv}pdlN%4S)(WqY|DCxDE z?7zZ)-C`whNA03kMy4Wu9-vdru^TAwsJU&}Mmw@3a@l;!VzPDq8D3bL&UDuuR%73E z;G@hiULDu7PIJId``nd|or$lPnVBxom^3OqIZEWF?y1VGfLt+Mk*HGe4B5oMV*J3* zX|p?cO3YF5MhPtYsRCt@_~jb@Pp5q~DX6NoK(^+ch|xDL$g z;`NautQ3;(8&|j9--%5qywS>8Bs3PMh2Vb$|ZL*HvO?)Y*iu zQ)pCgbdS^qPvT_5=`B;!qoS-(u{O13|DEjIwbpLI3|IP}dA*{kc7_AjfiSDHNIee% z)s0ujEB%`UeW9#x*OB8g)j29Zc`v2nbPYmP-jn=yCNv@JyT%9ej?b%%O0>n=Wu@1D zG#15&Y4a>JqM~Z7Hh(1knLed+Z}MPocCwACVv$nl9iV5wJNQb;D-mG>G!`21^MBA? z0=YF(Wuf8I{Z9ute^dwWHr8KyZTQ?vsDb1EzoZ-37wP7IWR0lvef|kM7Pi;2bv5)^1Loe=G=Ha|Gfxe679oF3(iNf^<05IWb z`aP80FBWn!XQ^vpAELG7y!h5dIP5J z*tcbQ%`=bCiZF%499CR|SUMf=8nLpTh$O?%SJ_!@?v zF+-O|+!+Ev1N_qvjj0@VQsD!2e7Cp7kwR}jjIC_wgZlf^1rPuFJ-^mJ*RF+*gZ^k% zTV~&#QmFoAQUCpcp8g(o6QUm7J==0cYbgNMXpdKU*18u(JGlyj#SwRxdPU~eiuN7 z0PX$kr7fgtzTPSM3EyKtvx4;+!_SlA`ntU*8ihiYHXqj|&xOt@%d^u5=A1|dE-pz$ z`#M<<$IfgLNH zjNcy=Cg2Xm@i^B|V#P|Vrerusgl^6A&vkVLfc|8P1SCCyBKC$$b(;rM`N7xy969R= z>_+Uj{5C6(o=Q9&iE_ZfOk^{t^J%=@XJc*tcyKnU>v|f>%^+_KZ4CXk)Z&e&#<+)6M(a$t1P3*=AS?8O1i|M z;)TOzl@PgDdAc7zer)lZ6Q6&p=qr54{{%&JO`jisH9$f@ARgY2M=u|7RZwH{i_+&Q z1uql5~)e8H@e4AT@`tmQ~ zmm*|*FNoOJIzvewQhF-w!O}fhnBLLI27Fmo?ub#)w^bEyy= zr>zM#>t78Q9F(4_urniQ&RB0G+@GnfNWU3;qp{V$&rf)4pkC^+x>>AMeZ91}sRU1x z0hhTz2#Izt5hKl8ZOQ@XhdP`W@^+jPcHK$Mcw8aah@I-K7AcRb=wxvxLpg=Bw5pSM zANnm^YzxSToU4iNf5JovEcpjZ!&sI}b>jp)&23f5uhPYKoyY}URxU~$f^{%rPy3Ad z!xm%Q^u~b{68|DT)4A?uHLP<`@%UjrvU&Q<$#!RY?RM8#zyUtE$o9g{s^0D$%lr2% z?^&1`nORs$5Gq|>UK}uZMCaPd%F5Q3^YIETut`YTWbGG5dJP|9PSqI>oC+5&qhjQX zV(EM)7Ut#g!j!QHwaEzWRNa=%mSk?Lkra`qKtk#C^t5@?<;HHQnu+!xw8BJT#FzL) z_|Km|`ugY7E#R($%Xo$Pi3Mh*j}Ey*%_OT^qW8v45n(g~;#B67CEDhgwUboTRHnI% zp)u`mn4SV3&~aDtvC%^z5#U{je|WgDUk&5q=hv-2x7wL52LPQ=e}4P!lOC?h6=)=l zB8!2POYsZFXh82{_Y8`wwleN&EeO+v;iOup2uP(z{E7ttwJU>qSl0&%_l&~ogY$e}-?c=i^ zKcS$DQ2tXl|Ga#oiPyY4|CnU(72Jb^uyOj}VnuC}Rt6f9&TFyUpT)+3TuZrjG(0-! ziud3M)#P&Ac+j!m(e0|B$pz+d8DDGd!Y{rKN#}Mip)xt)?una_77rs`Ug%7v!zxP% z4GjgmUxCPoh>2&4HMuFlRu*qv4fNUB*|&Q3y1OXie@9`KHc8V<0@jDSOP~I76K_xF z%Dfaw7&RFr<*{z5=&!Pv1@zi0r8PCp;bhct0Ja#80^4s{=N{WTa>51&`Z&QkB?V-1E>D6n5uU{GoS<%_qLZ2)`_0As5saY;$tP&Y2hm!*`aS65d8cQ>cpRtvwY%V7@KvsG4`JYkko z0LN2lv0KQ!6;2_T7WMaVe7P-PIM9JlTL?{e_!w~T9Ln;%KHtAaY|A+@6_01Fe}*LF znJA=t?BrKjxSNW_D>KqVtLj@Wq8Rsy0^2S7x9+;<*WjW!S;`|&|McqbZ1pBv51+nx zv$VbaDL|7qmfJE%taIy=4@MhuAu=Jt8FAP=KR*L7OCVSAzxG{idnO|K!rhuH7BYSFdWN3`c!xX4sOvo@yA11P~DN<=ubx= zicUC4+H~f8qwc*~Sa^E+;+@CEC*5EVUD>Tf)X$$7x{Fl^?U%t~iyqag#Vmza!jkA? zs6JQ{{JRK7I=P8s&bjDbu|$z>v)QPGQ%s*BZpX6NXmibi>qeGT&IrV7vLo7|^c zIOwUyh@9cunI0p1SblVKBG;)JyW#d9@_PD#x#)p151)9JopRT!e(+?fa96*(r|8?e z&y8s}16eMD^mxsbqZ>^#K7zC`o(ks~eMmeb4tev*B;lCYCRcwlvT&w<$FS80CI_V) z>yy$}p*f~{D#<(~;9fcNKmU9MT1U!s|oy|n%Q34kkW$_)0&_U;-T zErzo?5XjiLku42b$f>0bxx;7wABdwUsgD%tcLTE1+<3-m(baT8ZIhP~BI%n!ucyU2 zamist3acQOt)H;R(;RS@?M=6D?IctIeTE&9VC6 z$qktt_)>|O>juj;XX0S|@#RR^?gq~GzQdBq>A-7sxBx4H?s}8;mead4DMYtPd(mnj z!owpuT0ujampwlO6*3&9k<4X*I!*r^&(1Qu6Z?o-UzY#t*GAKBUe9G=apMjC!~TrT za>hXq#G!$WjSVnoDbp#SHq$*#hoi%o-m?sw2d{HY{#K9bjKQa~GFg?(Z1^q*$00d&v<%3jg5Al{qgA;*p4gK@*~?uv~>N; z2p^7Uu)KxxdBDo#2+x36WxmcK_i}OMdA{!i$OsiQ@M_-tO8bFkkEd!Tft>N*Q3>KwNXi_-61`g zNU*r4YtSm(DpZ#Xaz2XiZcd^0@F8R&xf5PGhL`)m1}NkvWGU>_TYH2T?~J43qkR+1 zWCnV#Ws@i9S5FD^C{%g;$)JY%JYmqn zA>7qllhb|6n{)*^HfNMAWiiA`MJ)Xkhy0^)zdE$)N1BGIp3q~j4L@L$l;QF*5&sv! z&KVTT&&79Go3E1M;B<1(=r_O4ob-{6=Bf@qbc_-tlYp zBnr!;m)Wv5JMPz&@bRnx(rghOCx)A-B8IyzXGmC)kkZpO6W6A}D%=G+-V`14D;q&>)E6Zw{OT z($X?AX0H+n;^ine>x4h`P3JUi@k?@uj2~C*owVcKyg!vseHe`!Ei3i~;z0~DeaqaN zoVPqn$Y$@_OM@F{iBp`qg>)9Y3O^bc*#Fr0QO=JX@)AbxZx-0FazeshYIZI|L{tHi z4GHb_xY{=1%TQt1-d+PD{$z_;f~m4>Sq67h?WQb_wzihp`{)BHhs3M(_^#orbPf}^ z3R9%!3`ce1JO{8aN%p)7eB(-;v)l#Bg#~nZ{d!Q8VD&;=Bv|oX&iG?{Wi!caUT@30 zj$lHmN`?a#h|kX2n&AvR;?0M#+!!ra9H#?Wr^A}E8#4!}VbZhl3ehIB(+x~Ko!t7X z>P62|4@_97CGp2X#Zf=WZ z)KCj;To|3%IQp%F9fpn2&c?TFvX~u-3{#Q_*42tL<0OU@e>%-nRIfIks@SmjTZo6^ zwV|S;%ai9AacYIbolZ9fVj=CEM}A{H`>YhuxYiMqDzmbau*`jk3^Y8As6U-8`rT_p z_{WQFJzG=MF>y1B)&p$nr+BU$ZG66(O!#a21@3w+dOiMg7^|D+pRHMRqFzYRV7@_m zSTFi14v{9oyVueV#qiN#`0zxrCdKY-{Khw}Q1qb@%C!o;3VTkY-q+BBX@vFuj6+2Z zs<Ak$mKaeS3gg@Dic?+z!Cvlp{QJS{rZwINeF}o##z|%9?Z6)-L=qxgq?Z;rlQqgx-jmv9EemO3TX)kr{< zU<8eequVZz+sGBufviwsO;lNELJq$^llh|d^&69X_33$!ak0FnP2pBZNAHPpc*T;K zXAWcPEhi>6wm^KGs+pn42Iugu!^73iAwj;zk{tr#5H-TN#I!f;th%VnP3G7*kzI8+ zw+4PEkBf1&&QZL=yjgJKB8PuHfvFi>#eFp^I~!P@I*v@GnQZhU&g>PJ-aP%Cp<^IH-q$9f*0TD5uW!KREU+$T=4ClPur$|qwTcChyPK!ja}MO@ zZACqsP^1TRBX4^rJ#Sz}Ie6TL6Um|XU_R7!_l?to7QW0?Z-V~G$pH}5ZJ1WB$h6F{RO0ObY{v^`wTE(Wo<-I6$`y} z=&J7Ki-+8TU`k5lE;%G%DcRlQtMhF;uCu*;nCV$ZV);4_{xdNRvu$MsFzqiT6!wd~ zgs3Q``%Y85_Wj!qppMDyU{9147a884L64Qb6!If;7PxieZ+5IW$ysRt84TT~$2u6n z)4)L7-!R`?H4V;I%Kykfx@?S;?cE-ouX8L0Ww*;KoxOIIGBf-3ZHEIcpscQ_uDJY~ zM|Ct%hHn zk(hE0Mo{`#HS5MYR!ZsVy#=$+YiUcl16yEbPomaKduko`b#a`WG-6pEgrRPo6cu02 zw1%YHmgJK zr2R*?NNIQ=Zf^b+3JAEXzt5lF!w02@I2ahtca6w8hh1Z{P>{CarXkYx<~WF&x$$L? zN8T2<5*g}E=kRDJ(u~tw6#<~yKFQ*%PxSW z2P!z;HpSmxJlThDWK!5D?6Zzfr(#UX2RmT95(KX~c?L3agdJWk{uLwn(+GXk`=XbM z>NG}*sYE`qfj<#Jq~$`1W}W^?PX4*$@?WvsKc+jHR;d@8?O|m6vec!FuhZSD46hK| zi1@vcTp5?z+BjoYB`u|HU5uuR?+dvvdTiDa+dBEpfCI{Mg;J!O)O@K#`cj*lb|m}d z5pPqLcxr0oK+^|9$)jbfKkHz=sI|79ptS+P)a#7_ztf;N_wwtQksi20o~%5NTGuzS zgSi7MC!92X_nFf?1+p+K6P210@p&Ht#0gqTvhW9lLrP)W!o<+9yHM`McXb*xvC?+7c9sf6 zo)<^H$E*04K_MZsGHNP#sIi>2Ol+KCD#Cnf$ddC`W`OJ@y$UrLJl{3z+M6TQ$*wxM zU-j*a#l<3y!pGzG-BP*NL86F{$m+$D(5;ViV49+wPL2tzL}a+&`JKtwFSF5wyxhc# z3+n3G0@~YC_=TEIrUVmM4S4seb#QLWnK3{GqVu&eMUxkZiv_Py7um7prxC3_4t!+u zBnA4h+jZD7u5`fS>J@9l5P0oXu2SW)=N(7A2{tLu(TyFv@q9)U5GZeKe5+HmSZosX z$0iZa4pC>yqd&1q4}szHD8po@Yt5ZHDu;-1fu-4wE_-n}G3QS1LgS^!tohyth<2W% zz5QFxv#T%LRz`ev z2abX12qAmSO@USCy&7&T~27~>{7I~P+U4w_k-}lv9Iqk91GTW z!@+XC78u?B#t5F?{J{t)MgibGnsv8%?>RU)wwJk$`%R(0lEp`mpWnWgEST2@lz;3O z(IuG#E-KC+g)pE3)R)cyX->B+n?sU`I8M0nN1{zz8}o&86vl0Ogwtj~%ys|R~~3qT9Q!;xuG z4Yq)pK2j+HnO5ylGU<QZCWUACT& z(l-v3O7PP=?67js!{-h5+BWkOgEtz7#sjS)<5O=o|0V`wuc;TMXNgrOxL+6Od>vup zvp2nSURw`VqhmK0l|a#Ur(Kb`xlEoLisCp30`JlyG;I`)DN=fI;$M&hO!##c8N z{KuPU(1#=eO|o{jKdI^4!e_jQ7;BGD9_ZKl1+Tze_gX%O{jr+mQ!Y`wy~Gmj`g07d zTn9#AwP6z4hz)vFjAgz)7o__4WirQ=;9ca@^zc<#@oZHjL74xgrFK1CI-j4f9h`D) zj$Sd!+Zdp4xBltpzmp5gi@oa+DhGrx6F(1grQZ&5%S%)Y1X@K`8H)15>bnX`DRj?w z3h(#>@bc~n6C%$_^QLuxTOtCOl$_BWQ7X2s>ABdbpjDZ!7q@vk4h<<(B$$9s1j2Mx zSUgI#hW3wh0mSN}`kF6zeU%w(zn2hk0SOO>TcupL`*dh}oYv{2=AwlS+q{(b+${40 zEM6dsMDNQ>+oD&+Cj=M=xAVOKp`O8p@y1)ekQTTAI1}wX0R>d6_k>hYvdV-sOyuu_ z-z)&dBwaZCQ=_T`dGCJWmDhf!9^8RYO9lw4Pu*oYMzp!bDcbiUBy~m;lSyC?^M`1v zPbj;Rh*ZS5*KlgG1%RtsW`=Y(Cva*QgRRjO(ae2Wa!68v{hwZlym+GI^n&`GDgm!_ zswuce+9mp)bit3{tHccyWiWbmn@gvN*>>bd;bjc061VIjp+axRxR;_t9n1nHX)M?G zzP){tpI{D=hXN_a{QDrJFG2(e|md_p}){i2#{ujR>O+n z`*3Ux=n><#p<${P90%)Qe&kW^G)*0ix&_?;v)#2t}3-^^ZZ~G7;)Q$J%PN6F%?loa{wdrqF4Bmlo z54E2FYuPs<2+&b_H!DC%wBO_i-=esY1ZyZr?7=P_)zDnX7aqRKI>4k1ID~xe6PbX+ zOYZ;4SP>}n|2CQBzKUr7o0JcB33#tYCg2BmP+b8X1;h7I#sdU2HE!gnf>{24JpVPO zu)LkEeatjJAMpzygQAO27Rd203K5_|!)p2Wy#IS{3-A{QIQQv5LebeqiYA2I&^YZj zn@2!q1}Onyk5t zsXOJrE?|biD>u;bh2p-r*)rsS?Aff(fAPVRsVgwWl`p1=$0AJ|;OlN5!9$Fo0ZH@e7 z0*q{Edf7lG&Cl{eO${lw2fwj%X=zzXO8#{`zy}HRSR!Axa2Wvw1E=yx{Q0tm@B7pg z74Tnrhf6=NmjUO4U*qRtVgIh!0J2>8G8KO=WVP}Qqeqjc|NFJ-{?|zLklB78hb)Oa zpr75>cb1B3sJmTXwX`{0I1Df;4Z>igD;n~W{?RE!%>gsu!CJ1!k)6#reU0dTU9MkA zjC}GKxC*fF9NiM7DpPgUogDa*-wtUFe9CfinxI|=vDLM0TRQ3OPTNo{YRQFgkO4Q>GY6)mR3W`< zG8`W13qH~ZVR;)uPW8$CLW>WToPc^P#bw+Vvr}a9^T%a>V)AtE;jhHuYOkhO_YaC@ zEf?mHB(QH`Wpx;2z!SOwES7dB50B}yv)c8`q;q@w`oQ))0=$>6-MMOH;%!ztE$`Oj zeV*cAk+IV>I89CJmhyU{KDze;G4V`AH4@-=T;U6|(ZH_P_Q1yHs*vr==bO#f=hrT$ z8(UcZwWk~AJSe^_z_n|CB)2arR|dd*t12o(wF3<3*&F5pG|BpQy0z8PD&lu3%nIkD zRMH1q$s>r;oYl=)M|9ONJ@|*CSfr0lb3K2BqV%Ba3M{(m)SNekMVlRf4;dO-)gxe< ze7BwMxq`adZSTSJg_9F*9RY;*mNn!5$dkEIGR_NEn6)u5dx%-USFiY%6#OlwFu5>y zeb=6^PWFnGnmSrQR#G;n4FDA4^T#E^QTuv_FDD8K$qv`o&#V;{cWUj%X-La{50|z9 zyVK0#UiwlKL}XGr)meA}L*5R)=eXOk7 z=e5)8Brp7R0a_jV1u@SM9FCN{i45tN9aX-*yWyyCMFQ&YA?Zw58gxW&=y19`UY)MY z`cav%h*$lBTqj}IX{;o$-_wD9@52_S6e!6!d!g}}#o`5?) zsD>U7sOTILP%Ds&w^UfnRw?VfC1X({NKD-TRx^T^hAN`%2AiYs=(=~R_+2Q65740& zfOQuHmI(SIf*Kkc^j3h0?OpdP(k{gVu$Csp0>Hr;6WHBw}Q)4D9d8h z-*F9prHClYK~@1(F&C6icFE^XveQ^b+eo6OyjP@6v4s=ae zVN1(|#e#+c9ewp*<#YGP=yHWQta~a3ABR{zH@%(Bphdih7yN)5&t`+$0z2m0G#L^5 zCB^cw+moRec4?@nr@kuyO#eFq>$Sk2Dn&bRV%C_2(dW+vX@3-~8@GSuV|9(TL9f15 zI^Jzt8wT=lvArBpzfOicrQr3J6ruQW&(}v07uNE3$0!;4J>#=Wcv+Zr5Np%(zyPW- zq@u=Zz_n++6@_Ak@iW4?g%$&Eb-?Bq-*#mHd;Yn&@`k~WNPYzI$LJPDk z)Em?9p4I-ct~CXlnN&v)4Vz7o>f4zq&S&krG^M^AKYS#dt}b2zoV7PMnYD3o@wS_{ z$IJll{_LL0hhymbcSL;lZ}O=zbEj>rGYKesPk}(R-#9wmc$d9bLAXmW`R zy_nlIr+!?+mOlwS%romO$@hZBVYb=lvS^aF7-}g(E)T|&3~g@5<7s_3Bw-UY6}=x> z#$+Yp)WP$W7MT6hWVBl!yu+!Pi%zX8OBx(BE~|-IbO`~wD*?$_-o`cy33!t__EFf$ z!$eHkXm*&5b`=nwB6PA>4rowuw0#lYH6Pj5f!I2OH4Q zHuMLy`mpfE88TZD4cF-6;MP9v6%;o&ZZM#UtHHn4M}?lOXH}3CeSI``*Lw%C!dM zONFbZaViR--rLGI3d_hUf{N(Vu+^PgR?5Fy+RRQYI{7XDCRH8iPEzkpZe;K(%u;9J zUYp}Oz>Ir$c%akLd_iF2fUW5vh`84S#%kK!YyrULp9UyrXCBTEU!TS0uoGbjy6t)0 zolQw)Ej!0`a?*oj&hcqX(7Mh>yjaW8I4`i=&@P;R=fF7&W$q zm|4puffQqBALe_Yrmn1kFdzaR2x-V40f?~E*@c%5^6RxWp%2;^_qgs2e`@V`I12^c z*yOz$9BhB_1I+l1oS8Ci%UptGr6ZQfLg0tCahvS_@JB>6MEWg>%$z7dIq#o?L66Q} z7L*sKOLeTAMB2uBEH8C5z|-gRRw&Oh?EWdOtU`zc>HL5<+Q{@5`G_dBOt+}ala&p% zyw7So*E*jAADtUZg!6j7dioI*W415tr4y#ph0^9uMSa7~`PBvklqRHi00;GjWN8xp z>OZzB-+z3JRTxut3KQ$t!ZgoDM3>m3ieb%h3OqY0j>bX5z%BhiMRor9yOPvW>e!A{ zV!(36t$xbuBSgt`fRVbo%e=HsLjEC2451Pt4P*R24EK(RWkBD~@o-H)|G+B1RGY+n zXA`eG8Z0xGCx{w%8aiAf`aaO#{Xu{%C?;9Dh%0<>0JM6N-qP|Fi<5?Cr4ZVB3lNn9 zhe6$=v`P|_rPi6>x5FhnO|5Gu=Pf=3C}vEC9UdBlE?d-@eHs!q?p3)NFE%&YH7fSK zTx@NDxONhk>OjHJGFT9d(N;0b$rgk=(X_UmH`-{pb1=_^?ZWm)+T0lTSN;n>AdLr1 zGy5%~Lmr9u&DXC!iJFv@Q;Sg=65XdMNl}bOxyhfLB9U14(s3%h2mZy+rQgSckz9wJ ze^9(;0+JwYi3>y{sw0G6Krgr0)m@bWGaH#E)qRSSJcS8_Pe(mo=6N=?rb#2Iv?}#o zQ^zG*hS~)N1Ld*{J_?}Crs=c*8HA&g6&d~Qg~x;iL%4BozYe;w>*KBY4FF*~k`aOz zlYFB`k)i`~P8U)=+vWeYx*J?lBXVH^$P}0fofgp0_%6|EPvT%2H}=3YeV5Wqgi)1? zv$65QZf=~vY9)8X{G*1`@1}za(N{y}aNyFbg<%g-bAt|vH*Y+I7yVDy8AolJUZA7B z@Wb&ya3Ueiwjr4AxpGkFgkyQ_e%5lb_3tl-9BuG4q@?K4(tKX^2ay!L&&O4>2+29J z(LR?dS(xz0LPtZ}zn3O3)1yVI>IU;aK;p#_gJJz#;B|?f>38{$T%*q|YnuZkNq#?a z=vEj1uRy4-XWeLe5PoNT!az&E=_Jl5`kTqt`_4J7tmL|1_u_a%`e`&=YKszRbUni0c7RVrLH1})ch4{`=3|sH{_o%X?lN{L4SDR0>{T74JN(;IPt;FO4aoP%$!*sNA9p5gAWl=_ z)I(QVnw_zf8fhRLUd~9*GD&LBjnLQr&;pu`s!Ad5bD}6sIiw_P;itr{ztS@vwH`pj zq6KOGhyFd_k5Ild0pfy3CCBxVM4u}I09i7Wwzl3)Sh%2k{|Y!I|5xoB@o4fu#Q%R) zzys@kywC`fN7Z|r0GO+0Z%K*t8e*uu zv!x3$q6;KH6a?Qr;`nb*ivaZTf3CeFR$E}Q|KCm2@c-Y@e>3Lt|Mgkh*?Z!q`0r+} zb`J!*DiJ>CcTrF9O?iBq{owzRzU9C9+fz94%nNVK%FTfH8w`<58 z#ff(ht4^T2kX=(*S^k{vtLpU6r$O{yu8SNUV267?jx45-!Y#D+968{nzPGvHU841d zHIMLV6hILMe8s5Z7%BA_DGeB1tS_QDkOjQO(LI5I@&Bo6hKa$C8)c}OH)!zYX#2NZ zXn`D}#;oxW$@S%~g~?z9o*2CH13xNdF6>cA*%5nJ`0$YvrqUML;5=m;eR=Y<=r#Vo z>?*QQBNiPap=8X4XBdfSIlrL3(~8AYczNhQk_Dh{-3|tr)Seb&j@|jtEp0?E&FAbG zF}m+wvIR6g2^c4n%z~N?e(26;#!LMFqlbhpz z!u(P|N-1&d6#%}8Ek<0QOc9;_D>yDPtS6v9aCkpMTm>LxXWXcaP+nhIvd6dSqI67y z7|itBUmQWglsf{CB}G&FO__p%xaxfLT!l|uFVu zTSiz)zyUrfXBAHa@A27gUl@J$J96c$rzrByE{;H&^EHpn3FH*UGsQonbLQOY9G0g- z)FKCJp$L{PpD!M>cg6*{;yNCdHa^?9Yus!;q&PjnpYq{QpX{VdZ>S5?d{PRvyHR+; z;=$zSyYpZK^pMLCi z<%s~r6zY7~lWtk|CB|g`=WJ5puzl|a^mC;cvXFnggLO!7$1v_qWMZGk#^D-h?tP$3 z`hhptR#ROBSQh*M8=KLDfT)xXx%3UH)OY$5mbAWTff365x->>iLCcTosnH^8x`WD~ zB=y+Kfw?IbXWD$!f^bGRc~g9RJ|);2pR4vfc?oyM6Jn~*q*0kbpQk8m_@ zQmEY{?XMy03&*ZWuJ+Gbxun$EDr62#JMR_z+w$B0$SWWUMWX(8yH2>y`R`G*OwdmM zgGlO$6NEmk@$Mb}U?bON6`4iVW|z=~vAvn78!ugEf3^L}--yGe8MhD8nu~dYF|qM@ z^Qgsl-fVYvBg>Hs3a?MEAoFj{nmjCKA}vT-D}4`kL3aL*zP@aRlXg>Kn=`r|_ihuT zoAXY--o7iocxc8gs^+>snOqNKDJZ%f_PAW8do={|&b_!C91PPgy0EeKht(C1IR{fO zU2ZN!+fQPd%bIibD2|-X1F?J#ID#22=BABA?Jn=D#=mLj9+_m=*~xi8u#z8aN7vQ~ zb*S}Ij$Ms;N&b!_$18R`{O#fO9A)@aU1uf@BGzEPJc5zeYl1qbjhbv9S}JzXwiZaw zWSspQs=k0a|0-@eGZ(+2vPr$R9@y)e#!Hh+xED|LTq{u?3UoV=(npsS-^$8D_(&cYXX1dqWeD zbi~((>nNqV{uqLPL<$MtULMC?bT~hnUudB)l-!a*Nt-3F3|_$+)9PF4`lQF z`nPeKx+dtm#P>5@c0!~(gRJ2PLzgzPB6D7?&KM;N-jddtYbq!a@7m}H=>LRLrZ%k)~>neOq{=oqCAIW`Yy%&c0Z_e3@_HizS3UBNZ zTDro67{?pd^zdO#y&Cs&M-wjngts1QKdtI_UXaYuiPcD z>_ng2U<^jw`c*+is%@^Mg1gy#6At=8rYkcZx`s4odjJQI?tBmfFLkKVi>`dW(VW(k zgOt>;9a1^;b@v*y{6PKOMxT_KXsZ}ec^+-q^!~w2_V21XH4ZdahZr#J62+PWfinCJu<>|=e`gE|HZU=p+qOE#lz`^`Q+-`y?PyDU8%?xCoj#8-!!FFRnRxQ z-x~=g)~#b(IB(ba+g@k0(_dY(XIB(ykkYejhct4ccX^1O9R-$CxMjak){>aJtrfX* zoeEqV%kfRpQQBW9*J(DH7t2aL*cT5ub}ZM@U`?}CymCHPllSpH(aOFeRtu?rio3Ne zvCC}B45B*w8FlMb8&&wpTrDjkUsmttQpuEk@m-&M?@^z$=B06ye|z>&E;MIuLO|JR z`KITt@*l;kdm!J6r|&g3KFPbX{j|Hw@5*JD#rpa_VwC$lJK^+c4YGQWa+-l-*(hXJ z^f!Sbi6A;r*`JXS^OGh;EE2G8mA$;PtXrOU#l& znrsduQph}g%t|IP^hz$c#$vA>p;9K1iz%SLF~rPaLCvg-byFoh|4F%*aqKhEF4kCe z7U23DDpF-}APX5H=}RrNyI~k2B)c{qZEawh@*p=>3%NRJ9)rn;*x;@isA8(4_ZUMH}6#sJpwTf?otSu90v4`a50>lFw)J zF9_dhsyH7b$xHNFF-kU6wDL7rUDiRHB932RpI)(CeY3#%NY~^WuI?;#<5gifVsK%r z=n~!enpZeWPE+)55}C*PeIBWBo4)hyF80P=sg9G11A#^S(NJLBsMh_V33w?7>f^LN zHG(b7T``MohP`IabSPXpJ&db#k$vI5n^OhWdus_ie%%ntqOlR>+Po`PHW_UT^q0 zaAJAEGqexgZUU}v<6KK?8O``W3;8i-7LC1gM@IH*^<7uunSRb59wnZW4;x;0+6)6p zT76B<`_-3Mn|1feL}_kAleT8dN=@$HmCZ4W<}hCKVu*-s{L#W)E5>%jTN4GJ~ z-k>rnM&h{pMc60$X*1$Ql}-b9BZ1IU=VDZ%z*pb+n_iUnyV#hsvU45Ddjiv)&H#iS zFSTV%jwo_{;&R_qIT>%5H-?QSiGv)}Ker;g1PFUPB9W#ac>8QYWM{}N8sDZA3e=dTv+u<^(Xa#-2 zTD>g?Dv4Rsn5&K|L&;eaGQy^Ix))wz$Hj}@<#eUjR*N05CtnY6Gez)ynZC1n5hjNS zN8!v*7K`(WR$6xFqk;xIPOg4KD2fvEm6TO2%4@9L(MG5HCg$lYisWQkpUszh&q=kg zBhR0EPGBehnJ8|E)R?NOJn)9L{?QTDps&$Xg3{Pu5hMRt$9|!{a8Jp5;00E9w;_pl zTUL8Q`g)HtbV!wFbjFTRnS&7YR>gKp`gDc#+aI;gj0TvIXTx0LuiL)ABOvo+g@HW* z2J;EflyQAB_`~au_3?1yC z5aKO#vbS&gyHu}4A;v;>!?_ESwAE?3Y9ss=c>#PS_OWSDh9ii6Pxn;qkFh`Ecq74I zl7e(R6jH9QRS$aC$kV)|n_b9GXBdU&`ir1KrBY1R@f>G2RXMsoChaFf=RSE=H-Zh{ z1)Df+dKRp7=JkyRSd&+!$f=~@cns*~FL$=58XzE3YpDH?5 zm9pQyzk~5xC`~|w;x6hb8`*4|@x*nxYV^>p6Fk7m(f$LVp7?P$dpj0_H_k`~(NU{+ z=_D+-o3ni(R~Q^!`P=%FAiWF*|2q4nKtQydISJQD+mRaYVZRvy)lTZi#J}{-3Hl-= zvS%TBaGUm`>pU6M<0&foCoqroHsxnW>4At3tm5^0J2vEeFI@E0tZ4AS$x_6ugu~6k ze}y|ftrp0mwAvb|_@GZfdElLj=4=8@{HXfVfju&A=vk}hb?_BhAWPKz?Q{BGff!wH zj?ui35R0ENUtIrIqY4k^J947^*3C>k?-M-L?tkI3G^XfkfUkAc3+^wVEld>oeN`pB zqvlYb^Jf3^li3W#cpl7R(v?>lER5OM$d^*`k=wIV9kG3U5NKndm4>z)PJc(}tqTVh zl_N{c--b*R4iX$3t3;<7x2f3e?g2m)=B7Fy$NZbumSQ6`v)gq#dGz3M#2K<%>5kaF zot0vMu%FErm$->0HsGjDk7Gij-|O6V-O3v&e6hR*S)PlLKt4DW=C#ecTP)xGFM78T z&xoUjZfazMb`F_efb2fBt-qxZ$oBY^>ZPI2=gPvWm}1|UR|UaSP77V14R%0w=V!p( zo4IJfHucwEOMW_UweU*5rDlzZyXcgt###2uldb~X#^e*x_$m?7jf}y*0kc`xTo;+& z@0I%q%TluKK2ZeA=7 z=}d?^=K9ag*O3QTR+BGAGk}eqRs_DJ(?4_+#kp`}5Mtd{d_<_mkyhz=;Ml5*iEhRC za5=P?qI23wTDNv?*4pG0(Hy6+XF=;lrtKuUv$_@(=yhEmw#Rt%lWK zWp?^rhVrchBRb?~nWvG?9ADNZ&&yYbB^PhhbIEE1T9$P<_c5T;LcqM3a{xYZ`?uWD zsh@7G7^dUx*CKzJ!hSId9nBv<7=6Mxn9pY}@}y@lpy`yA|7GU(;B`KIAt3$gg(q%5 zzD`ZOQ4`JDMZ~YvP~oVIbeSyO1B1N+@gQ$` zlz8G3UyAA`A%=QD+R_$dp~L&sI4QYync;SUXd-8Pz2N$l z!fUU{es^Er`|VZ=6|4FajChKNv$`~=;!hVCfb8B%kMADOSvF`qei*@BAx6)wxa@Sl zxh4dwUK&ckdvKu3J+>@mlAm0_Y!ZQA7QuJ72vQyvZ_IFuiS-ZRMvLC1>*0pQcb9d6 zcy8`Pn@$$}OR&8wbF7<#y5a#Xp#*}_(Bm?NeNBe~J<33H7Hh3WrSpTrNR1=mU`B=e zzb#!&DYd%ZZipw=1Ie z<+&*NvS%3D$F9KSVT73<1(xLneD;vumm48?;daEBVA>R=oLSt9cQkL$CVFHa=D*mS zjos>p*`F+)>3_^}+&ev9iS@c`OAdYrFJ8@FLo$_?2&i;y)zpd&Zh6mv|3e(e2Z%Jj z7Te_<>N;K|ls}R#>^u)xZ)Q>k2&{!!h!(`{EWTBc9iOo8)>Vc8tY^nZ-L|Q)13g%D z=BnteJ=qJ?0~~lz|kt zkdQlN`$YkTiR@oS?$}5O4bofztsbBF~VRNyCYgRC4luVex1! z7%!1J@d=3=#JVNxd zr%%2TJfX}*PCv>~qgL7d=Q-dwi-aT}Dq2&>`!ZZliVG!J%8YfCaz|4XF#B~`ATuaP zJr{Yz2?s)ztv*^7HAhXzNT57b#{kGxh%r#WUsVfmI4~FxvyD{v<9#;4E~bEB6oEe% z)c^X)Zij`x2^dENv2Y-%`x6X>#p6DI0Z_n@F?LuG;|F>?cFzdPBp7*0`ULs|pk>*r zc{09?D6YvG@WCWvLJTkw0=BzFB*d5_F-oFa3kW}9{1IKjz2f{-ZS}DvKiFVwODVZh z@{2}c6v@ORh{*gErGp3hLw2?(YS0gng&4_?;QjZ{5YYd^g|E4H)ow06k{qu@@87H_ z-o|{fA5hYdLp1pwPt0M4B!f2B-wB;qq+ir*zFng#b#U{MG!Y5ltFtbYqouBq4&MG3 zvP7aq5HA9UfhvG=d`)`%{hnWkej-!ayA9oa0Y)(fhG#WG? zzP;Jqpuo9H@aA~Yj1UTX^;GOEO|EcVo>D4O->zuQ2;8z$h?nDcBvD6;p6DL1RMrRe;Rf~ z>W@21UQ<5H6x+FP>=9~h6?>Yrrd$0z_S*k!=YW;d)+W3Q0~m@wOh1xuLX#fa9LUI3 zVy-`Xqc-rc3%pm~1%howR%_*-owX$LBv2=VOpD8H&hD?d9D0;r%zl%$Y6)Diz8w?TK#;8K$BNxj2*FLRH9RE z`n1x=%EYP+9QoGdFq}H*h;)ri(1-6dfFtyun$5YoG}a!gXbz=6*Ei{ns>m7OOP&8d z=NR#pn`!l>*85_lXk3WOP?(e5ov7!<)2Z>qL-dCp8-Lkv@&54=j4hU<=ngpniE++g zharsW+?8bd{zRFf#GQV%+Q{BihIv(kG%D{;M|+v`+S`dOgVu1f&_U}G;19tbhIwQ< zr-ZgRt2FdSJ}oFX^F@5&+=3a6l=2JQR~X9|%x8G&lVJDBa)Q6NQxEQ`_{#n@vf}!j zz+=7ac)2F`rlQoW3QUd_-!@}-xP{KEIe$D#KJh6@TY;BiK|?tq%jo;X9&tzJ=y&E^ z#gTPX*Z78Xjk&ESY9oK|XKP4Iu6F~Io*o`xxO&CN#LDtajnL5TTv+R-Wn33Hy}aXt z4je3zont|b4DO|JboG=~b)z60$q^DPK2Cz0j(-HU25sGAA|0a1i!kFFiRjb}i9XKs zmZbznyw2@ooMgp3t&XwKPR3^mnP+b$-xi!TVKUv)_$7?NNEcaG?82#}>Sg0_q?mi405Y)v7IHgI@cLqn7n(lWw(;Z7g_mu z%OtjFQHRZG%4e0JP*4s_0NyYE-K_WS&r_Ta4p7hd1O5&q zl_ED1=bf}r3&jQ1+dxNn758eM(%GFd=1{s_{Y}*d-q%YDT%V_V1gKrk`1{BT}caqul6w+{ME2cjd>X zyKKb(l>}0d<#R_r(=XO$Vf#Fx8MR)!P1+Ou+dBrojChE`2q5#H^PoJ{Y97pj&P=UZ z^0(In;@GsJso6;iT>Mq&a&Y~U!NMe|B^(B4cbMT(#4 zE1#awlXZU0@-rW7wq)13!uo2{NgEmiDpQ4PX)&A(?t79B@IbE2Ck9OwAW;J8v|276 z1>d``CA%fD^6R;;41Qf_qmuz)f)rff8BA{c*_~?SzEQDBHfUdu zu{J}MI&amibrGiEMXI55B3J~qjSa&=iz&yIu8W^JfOb{h=HUYxr=~Zy9#J9{x9X>) zO54IhUU0uW=9!s*?Vjmhs~%fR4o4Z?H=QQ96FU-hS79#Q_W`FuT1BR$`Yq~4SNA9S%=`9#WBie;up^#YPV=9>ds8Zxub?p5)Y!Crc5lLxrJ@kTd>Jm6 ztr!Ki44Z6eMFUF;R%x=Ve6t+5RD*kKdqX=+MU2W8=B|G)c4xaS!qzBSqBBUhvz)F==tBXY+-)q~ z!b?+8VU`*hD8@OTktQf4y8O(HS;w_4XT5K7VsWc+y^@qUnL#bLu34gwMRm0(3cpLs z@;FUP+0YrqZPnqJq9D5`B>R{6n^ul^61c%fJ088APt65OZhy z{^zrb*aGdi)OH3H$76ISya71el+Gc+CRruzwYf2e<5e>)*K#2NW7c5rD1$MY%{A5j z^V#??1}H!$0$E_v_23;UT?_18bSHW-WKl3Z{Z_xs2b9Aj9UGUDmJ3%u6tH!|ZmhiN zi`((2bG5M;DffVXla#pTn%5|=D4ppb8T|8QlWvwz9_|^|AH5O{C#FYJ&zQ^}@!RZN z?u|YZsDbCN52`9TZPeP{wkH9!r`y!9h`40)&5XG~6wOBv>=8o-i! zojWAu9A@H2As=^|b9Y?4Pdbhi&*c=y3XCzR&8ENVqKUr>aMCP_khmM|u#5xcX6MrM zh~aly*yY=}noqsjG%?3VE0To#sk+I4(bSbzwnRn8$G3nBnl*aowI=;6y} zb@8TmSbnQSoTO>pc^+wL0DN*+f838h>{O*TL_Zef}woH`q;reG)8)YwVJBY zhxOM+Uc0T5d1vL!j$8{z?oaiMmIGqLHR+e!2 z_CeC4^_ z=H_kz@4|{ot#x|}>hY}>!1=!f1!m+vVQcDg6?3)2CCX*s+(n{H6N#=on78JzHft`e zbyxA(6c(&O$G>owwe0%!;ypd+Z+vTZ9wLDQ%`6N^rnG{bLcbj7b;aDeQv~o{zd3$R zOE*aM5-V5&cktOLUzCXMt_JE!Ab90_kRa2s&mpjPcU8wTZxb|C>EEgP^QgSd1 zm&aRto$;7ll(Dc0;vP(VhHhskZ%40FH_w+7$rfJG+U;z$z+m78W3(dc(@G`&=rM9W z#T^dSFAVbAK}GUAvaw8NEIjkA?bcQ&)$<(Pcg1^-S_^IABOsF;9pr)--`uh^!X~UO@@W|t(IE^p_)cXE|2!@WXQaE4!ryRw+U~WDfV;7$$81FS zgc0PE^N}tMF`lf&b6H>hw#{ z%eBWd@6|s12dbisTn>E_rVohatBoOq;~2rOIWcH0Et? z#B*f&dZi5Qbd$Q&O9UyCn|u&hk&wy8n$&T7ojOH$AH?b)Zj0F9}plCsQ-@|5Mv3dBHV*?+L_tQ~krikN5me-1>j&vd;rZ!#p|$@d7KEq}7>c z!GvsKfg@E;CR|IxoJ}rDfxax>@3;X;<69I>u6*mk;ZfCmxhnCv2)oapJcocQ)gt zh%cX4(ms-mO;pauvuJr0+G|-LdvmSKJ_8rT1~F-{pDOA9(bd=e)wyta%6+rr1|zd9 z{3-_lX(~HiN;tJ;=#pyW%y;9lOY`Fg-i&?{lyP+Nj*SBS7j65}4dS*Du)q(gwAJUF zZ(H`(Mw4a4BC`^yuX`unF}L-?weX<9+ke|_PsVvx#EqhmWq?RoB-GHQhNf=21?2{^ z|Ao^2nrJ_y*QkYtdp4v@z5btRa zth8>hz6OWkg&&engX~r5Xe3iWm**`3jR#(5vyPY4Xm_dvaqkU%G}2XbV3-87f0)?- z44@-3liZu`w0&f!h|$^l?_Y6UBYl@2=zCsMNu;8!a*l)N7gu=B25!?S$Jyey3CTp+sG5f^Qs4TM(wFrK zQuCd^+@Qo~QE=n(yNAyjrKNT_W()A+;M$KS_*OOh?lj@&q|i~G#emP=U4zkcs{~iy zVs}quHMI2SEK5jz8oY}ut!;c_+_RM7j@g5HAm?T|yQtU9S_Q>=$~9X0564Lj8((?3 zYR+fmvv1M+CR;bYW*h#RIUP5~?-^!*Y7e;8qV901y&}0JoFMJB_0`Cc8Im?DVji%m zV4@WG$6-=E%iG^%l`z!u@TWrN#VW{A zc3>ykLs$6oPt$x zQzYcpV4soN&kz%r*hHh~IQ-bPpGmxW?>KN=6k4uV;FE;B}Y zHFZBb=Z&7Aqv@9xdc!M)+Yd~V=D2HQPAXkKVoH)K9~17pjPmD{82C}U)W#&YL>+M3 z064{5;BfG>5vj+=^i-y(Fe+yD!oe4o_nAjztdze7?|n1VVK#PO9`6_h;vvMjj0 zB)`vjG>3e)0KyzMS=-BuTDZgH&Bom}-H-CUbl%p^E?>}`ilo6*;u*6JR?;fREE&t7 zAvX_%%+b}DdNn(Y)@*E6yS%0#bIMZEQGf_^eRAq-#|SOt)wJeua`JZZwkn}HsDP7T zm_p`FZ42|uInY%=MjVw%$r`XlyF!190lUqUl?sK<2ycE=9)NzG2}a=P8Bd6S^{;6fL+qKd#(8mk$S#L zK7nU%nc$fNac#WzXn)y`8S|bLfieot0kEK*KEAlq! zpt5nK+AbM=*KbH^6uMh76AT{w8{?H96LVI4Xy?)JARn(REsi#8Fw0&D?(lNCZUn=| z^VE_$Vh=?hCd#l-Fyz6h}y!$hg6&YU+zZTXufZ%7C0UuUS8%=)~P`Ys@xAHM597x9<_@{!97jF*! z`2ALaL`lZSwYVK}se{PgF}vR=Ns6B>?952E1%2y&N$6GW{{+b|DBuk$N*BM}BPM`i zAYyLj zYPbvj`&?76M5lhm#Z*yMRg|S?H5z+s&400=cG`D=9D^<6H`dn))Czm;W{w?u?q|yi zZ!g@!?hn+A$aGgb$8D40hHXlBi?-9Fll9&p1>Meqcy*XNqg!}s+2y)!fIaK=a0hxZ z0LQ%S8P>)8<|K21*XsjswzY722fuE)re&AzJ9fl_^y)DQy&GWYC*^ZYT*UPCbgd@x zXQ38%E8g(Ns!05Osvkc#$S$*PkP^PvSxf7AymG465CJCv&xln;@YPNCj?CVBdq$0T zHpvBctSlu+gpZp1ffw!MO;6f#k=Pyll_dS-XhB4bq^)Z>SPtwDRa|vCU+?A?B;Afc zUb2`@>f-Cy@O4ShecV2>1$DmsplJnetb(^yxHLXmO;*0+>;i51fEe~!+)w+G*1129 zmoa$Q<(*ptzMM`4np~q^S`iIt)L{_dm?6Svt z!)M$-`06HPqQ}ZrVvIvxd0&%%CzOl@U2bg1+r_ao?4rKqC`@W{gSimxgkh~za1p2U z@IzA-WmWPjNYim0N z;-b1~nJYt5Dh~^~5$CnXw;H?MWuvVo&r%C}atIHgqDrMJSml`xaT^7+T`Md5+Eb!X zjWGdPS;eW5n3b|bK_VLuOM^%Z$d{8bYq3`WlGLsNlaV~qMY3b_`O1rPx+oJGF}0D_RrAl)^RzNjB9Nrk!1A5R(82(A>l=UK(fui+ zESbK3%~$UPsdN1)Bs*!LQgFzi@OQxv-rxRfEmn zAKdFg2h}+$=)V`g})Y@;X5waXX7Htj3 z67i~yB60ZPFBTK#0p_o*vzUT<^O}kTgbncG^M;1?4n|HjH;-2q-RQFxA|>ToN#*Nq zH_*xrW|=rVT4neblVxo?jk{&dv74Joi+({K_4x#}&p*@3M7Tbt12EF0SN=M&Zg`nBl~V3OaaC{0U& z3>cebl@*mos;YBY)5uSd41T@%-(y$G9=QB3eU#*FuS|7UYg_L|L{k$c@YR0p%70|F zHJ2P?a%2xV&D<}xBGG8lG^}qbF9md&2dE2MU&F#stifZ@lf|XUb_Pj+^2#M46M?Sh=xLhe7!bnv?Yql`v|d{+RQR zJ{ai~wa|}mj1j@n076&r=HDn?zr1g6{tc?kMEmyWWPudK@ccguJ%16V%Au<)-?y#G z+=X?()GJjRN|*iU=z~D3R^!G>=mpP8bIbLuJ`)u8k9Pm-D)JJzlv+Oj$JmvvkW6v% z(O2Vnb3*dFuLqCudPpDsXAkLhGu4|VN&6~rJ?MLm$2;+R(;fUYIlFYG``+GazmAlk z6ydgxWRNND26u>5-r;}`J}cg6P+mNEi#U&jN6rCsr;`B^2*X5q94o*oV(i!{O5bL{ z2Y`2gqb}zE>6_6N9Mskb<94iQXwY*h)v5^OQ$lLy^E1^pMzkS8mDFEjCMWpWRlu9_X#S(oSzZqT#3}U*R_1?t;)bPzwV_Nc0I{3Lu4Gx4+_6y zLhe3i)P=@;@d|Q6R6U?89VQ&A9+71}rtBsLvNouQh0X5cS2u`7DlVO%dx<>3S-Pr4 zl+5ZsBt*LvqiopTix2X`#i`8;$A0eEiFqwfgJZ~m2pdH569m?2#1AB8WQ3D2aQt6m zod3s#n%h^X#i)LM32tY7IYtQNy+`!*W9i~1Xo&f*r$oE_tu3XEO!F7NH>k8giparL zGcS>^L%V0!b0T)di-&ZG;*`(-d72SK_p0-Szfb8R4XyA$RIhcD6Zz~_sx@#1cC+#?i$=J z$PnBKfdrS}1ovP=AOv?Ce1Zpew-DTAaCdhG8Enqx`Mu|yx9YxCx9Z;fMOAuw_wK#B z_gdfeS*s=f@skT|eTQ=|B9qIL(k1HxlW~(_m_1q6N5cW(ha?8OR zcgo|waeDvX7VbU!7o%=JqrUj;oKv*pY>3A@hvi+mxIezF-@Wqli{{zV6sSH@_xf3G zQ9Ig25ehvn*!sHWJ2`R=TPvJkIaDXAuZZALS|h>mjz?fYZDsE;mkpCL1@;=v!VCy* zj||)``BIzg&r*s(lLXUSM}4hNrzsTav$uL!kdX`OVt$DaD|3fwj{8~*4i^LSqx;9Xv=4-l~Z3#KPK=JxqE~CpmL~E6evQk4|6A< zYcC_q?w5gDS@bHYD&13XVg)qXTn+}+WM+seO}32C{y$Eth~UocmX~T+m=v%0i^r-A z*0XCr^y9SF*+6SMY*^NPhyM4Msp_rk&|m~_2MFtWmdPs zKWjo&GVR+%-`IMQogPjRs9&zNX=zg{D1S|q%P%@MXNe&o-U#9AD7WIke^b(@(Lk2Q zod3I-S3vqP<&s9nXo2JL8bN+CrCrMp^PpCDx%1KNf~b9@%Lewd<$lCiRGTHp{j3w2 zU50F3@qJj{6Fp3HHm=y%^!--Sd{ASbCwejSw}&3r(Oq+T$@jK|mHG?f9CQz1Ys+C# zq>F{Noy`H}?)LaGl2iVI>b_6ps-fWF#P2~ARO;)wQoBgKMX!iV9elZMwG&naO(j8U z2$(V7!agB3Qx$h&dp<(7PWTp&mRqF_EglXlGnO(;FlGI9OOQdazW2&qlPqo|wI%wR z^^P4JsFVYuci-l+kX8HBToo0*Z4Z>96j5???@o@6S#6;(_qMnOxZ0tKSXqA2Km+m$ zIW_BXp{wef3LYbLbUZywtm11!f~c)O&|P{+irmD>_b=)smu((k0Zt3wr^FUDYqxP; ziOalc=TG7BF^#N20|U&dwr6nH)M<0exXqM0J`Z+CjpKgNyfQB&TU#4p5ZST1#_FnT zFb{U=#Xz;~v);@rB;^{Wn&%Fc_IS>cq0twzsHLy1X6x|Vd0<&D(@EQwAoYh@`A5Y= z(#_i;vZ4X)^N)#%33$U3^(Ef2un6otk2IHrmM{4~*S)@%cvugNOEr}YecjwpNK7i? zw=Jl`k-j<8{A^mVf#FD0RA*np56@S{F9_4N*5~YwvC_1eZR8Gd9<>*=?zj|3BmNB0 zkFL|`z-?*(Z`ZcKooC;F?Out`-PkDWA7k45I6hUL-CVh}W{Ph$VAwY@&guPO!*cfK zEboRimqLpttz%&!DJijrMv)ex>vkwQ%A55KfEJA~#+0yLhoYGahKlrVNd4BX+Lkjh z78CIGT)Q4C^SvjnYgT;r{blUdI3a7QTpL9i62~W9#69EUFCn-MX$q?VprMNUp~~SR zO$wOL`8b3hIzp=Sa>(a{&qG;aXXozM3tId80rSSWKd3>CX7ld{E(MnFDKO>0O(vxG zu?i*+Tf)AI>jcng0gqRpn6+jE_Sj#T_|I0bI8Y8BmT&lG-sz~_!&{BglkTTol8C$5 z>PwO#d*Lf$pRswEBrO*ZlL1jY9L2IWZdgal&FPG9Ks z`m+1_p1wm7 zWi1KP!~)%Qy&AhZv&r34q#kLyb@bf&2D@|5yV*bk!#)k615C_=uR66OyDKMk!<~M% zcuIB=n|+RS%VTy{ZXIqu>`JqM4$Yg7ZEfc-?@V=-7lg$g4zVSQ!>Qu%2HG{z-LB(NJknwPL&kBysw zbTqpl9~7h5o2uV-wDKSuHW6*Ld*})fYqKAd7#(@rWyrGB=cfr<*UodeyXbiyA)uqE+o3HcE8Bo~ zbV#9$m}@OeZ=Viqa$6vvIg z-QeA+B(}BggZJI4EJ2zL7}<^>Az2#zu)XYC=e6f*$T>v)f06y_M#g3U8BYWQp!mJ=TQfg*+6%1~smDDMBx9yuFYk_Wn)eF7xk0Ws#&O;f5)knaB*puT9;s z)p}SGA54&)==ou|#f}{wgYwONt9}FWUOL6_3=hfXmpFfz z$0z>OU3M61?^||6h1R})5iCtz_N8q^_6qM^GS3rG#nUen+K7hGyt8J}7fm81CnX}> zWPW*qw6GG7?ZY>HhHP#%@nw4Y((6y=VyERJgq1F%=U*6}QOg^3q|RMpHBCy8l|CG& zcNb<&HrZiv5arrcj4x?;sE12Rz6eXUTWA}c9Qz2+ek&!S`EV-dGc=VLpbJYfsCpBP=RZ(wtcf0Ba;x9<2&0j^yfbL2ZKTR z1ist$yJ5pcZm@hxGaqD-W|={zqneTu>kwFPw_d~{NMC>W+)%5viLR(AY>o66Z?xdK z-nVUpO~T(4KPW=z_GaBdS-L8trpxNL1s*vES+ZwHG^OTMuI6 zrBEMAFH=;$U73KsJnCO}gyHPG6l&N~1!YOQUR;jS_$=If`R#eVk(*-B@v(UteXMX0|EC96nTwH8~ecCco z1Xm;q!Hg)3hyStAH3^eUjZ2_0A^IsM99F|i)Cxyga?;upu${3+wL54qwyA#WJS9@r zWY%g1o_mtpQn9;56jVPrnc81C)IQUBo;zkVUEDj;=*kPqR?r>PA<;d^#ACE8s;H1m z=<;Rn_{vkocbS*SZx@~7m_({{*5y$I7f_Du?$si$NF}wdZEdtFqvcbi)bl0c1MEbc z)$7E-Wo4=}z#Ej}brLiaoJF!>%84PamG;(Eb%uS|aYHDkLCS>SZ#Nvyv0E94QE@|3 z5U028s(_9PMSfXZwf^<*iw~6~ZA2eqk?*MR^Ur zJmUj#cpqLk>Db_6`7N`N(DcSI^9*2-3D<8AiF{HQ!h9i^ziVU`Ct`o)ch5I@Y-7;> z?y$Z1m4$U-={h&dUL;vD*y}#4+*}~hionXsz<4LIxyseT;|)X|u>>e=imrL-x_hiY zWXS9k4+Aw>Y#aUi-LWae#=L*A(taS2iAgElvE;-M35_VcCA?q2o^@{M*7%JhDw29cAUfQHIB7=_Cbg?H4 zuUH42ke9!M7wlmc%!%v+h-vcqzJS#?azcg&Y_uLXoO?BI=+6r8lq0g|dJ}i2>_;F+ zS}g@0@E2n|g}JE%+$pcn3)xnqjAIHk?by^b3Gt`qdy`1Q9^r2y+X_cVj9uKAlLr)} zOH5rcfAb|>%ce3F8BrYGeKk6P7y@1wvWzsif6pB=sucNwNb!jFbCs52c*540O%IQP ze&hJu40o2r_x@OzB}M+6;MQ(@#cu#3{;tM|e;v~oqSU()V4G&{#K3?Z;))>Bv7U+j^?da@u~ae5kF7AKwq@Jnhc;&&3m?22;YkM;SV98uV+_2M$1H7Hg`yr=q@ zIs0-_=IE8sQ_>HX?av$K`mcnolM6bp0Q|-`0BCma0dyw$?P}`OFY#^#n)%f1siMKPv@~ zJpvTg|K+OwTTknOUUTq_hVwM^)+J%tF6Gpth!FZQl?hmfUMtc0v|IA&kNPTeN7h+?8r`R!8Y0&${bI(L{ zX&C)@fiW73u~r4$=eIN_zk9Z8yabziY_FUk3+(yFcG$p^>3$B#XC0fz+b(&&^XZ&@ z93-&I_WR9oGWn9BH{+d;}HNSh)91(xPDCj8yMXYRk-}$z=1>6Sxb4~qA zE%?7H8KyZ7q5)3!`$F`e69+rTN7q7wtT)Mcmv&C0tdd@{;J^66@&*rr%L1C8zgH`Z z116|iG8%8U`7EGzZFp+$lC^&(1b$2ySLkh}mA6oAf(~uG>5fGru&A$q-~GtGyRdSv zrLgz?nL92nAQMV40rJV-SrzDvPKgG`-{LHO0J$0Dt`*eTAZoBs73FCFMhSsr9A#>D zTsS}iwMUpLDzT!3xt#@{X)l(lMBT;^0aX~kTLStAt_NpgQlCj8I{}86pur|R zlPQiu6@41mQ6Co4J~^+bTE_wB;MK#v>LlOSX27TCag5=|VvNr#9Y%}`62I6621I-3 z6eXqqHNpaST+n?bgE!Z@m0_Yu%nxOxBk9AV<`a+xeKy_E!tEkD5-peBdK%A?otw^( z_&C+?fcc17-+u>1J;z+|Gh}rWNhI0Rr;NF7wwzRRZD5iWIdDZT7tt!3?jy&z z(;tb6Z%q8bPrkqX_rCMWQ3BgV`QUo0G!@vAgN(QjF6ffmAV<*!TFGf1OrnEz<~Z2u zCT>jMKL8~BI7R`6z=f6~nX_&r!*+wNq3mmWC7a)MfE9Uw&VziH z=yO|E4i&AHM9t#PE%r&0NKexhQOY=8~;{r3+l#!%PT zTJ(UXdp?ZRc;(Lp8fWtc%RJ#UK0{M2L8@tAg?tJd-`YwMi^$}u7^Z;L_Y)^`@~sl; zAPH(_5XwTPk&lZ}Cqc?AGpaKNc+b!akHd+;C8u=5&>}9 z9f%!2C;?pEW#by{xYDYJjTf@f#M1^o_;N4*u%GHH2Zlr6RAt13ewYQmG-Z#{JeklZ z#U#`5%lw`FX#USclWPahJJ&w2>F1F*4a+$tuqP*xq=pj!DIkZ#V<4}~tx(r}78wGi zMK)mNOM>NXZ@<;c9FJUZ#-Qdabk?$1wBF0Z)bn7z_AL$*w71%^mk_j%od5~zpi0$C zj7+oLxMx3uJw0QScrYcIV%T0{w8xKIAUj)Q*$@con-s4)zZd8oK?*p&m|l?^V)6d^ zdqf&|l2m-#fi;x<-;!)Re>O);wn8NhW~CkkjXH`L&Qg^(q;ICK`oip^!~B%fwx6Oq zBkm8tNEza893ZnLnw*2fGdm{7d^d0m8v4a`gy7SG(D;H=R_o0nCdbYjrC&TVwX`n< z@~&(-U?t1Wrafn^rC*djs&x7J?7Ir^C2w-`3pt->=E3rHR45k{yN;#uhIQ&(r~ORw zBPoUJt88oo6{fEIZr+eCm!i4Z2G;FnVovc#hu1MF z{o{J%!k0r!!ur_Uhv-fFMd)^EO8hMwqwQydt&-7J(?=qe>(4z&Oy~HTQg@kt_0;DZ z`@C4rj#e|Z6LPRrlv!@{v)&qAa&0X5p?QrN{?3ckFd4p>(w}t@FZ|r#hvqS7m}s{k z^p;0+y9uHUs(ZJsntDqH148-*7`I`wb0Eu%Z}vyo$Ys;yEPL0nzkSX~?V1zOh=&}8 z3wP(OdqEY6FcIJJ4qv&?qK@m>DdB2&m+i8?gDW2WKp2S7Kkc+EA&@2tZwTXTV!ad2 z=maFW8H&8`fB0EX7;D%neb%O|vrLUVV{C=$RwlaWQ$e1py>w3?;)v!~UtUUs^ga*# zosVq|@;2X%3b^I>XiB-eoi}X=JeZeJdH$5}NCW{<-ne7^c+HQ9LQ>g3kSDj}9FZ|` zFm5oN4Ulg@K(y(6rt_;6hweRZ;fm_=&bDCL$EnL z7fj=GpDL|g>@htsQsQ0HADgCL$p;b){yCYmzoFcyP^iIBEnUc2j4_X|~TcWLzpRjnaY2xzO4AdNdBS|hEyhm4sR7jz!&oNldl)Y<2$J<(UOuVcEg4x5vsZTpK^+4gO$?J5QcQT~zyezL|R zCzr~^#xulaj~$nMPfO-z(alE-o)fppeY zJ#07UxUqtXf~OWb1!J7#)(t+N^8Sy zlOFdxWpypn52Q^$66gzW9}EzJb&y2Z?!J)QkoieZzC1nI^z1<_D+Y=j?|d9S>A;0v z-O6qmu(=TVr#T*t%R5=|YYWnzU@C9X#a#s*9ZgDyLxRnzckOAERjFZ3a=MIPcEEYj zc;?_$58C7eX$sm-?~o`99o3jwRh-$AOXs3*-09Si(z9DDYuZzihxsyxjlUk_pJg+U zV#|IJ;F5SapDDid!2BGb}}Mm%rKnpp9i_%^y7&DOHelFqcbg1~~0SC=T^ zh@BJxC}Qp90;;v$vlw25gMEnk<+*ZpMz-BVf~rL=^~t}*tn&u7U=L5ucg8atrnw&t z;YVn#u!&uDTCd5y-BtRsv zf1ssJ$ncEi<(GT^%G9N*BMq1VIgf-zq5lPps`ZZujO1Tp6a@529N=T z4i*TFpRNJ9oA%Q?)hBqf z{H%7`u#XLDfzHdLHk{(X-|H6bQN~5gZajnw=Go4{pZ66$zfCnje*GdF3D#6BVVmF| z$3Z7v;CLU%OSDq^!&nw+30&99< z@wMIk?-&|1poKQIdy{EaFDZ@68xx+h@B;A>UFXq*_{Yds3h@j#j$nyiOsQEa8%YU} z68`tfhBOE37D#|!_xDb3saz4Bbouh}^Xw%gP$ZDL@M^fLH7WqNM#H9UiB!(rvp9VV zI`^(@p>o*PF|vw7e;rv|)WPj~L(@HX1Q{W0jJyml3W|ODZ=$1LZY z&s1#9Q@Ax?DOGhfvzt0CTiuI3+Li1Hn{!Iu`K#xS@p2wr5XXQM)*Xy z%hb40_2MekA%AwlXxd1GFaj>)+Zd|#$^f?fzqNp&+Dr?5w+2+&1cg3S!J&wzP~Xq> z)0soV6AN?y^jle#&Q-fzxK%N;gfWm^XMf)3rLI&EC?P8*9=0nk)2b`{9htMqO2Jub z*88e?B+yq>P=_=;fL(Qxr9@e#sB6^d)6RuevQ9xkMZyd8aJ>Z9I)TX-RkUdxtBsDA zLW=4`jw(%B`BOXiyz1zBkU8p+c{R2?L;ol4fu=!YxXCY3zoEB+X1W zPVtSwAWrM#0N)pu4&g(ZWyEI!Bd^bpauG3x2O_dd1=LKlbTfZ8y^6cye2#JYBwE#z zS(67_rIv)0%t0!4Ll~G1&=0W?oQvllA6T6B$QnEo(u8|t4N~ao5V(j*;m&U{g1ZuU zLLhTneVN=51^Vt6>wl)meXCNV)GezPx*CW+=f0}8Z}U9l{d{Oi6?S$`z(fS5C`zz~ zFp{_*+F&f~V#Bp`%Z)!VPcIm+3VK=p_^DsXPdhd~eF2w;QN) zOIM~OoDsjtuQ0a{}Ye_+* zEiDP`gl){UGTTFCH90H!IW^&wPtNZ^(bwC(s?f$U>R{?9kaS~XFCLR0J@=W$tKIk$ zv(4-Q$I8!`R#k&9)vd&m2m zypsaDn@(Pm4jMs=TGI*}3(4<(_z?9mdpUO%ZN4!32Sf?KZPJwAS1>I4+9Ej!Ad+r} zmd1&8OZvA*k$<;gL45u}F)ZWGic6wXPB&8P!X7q?n~A;x;0qzApX~WY+g^--yH>%F3`$xosy~58bf*l%=9xh6vpO zd$7oG^qX(U0B2DY2<34!Phz&;NkUcagf0<4R=3jEH!PMrdzDCzP?|WP;;ol2%k_MFyt+RTc*4;Airc?c#@Ay1BbC2JmpB$_8C5=Gr{<%sQ1#K&fU6k>j zKj=l^!rgYWY(|)43(W4WXWs|GK5V<}-CClb0`LB@e61RB1ho(?m-F0i`>diV+ajC6 za40msDPhR>kZ$Z0JU_rw68H&n+d2WIgp;cJY3HL^=lJQ8$3s-QRcZYX-Iq z-LvyNQIZ1bZ?F|%mWl4VHK7GO!@~xoF=818S~4{=f@0l4zScR;2b#3rPE?dm4yEL~ zmA(2UA49=F%GF2R@n0OSMRW63*8pgVNC^#|#qL4VRYAsm6;Bgd~pr3|8i{&b3~3Y-S1Y|8dt7=d&ud20f~O(dtQ z7CS0vwwlWz;Y?T5)&tZm#C}q*VSWvH|2)Zh%|H<>Rbji0iXj_YtANeB&ICYcR>&lVwlz1{AO>xSTVWX*& z4R`Gy*cL&=;k>WqH+I$NcODibqf}B`KN0=MXMaEElFKE>kwxRN+E;vN78=;~{ zJnFyQchkM9tr+n$|8P)AnmGYi#*>^rr>|3FAX6pgNtSaN`ys3Vka(!Rm$Wf6V2`s~ z*`G-)oV=MmJT<3LYem!+YPh)2-s9NrPMoACJ0W@bsTuGOEGwS%j7M4{D$wKNB4IW# zH!*fbyfW97n|ss+@1q7q0O)jYFR_u--6jSSaWles6k>w#cgEwi1YuG%gQc%GcbEvm ze!^X_TS!WSns^62AAU~@ePUIU%b}|rij~8YT2uAxS;YX(#^uC#luv(@-Ak-=E#&?9 zHOXDKLD-=kcd8!|5k-qLX}rEpyj*^S3XF)fqimaYTDTR$86j0mAD7qSPTt}VJPrc? zv|jpyqZDM+^QWN3j|);OS4Ck{=w3m5vTVrj;*YV9Kliu4rBsVpzr;p2NvXmerg|k`Kx$Wl5GR%-{MfEc# zZ-09FPc<{eP1BpTu-a978iE_TjL0M+nb7Sb8A4BqU8{s|>|q@UzQBEIJ=&seJLvIp zsou4xp1;`N?rjmK)JiJ$Rr1@P2L89QPaJ&Z0>B*LXAxp*N_tQI90G2uBg%$OYus^$ zS*U1f9GYf3UZT;uszO&&|8(Thr>7ry1#R0bvZ5kABA3O%Ejb7?=j&@Z|oFO0Af=9LT`r?!dFg`PmZqZPfcSuGdD%|hV^j=zl`BM9+vi`H%+Py zp=jzPL++oZHoZihB-Y14Kr{UKL&(+Kzna2o-~Q6sz)%01va7_fDvCC(Q0lO6Kw!r$Sv z1FWR}2my1xM%??J2P1#9y=vmBnM)Fn=8>`FmZfd@xaGO3koJdriTDg1IJ>rMTl zUgKFavI8G}KqTM3x~23TMfS4#eyW-o6F%F5VvlfR;ZeLGsdb=y;TfjY4L!#!>rqS@ zc{R#}2mFLer>p1s0{g}r+>R8b-&;K@oD2%`3q(&&D~}M2!;^x=cXI?tQ1?yTr@Ob+ z9Pdyd=^I}mD_Et9-i_Y3g-2Hw%n)#;MQ zPtkkHDMBh-m~ZW5Unc*4u$S%mm`Kmb04(Rm7}v-1*Pjr{qVRSSR}P&gDY^9x>8}WK ztNE-t={tJ05>Tod!2wv_mDg|oinil11z>FO_&h9tnluqjV)ZU*28|o`2ZyB0RSchy z5ijex*xrY(Yybj5j70!ZvL{(7Bind^;L#zaf{E3R71NB4{ZDeaC^E#rPQ-|h=9Bd4 zv8ZKM%JOlxZN`UVl{ij_P`K)rzFSlNVwWW07vO<}zw;9p$5{uOiECuLyCC>gQLD9m zXGI-l*D<7ih?1PWCNg_u*MWzglE=l{`<@}ly>CcamcarT_~SHuAA7@y?`jh4^rR$6 zP^m@u=KqA;+X37F9}VqnLWA7z%ZDOBuosJX?C6gXa9I$KxsvbQsl7s{q}l44u?h6s z+9{Jd18mxH0b@;uC@c9&^3I8NrV=#@(zg2n_puKFj0 zKMm^OlA;IRfj>U*IAWe@(G&4I+h_2m=A{xt@6$5EHjI{noqcr+q%r@k7Ax(A$FQ() z6b#)I*le-E@>1_L3?9xj$%oNV7zhBL>(3qH92XbY*u(_DtjA`U6S%+D+;oP-!Pyei z3zLL+R0ud;^8lomB0!gw_)xd2tNQE%6;t$w*>60%2Z`Zft@YjrZe{Jk4AEN-Un{gy znXAhodvFz^6D{htXaYx>W%ls$e4C@Qt7|wFq)NbXj<`!t*96^9OtfKjaH@)&ep6IL zS0)~_&j)PplMZYFKE9XBJ}Z7NcVdm~OmE;;ys31MfkrRSvYA8Q`+dTPKQJ|mkqkcD zx$63QLCdKHFN_V$clNZ{XoO8g_5R-mq(%$mWDoPh7L zSycp}AP!zq$VCrWrMnpHi=0#YP81Zp^R%?9yWN{CvKXm-4s(=D zG2E5@uu?tHCEvLwR7ltOM!$W@F}GxBtqI{cR&7HP!9e{5SM)1M?buFroxsPBk9B)# zFUO0uPk$)CmmwUllXxNYRNn23woKV+dVbCq(1}gzPTp((&C-gA{}b?o%7X0IYyUCJ zgM(&<#9$u-4qMEtHa@Fyx=gt{2&gVtO5!G^*1gHAQMk-)sWK?c(1162sC}A?YaDUD z4Z9SGp!E0p#qmN$@EJWLW0O!_yG#G%eikW~cNjW67~N+0r4TO$URW1ztfOF>pZz8; zDz)EAP~zU*PxR`0Q9!ZZFirUIHYdXMZ{77Qi)QJlOQ^Uw9d2MCPP?dThKSWtvj;Rq zsT~(9N8_!Iu5OvZVa}$n(eSgcH4I7RS;}|u@v>GnlC;s*>C@)JXImg@1q3d zb5jy~GlZwzHWl(e$nlH|M3`nX($mv#uH`CP%*|PT8hyfAzc4eW;Es!-PXX4#3%?2! zG{hE#<3!vKnpbr=>N7`VzQ)o|%2I9sFOGe+xwyTPFU*lur{G#z$X6-Q=j`Ec7O>ZK6Tj^$u?DUl|0l-NzMjG(t`Ll8;%gyG+OD7X+ACS#Tv>D~?B z<^8+6Qx0Q&Rbp{9G{T*oOzdfC0RoX?T;AX@wWp72ZT>}|d)v?+fHvL_6JlbSaU&R^ zNjnX{YF;m(MPOTf-8s+(kBGLkRAZx!%$}{X% zekM-e?^Ijc=Uex5wcDCdpZb*zw4vmxnieok=xu{e9Bs4SUCgR3WevGm{QUONUE^cM z90OzFX!q$K5!JVsESH^~Qei(;U6fKpcJBzcB}))ph;v~3$oB|t03Xgl3=J^ccu4D^ zLA)fm!I;MD#`A24E_HK~jEJ`0yM{%I^zZU(xdw-$qZ`Fb=kC@?rCw{Q9euXPIpFJ+3{Q1D6{c4b@K$CIHm&pbBKgQy!fu78xi5 zVK>Ywph#IG;(bLDY|i%fJ(c8N${HjE9hV)*z!SxfJ7`IU>SXcKtx|#BED2l1SMFJC zeSQ6h5hU@q);rVakzc2}ieY{MGCa~UCM=@QtIUUPx&>Ot=H@)_8-DP zzqy4I^UM_3lnX#Q9DSJY19O*OG*!ix9vu~^=fTT>G`I*EZhd{xOtJli2L6=pv9C2~ zPC~@BfVGiwMRnEtXMOV}tH%O7Sfb>>MUa7U;oX(Ho;O*EpHV-+4JYhRm-Tda%iB|2 zxGb&)uP%C2(_z|(AvR#ZM*S9F0kFC_xe$vMi>4{8ZsqxAirf_6PCT}5_AMS_z0XFL zZx=k>PW*VqAj`5hCX~>t%au*f>7U!c!Pw9PW{ zpA>zx;dkQNz`p()2LmubjJFsVby@3FUb}@|Ubc;2-bhA?&=G|7p3K8Ub}1dz-CT(l~SI<>w!D;9dn`cYfUKKnk=P{sgu#4 z!FX}0X&6k>5TosmS0QuE{Bbej(Io~0_J&ej3pnBd$SMz_zyd2?aX<$A_hI5(L=(yx zB24ukn9X)FZ|}t(r|f-$>P$M_djwv?&Q$B|(=l2u|0;4w)C&gE`lHhYri-<<1(>V; zI|N$6%GOU&cKN?FyDQlaoI$!$@7-&5+!5oOQi=M%CdV%u@B81RRqc3EHhneS_AvRiCPtVm6{K5#QqkbNjddOZY_TmC!$jM3Lu0!HuTcDtGBO@0 z%z0NF1vN{`K50KHwVQ|3QtWFczm4j-RkJSI zq852qAq~zmrtp+I@9n^bJqcvU8_p0_gb72v z?(UwEC4jq-*F1cBGmUT$%I4D2=m5(z{FjIIGs{*RRN(Vn4im)Kd# zO=bZ4l&EGY^di)vN5KMJgpus1Dh*`OztMAGh~>;(jkVn+IxGv$1aq#UTi3wSsbcip zU7^l%moA_)cjn1W4x5X`B^0XzUc>1S0}k1{>3e@G?%is|mTy$50XRx3Y0^|=v7>l| zSj_AOQ$UIs%}6ui{7!6nwn}Y=HABp&@nh!oN(c7tzCHMy^ziVoF31Ad931SsI=kK6 zF~xE&k1d8CAn4nD<+e&H!zyX)Ew(e^1KVZ0^%@IP1Wt;6F1v#{hJzXJglF{ow%^Tr zoL)Fj!LpdzzJ0jx{u|*ER+PQ6K4LA{zK)#}-=k%CJxF1Ry$ENcjlDNLx-(SDO}%D! z*DtH}zEoA=(7!%!I7ixjH3DU1WD|<%-kR0@K&4PgYZA2z9k@Alu00ZtjKr+tM_s-p zR}DeM_6L-YD=Jym*Io-0KaIE2gq&5<-;tApcqB5#-{QYul$Mi=E}BdkfN<2*A^8jl zRMoW@RUZ(Sk#7Iq<6;LDV0s3b^>MRi>tP2VCJq zT1xNxO}+3_3+%r7eGa3N{r>RvKYcOu9Fx-YW+s!N2#M%mLt^@feIB*6>HX73h3WfS z0V#%_EhqY5DHPPq3nSMC)NpPTArrrc!7%!y-pAbWtT-*2Q_rA&6+!P-)h4fTMqozf z*ZSf>fcx>+q+gcOKdoZrqTULNkkXS*-$W$KF26wH66DMkb4{~SXcJTj z!bV(NUlaLQx<$R#w2umC&!Kr7qpc-+P_1)d)z*8j9_$$@Znb+VuG3$ODn?4d#%s8! z0g}Aq6uA_2!VLVw$LE+_VUPCHpKtG-1(lSPu$7fD>_h1}s3~1tTXH_k2_D@@d49$i zT5aZZ-m{ve>Dv*Qjv+!f;Tedr$XJ-?V?!vr5&A1~7Ex@<&~)$Gm@E2Y14+0)i=v8F5ihsemJNp9EWiDep%H zmVpc~OK;~ZTf*cIzoQkb=r{od3L>|bWfr*$$WOQt3kzfs%Qozga|0Cn|I*uVMfzU> zJv`~g0ra-jRkp{!pZvdxYXAQlZ6X1d9*N}7MjHY;dhzIqKYPMZV>fj4+)(|oYk6rE KsZt3e|NjMhc;D^- literal 0 HcmV?d00001 diff --git a/slices/021-permission-gate/proof/ac5-denied.png b/slices/021-permission-gate/proof/ac5-denied.png new file mode 100644 index 0000000000000000000000000000000000000000..8be276c603572d4bccfe68799d40d41f8f52366f GIT binary patch literal 75462 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 literal 0 HcmV?d00001 diff --git a/slices/021-permission-gate/proof/ac7-permissions-audit.png b/slices/021-permission-gate/proof/ac7-permissions-audit.png new file mode 100644 index 0000000000000000000000000000000000000000..31670273a6bf66a06fef349bb6b8bf914abebbd9 GIT binary patch literal 99515 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 "object", + "properties" => %{"path" => %{"type" => "string"}, "text" => %{"type" => "string"}}, + "required" => ["path"], + "additionalProperties" => false + } + + @impl true + def risk, do: :write + @impl true + def effect, do: :artifact + @impl true + def execute(%{"path" => path} = args, _ctx), + do: {:ok, Result.text("wrote #{byte_size(Map.get(args, "text", ""))} bytes to #{path}")} +end diff --git a/test/trinity/permissions/fingerprint_test.exs b/test/trinity/permissions/fingerprint_test.exs new file mode 100644 index 0000000..82a0bb7 --- /dev/null +++ b/test/trinity/permissions/fingerprint_test.exs @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.FingerprintTest do + @moduledoc "Slice 021 line 1: the canonical form is RFC 8785's (the RFC's own vector), and the fingerprint binds every field." + use ExUnit.Case, async: true + + alias Trinity.Permissions.Fingerprint + + test "jcs matches the RFC 8785 example vector byte for byte" do + input = "test/support/rfc8785_input.json" |> File.read!() |> Jason.decode!() + expected = File.read!("test/support/rfc8785_expected.txt") + assert Fingerprint.canonical(input) == expected + end + + test "keys are sorted and numbers are ES6 shortest, whatever the map's order" do + assert Fingerprint.canonical(%{"b" => 1, "a" => %{"z" => 2.0, "y" => [1, "x"]}}) == + ~s({"a":{"y":[1,"x"],"z":2},"b":1}) + end + + test "the same call is the same digest; a changed argument, scope or cwd is another" do + fp = Fingerprint.of("write_note", %{"path" => "/a", "text" => "t"}, "session:1", nil) + assert fp == Fingerprint.of("write_note", %{"text" => "t", "path" => "/a"}, "session:1", nil) + assert String.match?(fp, ~r/^[0-9a-f]{64}$/) + refute fp == Fingerprint.of("write_note", %{"path" => "/b", "text" => "t"}, "session:1", nil) + refute fp == Fingerprint.of("write_note", %{"path" => "/a", "text" => "t"}, "session:2", nil) + + refute fp == + Fingerprint.of("write_note", %{"path" => "/a", "text" => "t"}, "session:1", "/home") + + assert Fingerprint.version() == 1 + end +end diff --git a/test/trinity/permissions/gate_test.exs b/test/trinity/permissions/gate_test.exs new file mode 100644 index 0000000..7da62ca --- /dev/null +++ b/test/trinity/permissions/gate_test.exs @@ -0,0 +1,195 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.GateTest do + @moduledoc """ + Slice 021: the layered policy in isolation and in order, the Gate's rows and broadcasts, + AC6 (expiry) and AC7's auto half (every decision a row with decided_at). + """ + use Trinity.DataCase, async: false + + alias Trinity.Factory + alias Trinity.Permissions + alias Trinity.Permissions.Approval + + setup do + row = Factory.session!() + :ok = Permissions.subscribe(row.id) + {:ok, id: row.id} + end + + @args %{"path" => "/home/me/notes/a.md", "text" => "hi"} + + describe "the layers" do + test "the default by tier: read allows, write asks, an unmapped name asks", %{id: id} do + assert Permissions.decide(id, "echo", %{"text" => "x"}) == :allow + assert Permissions.decide(id, "write_note", @args) == :ask + assert Permissions.decide(id, "mcp:x:anything", %{}) == :ask + end + + test "a global rule with a glob allows inside the pattern and not outside (AC4's core)", %{ + id: id + } do + {:ok, _} = + Permissions.put_rule(%{ + tool: "write_note", + pattern: "path=/home/me/notes/*.md", + decision: "allow" + }) + + assert Permissions.decide(id, "write_note", @args) == :allow + assert Permissions.decide(id, "write_note", %{"path" => "/etc/hosts"}) == :ask + end + + test "a persona policy sits above global rules and below session grants", %{id: id} do + persona = %{settings: %{"permissions" => %{"write_note" => "deny"}}} + {:ok, _} = Permissions.put_rule(%{tool: "write_note", pattern: "*", decision: "allow"}) + assert Permissions.decide(id, "write_note", @args, persona: persona) == :deny + fp = Permissions.fingerprint(id, "write_note", @args, nil) + + {:ok, _} = + Permissions.put_rule(%{ + tool: "write_note", + pattern: "fp:" <> fp, + decision: "allow", + scope: Permissions.scope(id) + }) + + assert Permissions.decide(id, "write_note", @args, persona: persona) == :allow + end + + test "a session grant is bound to the fingerprint: other arguments ask, another session asks (AC3's core)", + %{id: id} do + fp = Permissions.fingerprint(id, "write_note", @args, nil) + + {:ok, _} = + Permissions.put_rule(%{ + tool: "write_note", + pattern: "fp:" <> fp, + decision: "allow", + scope: Permissions.scope(id) + }) + + assert Permissions.decide(id, "write_note", @args) == :allow + assert Permissions.decide(id, "write_note", Map.put(@args, "text", "changed")) == :ask + other = Factory.session!() + assert Permissions.decide(other.id, "write_note", @args) == :ask + end + + test "an expired session grant no longer allows", %{id: id} do + fp = Permissions.fingerprint(id, "write_note", @args, nil) + past = DateTime.add(DateTime.utc_now(), -1, :second) + + {:ok, _} = + Permissions.put_rule(%{ + tool: "write_note", + pattern: "fp:" <> fp, + decision: "allow", + scope: Permissions.scope(id), + expires_at: past + }) + + assert Permissions.decide(id, "write_note", @args) == :ask + end + end + + describe "the Gate" do + test "a request is a row, then a broadcast on the session's topic and on all", %{id: id} do + :ok = Permissions.subscribe(:all) + {:ok, a} = Permissions.request_approval(id, "write_note", @args) + assert %Approval{status: "pending", risk: "write", fingerprint: fp} = a + assert fp == Permissions.fingerprint(id, "write_note", @args, nil) + assert_receive {:approval, :requested, %Approval{id: aid}} + assert_receive {:approval, :requested, %Approval{id: ^aid}} + assert aid == a.id + assert [%Approval{id: ^aid}] = Permissions.pending(id) + end + + test "once: the row is allowed with decided_at and decider, the fingerprint allows one execution, then asks again", + %{id: id} do + {:ok, a} = Permissions.request_approval(id, "write_note", @args) + + assert {:ok, + %Approval{ + status: "allowed", + decision: "once", + decided_by: "liveview", + decided_at: %DateTime{} + }} = + Permissions.decide_request(a.id, :once) + + assert_receive {:approval, :decided, %Approval{id: aid, status: "allowed"}} + assert aid == a.id + assert Permissions.decide(id, "write_note", @args) == :allow + assert Permissions.decide(id, "write_note", @args) == :ask + assert Permissions.pending(id) == [] + end + + test "session: a grant row scoped to the session with an expiry; the second identical call allows", + %{id: id} do + {:ok, a} = Permissions.request_approval(id, "write_note", @args) + {:ok, _} = Permissions.decide_request(a.id, :session) + [rule] = Permissions.list_rules(scope: Permissions.scope(id)) + assert rule.pattern == "fp:" <> a.fingerprint and rule.expires_at != nil + assert Permissions.decide(id, "write_note", @args) == :allow + assert Permissions.decide(id, "write_note", @args) == :allow + end + + test "always: a global rule with the confirmed pattern; a call outside it still asks (AC4)", + %{id: id} do + {:ok, a} = Permissions.request_approval(id, "write_note", @args) + {:ok, _} = Permissions.decide_request(a.id, :always, pattern: "path=/home/me/notes/*.md") + [rule] = Permissions.list_rules(scope: "global") + assert rule.tool == "write_note" and rule.decision == "allow" + assert Permissions.decide(id, "write_note", @args) == :allow + assert Permissions.decide(id, "write_note", %{"path" => "/home/me/secrets/k"}) == :ask + assert :ok = Permissions.revoke_rule(rule.id) + assert Permissions.decide(id, "write_note", @args) == :ask + end + + test "deny: the row is denied, the fingerprint is denied once, then asks again (AC5's core)", + %{id: id} do + {:ok, a} = Permissions.request_approval(id, "write_note", @args) + + {:ok, %Approval{status: "denied", decision: "deny"}} = + Permissions.decide_request(a.id, :deny) + + assert Permissions.decide(id, "write_note", @args) == :deny + assert Permissions.decide(id, "write_note", @args) == :ask + end + + test "a decided request cannot be decided twice; an unknown id is not found", %{id: id} do + {:ok, a} = Permissions.request_approval(id, "write_note", @args) + {:ok, _} = Permissions.decide_request(a.id, :deny) + assert {:error, {:already_decided, "denied"}} = Permissions.decide_request(a.id, :once) + assert {:error, :not_found} = Permissions.decide_request(Trinity.UUID.generate(), :once) + end + + test "AC6: an undecided request expires into a denial decided by expiry, within the configured timeout", + %{id: id} do + {:ok, a} = Permissions.request_approval(id, "write_note", @args) + + assert_receive {:approval, :decided, + %Approval{ + id: aid, + status: "expired", + decision: "deny", + decided_by: "expiry" + }}, + 1_000 + 500 + + assert aid == a.id + assert %Approval{decided_at: %DateTime{}} = Permissions.get_approval(a.id) + assert Permissions.decide(id, "write_note", @args) == :ask + end + + test "AC7: every decision is a row with decided_at, listed newest first", %{id: id} do + {:ok, a1} = Permissions.request_approval(id, "write_note", @args) + {:ok, a2} = Permissions.request_approval(id, "write_note", %{"path" => "/b"}) + {:ok, _} = Permissions.decide_request(a1.id, :once) + {:ok, _} = Permissions.decide_request(a2.id, :deny) + rows = Permissions.list_approvals(session_id: id) + assert Enum.map(rows, & &1.id) == [a2.id, a1.id] + assert Enum.all?(rows, &(&1.decided_at != nil and &1.decided_by == "liveview")) + end + end +end diff --git a/test/trinity/permissions/rule_test.exs b/test/trinity/permissions/rule_test.exs new file mode 100644 index 0000000..b6624a9 --- /dev/null +++ b/test/trinity/permissions/rule_test.exs @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.RuleTest do + @moduledoc "Slice 021: the pattern language of tool_permissions rows." + use ExUnit.Case, async: true + + alias Trinity.Permissions.Rule + + test "* matches anything; fp: matches the fingerprint only" do + assert Rule.matches?("*", %{"x" => 1}, nil) + assert Rule.matches?("fp:abc", %{}, "abc") + refute Rule.matches?("fp:abc", %{}, "abd") + end + + test "key=glob: * within a segment, ** across, ? one character, a trailing * is a prefix" do + assert Rule.matches?("path=/home/me/notes/*.md", %{"path" => "/home/me/notes/a.md"}, nil) + refute Rule.matches?("path=/home/me/notes/*.md", %{"path" => "/home/me/notes/sub/a.md"}, nil) + assert Rule.matches?("path=/home/me/**", %{"path" => "/home/me/notes/sub/a.md"}, nil) + refute Rule.matches?("path=/home/me/**", %{"path" => "/etc/passwd"}, nil) + assert Rule.matches?("command=git *", %{"command" => "git status"}, nil) + refute Rule.matches?("command=git *", %{"command" => "rm -rf /"}, nil) + assert Rule.matches?("n=?", %{"n" => 7}, nil) + refute Rule.matches?("path=/a", %{"other" => "/a"}, nil) + end + + test "re: is accepted from a hand-edited row; a broken regex matches nothing" do + assert Rule.matches?("re:^git (status|log)$", %{"command" => "git log"}, nil) + refute Rule.matches?("re:[", %{"command" => "x"}, nil) + end + + test "the changeset refuses a pattern outside the language and a scope outside the vocabulary" do + ok = + Rule.changeset(%Rule{}, %{ + tool: "t", + pattern: "path=/x/*", + decision: "allow", + scope: "global" + }) + + assert ok.valid? + + bad = + Rule.changeset(%Rule{}, %{ + tool: "t", + pattern: "nonsense", + decision: "allow", + scope: "global" + }) + + refute bad.valid? + bad2 = Rule.changeset(%Rule{}, %{tool: "t", pattern: "*", decision: "maybe", scope: "team"}) + assert Keyword.has_key?(bad2.errors, :decision) and Keyword.has_key?(bad2.errors, :scope) + end +end diff --git a/test/trinity/permissions/session_flow_test.exs b/test/trinity/permissions/session_flow_test.exs new file mode 100644 index 0000000..4cbe1a2 --- /dev/null +++ b/test/trinity/permissions/session_flow_test.exs @@ -0,0 +1,162 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule Trinity.Permissions.SessionFlowTest do + @moduledoc """ + Slice 021 through a Session: AC1 (a read tool never reaches the Gate), AC2's test half + (approval_wait, allow once, the tool runs, the final message), AC3, AC5 and AC8. + """ + use Trinity.SessionCase + @moduletag :capture_log + + alias Trinity.Factory + alias Trinity.LLM.Providers.Fake + alias Trinity.Permissions + alias Trinity.Permissions.Approval + + setup do + row = Factory.session!() + :ok = Sessions.subscribe(row.id) + :ok = Permissions.subscribe(row.id) + {:ok, id: row.id} + end + + @args %{"path" => "/home/me/notes/a.md", "text" => "hi"} + + defp tool_turn(calls, final \\ "done ") do + starts = for {id, name, _} <- calls, do: {:tool_call_start, id, name} + ends = for {id, _, args} <- calls, do: {:tool_call_end, id, args} + + Fake.scripts([ + starts ++ ends ++ [{:usage, %{input_tokens: 1, output_tokens: 1}}, {:done, :tool_calls}], + script_deltas(2, final) + ]) + end + + defp tool_rows(id), do: id |> Sessions.history() |> Enum.filter(&(&1.role == "tool")) + + test "AC1: a read-risk tool runs with no request: the Gate sees nothing", %{id: id} do + :ok = Permissions.subscribe(:all) + tool_turn([{"c1", "echo", %{"text" => "plain"}}]) + {:ok, pid} = start_drained(id) + {:ok, _} = Session.send_user_message(pid, "go") + events = collect(id, &match?({:state, :idle}, &1)) + refute :approval_wait in for({:state, s} <- events, do: s) + refute_received {:approval, _, _} + assert Permissions.list_approvals(session_id: id) == [] + assert [%{content: "plain"}] = tool_rows(id) + end + + test "AC2 (test half): a write-risk call enters approval_wait; allow once runs it; the final message follows", + %{id: id} do + tool_turn([{"c1", "write_note", @args}]) + {:ok, pid} = start_drained(id) + {:ok, _} = Session.send_user_message(pid, "write") + + assert_receive {:approval, :requested, + %Approval{id: aid, tool: "write_note", status: "pending"}}, + 2_000 + + _ = collect(id, &match?({:state, :approval_wait}, &1)) + assert %{state: :approval_wait} = Session.state(pid) + assert [%Approval{id: ^aid}] = Permissions.pending(id) + + {:ok, _} = Permissions.decide_request(aid, :once) + events = collect(id, &match?({:state, :idle}, &1)) + + assert {:assistant_message, %{content: "done done "}} = + Enum.find(events, &match?({:assistant_message, _}, &1)) + + assert [row] = tool_rows(id) + assert row.parts["ok"] == true and row.content =~ "wrote 2 bytes" + assert %Approval{status: "allowed", consumed_at: %DateTime{}} = Permissions.get_approval(aid) + end + + test "AC3: allow for session: the second identical call runs without asking; other arguments ask; a new session asks", + %{id: id} do + tool_turn([{"c1", "write_note", @args}]) + {:ok, pid} = start_drained(id) + {:ok, _} = Session.send_user_message(pid, "one") + assert_receive {:approval, :requested, %Approval{id: aid}}, 2_000 + {:ok, _} = Permissions.decide_request(aid, :session) + _ = collect(id, &match?({:state, :idle}, &1)) + + # The same call again: no request. + tool_turn([{"c1", "write_note", @args}]) + {:ok, _} = Session.send_user_message(pid, "two") + events = collect(id, &match?({:state, :idle}, &1)) + refute :approval_wait in for({:state, s} <- events, do: s) + refute_received {:approval, :requested, _} + assert length(tool_rows(id)) == 2 + + # Other arguments under the same grant: a request again (M2: the fingerprint differs). + tool_turn([{"c1", "write_note", Map.put(@args, "text", "changed")}]) + {:ok, _} = Session.send_user_message(pid, "three") + assert_receive {:approval, :requested, %Approval{id: aid3}}, 2_000 + {:ok, _} = Permissions.decide_request(aid3, :deny) + _ = collect(id, &match?({:state, :idle}, &1)) + + # A new session: asks. + other = Factory.session!() + :ok = Permissions.subscribe(other.id) + tool_turn([{"c1", "write_note", @args}]) + {:ok, opid} = start_drained(other.id) + {:ok, _} = Session.send_user_message(opid, "one") + assert_receive {:approval, :requested, %Approval{session_id: sid}}, 2_000 + assert sid == other.id + end + + test "AC5: deny: the tool row carries a denial the model reads; the turn goes on to a final message", + %{id: id} do + tool_turn([{"c1", "write_note", @args}, {"c2", "echo", %{"text" => "fine"}}], "after denial ") + {:ok, pid} = start_drained(id) + {:ok, _} = Session.send_user_message(pid, "write") + assert_receive {:approval, :requested, %Approval{id: aid}}, 2_000 + {:ok, _} = Permissions.decide_request(aid, :deny) + events = collect(id, &match?({:state, :idle}, &1)) + + assert Enum.any?( + events, + &match?({:assistant_message, %{content: "after denial after denial "}}, &1) + ) + + rows = tool_rows(id) + assert Enum.map(rows, & &1.tool_call_id) == ["c2", "c1"] + denied = Enum.find(rows, &(&1.tool_call_id == "c1")) + assert denied.parts["ok"] == false and denied.content == "error: :denied" + + assert Enum.map(Sessions.history(id), & &1.role) == [ + "user", + "assistant", + "tool", + "tool", + "assistant" + ] + end + + test "AC8: killed in approval_wait, the request is still pending and decidable; the restarted session is idle", + %{id: id} do + tool_turn([{"c1", "write_note", @args}]) + {:ok, pid} = start_drained(id) + {:ok, _} = Session.send_user_message(pid, "write") + assert_receive {:approval, :requested, %Approval{id: aid}}, 2_000 + _ = collect(id, &match?({:state, :approval_wait}, &1)) + + Process.exit(pid, :kill) + _ = collect(id, &match?({:state, :idle}, &1)) + {:ok, new_pid} = Sessions.ensure_started(id) + assert new_pid != pid + assert %{state: :idle, pending: []} = Session.state(new_pid) + + assert [%Approval{id: ^aid, status: "pending"}] = Permissions.pending(id) + + assert {:ok, %Approval{status: "allowed", decided_at: %DateTime{}}} = + Permissions.decide_request(aid, :once) + + assert_receive {:approval, :decided, %Approval{id: ^aid}} + assert Permissions.pending(id) == [] + # The turn that asked is gone with the process (012 AC9); the grant was recorded, not run. + assert tool_rows(id) == [] + {:ok, _} = Session.send_user_message(new_pid, "again") + _ = collect(id, &match?({:state, :idle}, &1)) + end +end diff --git a/test/trinity/tools/registry_test.exs b/test/trinity/tools/registry_test.exs index 433c011..73e7cdc 100644 --- a/test/trinity/tools/registry_test.exs +++ b/test/trinity/tools/registry_test.exs @@ -19,7 +19,7 @@ defmodule Trinity.Tools.RegistryTest do describe "AC1: a module plus one config line" do test "the four test tools are listed, in the core toolset, with schemas that build and digests" do names = Enum.map(Tools.list(), & &1.name) - assert names == ["big", "crash", "echo", "sleep"] + assert names == ["big", "crash", "echo", "sleep", "write_note"] assert Enum.map(Tools.list(toolset: :core), & &1.name) == names for entry <- Tools.list() do @@ -31,7 +31,7 @@ defmodule Trinity.Tools.RegistryTest do test "to_llm_tools/0 carries name, description and parameters for each" do tools = Tools.to_llm_tools() - assert Enum.map(tools, & &1.name) == ["big", "crash", "echo", "sleep"] + assert Enum.map(tools, & &1.name) == ["big", "crash", "echo", "sleep", "write_note"] for t <- tools do assert is_binary(t.description) and t.description != "" @@ -66,7 +66,8 @@ defmodule Trinity.Tools.RegistryTest do assert {:ok, %{module: TestTools.Echo}} = Tools.lookup("echo") assert {:ok, _} = Tools.register(TestTools.DynamicEcho) assert Trinity.Permissions.tier("mcp:fake:echo") == :ask - assert Trinity.Permissions.tier("echo") == :ask, "no core name is mapped at this slice" + # Slice 021: a core tool's declared risk is its tier, handed over by the registry. + assert Trinity.Permissions.tier("echo") == :read end test "a runtime registration claiming :catalog is refused by name" do diff --git a/test/trinity/tools/runner_test.exs b/test/trinity/tools/runner_test.exs index 698ffce..90bcb9c 100644 --- a/test/trinity/tools/runner_test.exs +++ b/test/trinity/tools/runner_test.exs @@ -156,7 +156,7 @@ defmodule Trinity.Tools.RunnerTest do on_exit(fn -> Application.delete_env(:trinity, :permissions_policy) end) Trinity.Permissions.PolicyMock - |> expect(:decide, 2, fn ^id, name, %{"text" => _} when name == "echo" -> :allow end) + |> expect(:decide, 2, fn ^id, name, %{"text" => _}, _opts when name == "echo" -> :allow end) tool_turn([{"c1", "echo", %{"text" => "a"}}, {"c2", "echo", %{"text" => "b"}}]) {_events, _elapsed, history} = run_turn(id) @@ -166,7 +166,7 @@ defmodule Trinity.Tools.RunnerTest do test "a denied call is an error row and execute/2 is not reached", %{id: id} do Application.put_env(:trinity, :permissions_policy, Trinity.Permissions.PolicyMock) on_exit(fn -> Application.delete_env(:trinity, :permissions_policy) end) - expect(Trinity.Permissions.PolicyMock, :decide, fn _, "crash", _ -> :deny end) + expect(Trinity.Permissions.PolicyMock, :decide, fn _, "crash", _, _ -> :deny end) tool_turn([{"c1", "crash", %{}}]) {_events, _elapsed, history} = run_turn(id) [row] = tool_rows(history) @@ -179,7 +179,15 @@ defmodule Trinity.Tools.RunnerTest do {_events, _elapsed, history} = run_turn(id) first = Enum.at(history, 1) assert first.provider_meta["tool_surface"] == Tools.surface() - assert Map.keys(first.provider_meta["tool_surface"]) == ["big", "crash", "echo", "sleep"] + + assert Map.keys(first.provider_meta["tool_surface"]) == [ + "big", + "crash", + "echo", + "sleep", + "write_note" + ] + assert Tools.surface_diff(history) == [%{seq: 2, name: "get_weather", reason: :undeclared}] end end diff --git a/test/trinity_web/live/approval_live_test.exs b/test/trinity_web/live/approval_live_test.exs new file mode 100644 index 0000000..1752273 --- /dev/null +++ b/test/trinity_web/live/approval_live_test.exs @@ -0,0 +1,157 @@ +# SPDX-FileCopyrightText: Sudo Apt Holdings LLC +# SPDX-License-Identifier: Apache-2.0 +defmodule TrinityWeb.ApprovalLiveTest do + @moduledoc "Slice 021 line 7: the card renders on a request, each button decides through the gate, /permissions lists rows." + use TrinityWeb.ConnCase, async: false + @moduletag :capture_log + + import Phoenix.LiveViewTest + import Trinity.SessionCase, only: [script_deltas: 2, collect: 3] + + alias Trinity.Factory + alias Trinity.LLM.Providers.Fake + alias Trinity.Permissions + alias Trinity.Permissions.Approval + alias Trinity.Sessions + + setup do + Fake.clear() + on_exit(fn -> Trinity.SessionCase.stop_all_sessions() end) + row = Factory.session!() + :ok = Sessions.subscribe(row.id) + :ok = Permissions.subscribe(row.id) + {:ok, id: row.id} + end + + @args %{"path" => "/home/me/notes/a.md", "text" => "hi"} + + defp write_turn do + Fake.scripts([ + [ + {:tool_call_start, "c1", "write_note"}, + {:tool_call_end, "c1", @args}, + {:usage, %{input_tokens: 1, output_tokens: 1}}, + {:done, :tool_calls} + ], + script_deltas(2, "written ") + ]) + end + + defp send_message(view, text), + do: view |> form("#composer", %{"content" => text}) |> render_submit() + + test "AC2 (LiveView half): the card renders with tool, risk and arguments; Allow once runs the tool and the final message follows", + %{conn: conn, id: id} do + write_turn() + {:ok, view, _} = live(conn, ~p"/s/#{id}") + send_message(view, "write it") + assert_receive {:approval, :requested, %Approval{id: aid}}, 2_000 + _ = collect(id, &match?({:state, :approval_wait}, &1), 2_000) + html = render(view) + assert has_element?(view, "#approval-#{aid}") + assert html =~ "write_note" and html =~ "write" and html =~ "/home/me/notes/a.md" + assert has_element?(view, "#status[data-status=approval_wait]") + assert has_element?(view, "#pending-approvals", "1") + assert has_element?(view, "#pattern-#{aid}[value='path=/home/me/notes/*']") + + view |> element("#approval-#{aid} button", "Allow once") |> render_click() + _ = collect(id, &match?({:state, :idle}, &1), 5_000) + html = render(view) + refute has_element?(view, "#approval-#{aid}") + assert html =~ "wrote 2 bytes" + assert html =~ "written written" + + assert %Approval{status: "allowed", decision: "once", decided_by: "liveview"} = + Permissions.get_approval(aid) + + refute has_element?(view, "#pending-approvals") + end + + test "Always allow writes the edited pattern as a rule; Deny denies", %{conn: conn, id: id} do + write_turn() + {:ok, view, _} = live(conn, ~p"/s/#{id}") + send_message(view, "write it") + assert_receive {:approval, :requested, %Approval{id: aid}}, 2_000 + _ = collect(id, &match?({:state, :approval_wait}, &1), 2_000) + + view |> form("#always-#{aid}", %{"pattern" => "path=/home/me/**"}) |> render_change() + view |> element("#approval-#{aid} button", "Always allow") |> render_click() + _ = collect(id, &match?({:state, :idle}, &1), 5_000) + + assert [%{pattern: "path=/home/me/**", scope: "global", decision: "allow"}] = + Permissions.list_rules() + + # Under the rule the next call runs without a card. + write_turn() + send_message(view, "again") + events = collect(id, &match?({:state, :idle}, &1), 5_000) + refute :approval_wait in for({:state, s} <- events, do: s) + + # A call outside the rule asks, and Deny records the denial. + Fake.scripts([ + [ + {:tool_call_start, "c1", "write_note"}, + {:tool_call_end, "c1", %{"path" => "/etc/hosts"}}, + {:usage, %{input_tokens: 1, output_tokens: 1}}, + {:done, :tool_calls} + ], + script_deltas(1, "after") + ]) + + send_message(view, "outside") + assert_receive {:approval, :requested, %Approval{id: aid2}}, 2_000 + _ = collect(id, &match?({:state, :approval_wait}, &1), 2_000) + view |> element("#approval-#{aid2} button", "Deny") |> render_click() + _ = collect(id, &match?({:state, :idle}, &1), 5_000) + assert %Approval{status: "denied"} = Permissions.get_approval(aid2) + assert render(view) =~ "error: :denied" + end + + test "/permissions lists every decision with its time and decider, the pending ones decidable, the rules revocable (AC7's page)", + %{conn: conn, id: id} do + {:ok, a1} = Permissions.request_approval(id, "write_note", @args) + {:ok, _} = Permissions.decide_request(a1.id, :session) + {:ok, a2} = Permissions.request_approval(id, "write_note", %{"path" => "/b"}) + + {:ok, view, html} = live(conn, ~p"/permissions") + assert has_element?(view, "#approval-row-#{a1.id}", "allowed") + assert has_element?(view, "#approval-row-#{a1.id}", "liveview") + assert has_element?(view, "#approval-row-#{a2.id}", "pending") + assert has_element?(view, "#approval-#{a2.id}") + assert html =~ "fp:" <> a1.fingerprint + [rule] = Permissions.list_rules() + assert has_element?(view, "#rule-#{rule.id}") + + view |> element("#approval-#{a2.id} button", "Deny") |> render_click() + assert has_element?(view, "#approval-row-#{a2.id}", "denied") + refute has_element?(view, "#approval-#{a2.id}") + + view |> element("#rule-#{rule.id} button", "Revoke") |> render_click() + refute has_element?(view, "#rule-#{rule.id}") + assert Permissions.list_rules() == [] + end + + test "the header indicator counts everyone's pending requests on every page", %{ + conn: conn, + id: id + } do + other = Factory.session!() + {:ok, view, _} = live(conn, ~p"/s/#{id}") + refute has_element?(view, "#pending-approvals") + {:ok, a} = Permissions.request_approval(other.id, "write_note", @args) + assert_receive_approval(a.id) + assert has_element?(view, "#pending-approvals", "1") + refute has_element?(view, "#approval-#{a.id}"), "another session's card does not render here" + {:ok, _} = Permissions.decide_request(a.id, :deny) + _ = render(view) + refute has_element?(view, "#pending-approvals") + end + + defp assert_receive_approval(id) do + :ok = Permissions.subscribe(:all) + # The page received the broadcast before this process subscribed; a render after a call + # to the gate is a render after the page handled it. + Process.sleep(50) + _ = id + end +end From a32d7057fd1253a84aac16822f1d61edf5cdad15 Mon Sep 17 00:00:00 2001 From: Ayla Croft Date: Sun, 20 Sep 2026 14:21:33 -0400 Subject: [PATCH 4/6] feat(s021): complete slice 021 (permission gate and approval UI) PROOF.md with every criterion's evidence: AC1, AC3, AC4, AC5, AC6 and AC8 from the Session-flow and Gate tests, AC2 and AC7 from their test halves plus screenshots under proof/ taken from the chat on the test registry, with the owner's two-step manual queue. NOTES.md carries the eight findings and the follow-ups. coverage.tsv: 021 at 72.45% from 67.18%. ROADMAP row 021 to done. Gate exit 0, 233 tests. Signed-off-by: Ayla Croft --- ROADMAP.md | 2 +- coverage.tsv | 1 + slices/021-permission-gate/NOTES.md | 50 +++++++++ slices/021-permission-gate/PROOF.md | 162 ++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 slices/021-permission-gate/PROOF.md diff --git a/ROADMAP.md b/ROADMAP.md index a38f4f0..4e878da 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -38,7 +38,7 @@ standards register names the rows that ask for them. | 012 | Session process + agent loop (gen_statem, DynamicSupervisor, rehydration) | 1 Core loop | L | 010, 011 | approved | | 013 | LiveView chat UI with streaming | 1 Core loop | M | 012 | approved | | 020 | Tool protocol + registry | 2 Tools | M | 012 | approved | -| 021 | Permission gate + approval UI (M2 fingerprint-bound, M7) | 2 Tools | M | 020, 013 | in_progress | +| 021 | Permission gate + approval UI (M2 fingerprint-bound, M7) | 2 Tools | M | 020, 013 | done | | 022 | Core tools: filesystem, web fetch/search, shell (MuonTrap) | 2 Tools | L | 021 | planned | | 023 | Context compaction + session lineage | 2 Tools | M | 012 | planned | | 024 | Effect catalog, authority selection (`TRINITY_AUTHORITY`), local receipts | 2 Tools | L | 021, 022 | planned | diff --git a/coverage.tsv b/coverage.tsv index fe89ee2..e2833d3 100644 --- a/coverage.tsv +++ b/coverage.tsv @@ -6,3 +6,4 @@ slice_id percent sha date 012 60.82 019d9cf 2026-09-20 013 64.41 080c543 2026-09-20 020 67.18 8a5b7ae 2026-09-20 +021 72.45 1f3727f 2026-09-20 diff --git a/slices/021-permission-gate/NOTES.md b/slices/021-permission-gate/NOTES.md index f698f71..55a5aa3 100644 --- a/slices/021-permission-gate/NOTES.md +++ b/slices/021-permission-gate/NOTES.md @@ -76,3 +76,53 @@ pre-checks, so `decide/3` stays exactly once per execution attempt (020 AC7) and call; "allow once" is an approval row consumed at its one use, not a rule; a denial is bound to the fingerprint for the turn that asked and never outlives it; the persona layer reads `personas.settings["permissions"]` (`tool => decision`), the smallest shape 030 can grow. + +## Lines 1 to 8, 2026-09-20: what was built, and what building it found + +**Built.** As planned: `Permissions.Fingerprint`, the migration with `Rule` and `Approval` and `Store`, +`Permissions` (the door: tiers, `decide/4`, requests, decisions, listings, topics), `Policy` with `Default` and +`Layered`, `Gate`, the runner's `:ask` path, the Session's `approval_wait` with `awaiting` and `held` on the turn, +`ApprovalComponents`, the card in the chat, `PermissionsLive`, the `write_note` test tool, the screenshot server +script. `jcs ~> 0.2` (its own commit). + +**Found while building, each recorded rather than smoothed.** + +1. **`decide/3` became `decide/4`.** The persona's policy needs the persona row and the fingerprint needs the + working directory, and Permissions may not read Sessions (a cycle), so the runner passes both from the tool + context as `opts`. 020's mocks moved to the four-arity callback; the count of one call per execution stands. +2. **The page hears each request twice.** The chat subscribes to the session's topic and to everyone's (for + the header count), and the Gate broadcasts on both, so the card doubled until the page ignored a second + arrival of the same id. LiveViewTest's duplicate-id check is what found it. +3. **A test expiry of 400 ms raced the tests that decide by hand**, so the expiry in test config is 1,000 ms + and AC6 waits up to 1,500. Two runs of the three suites green. +4. **The test-environment server for screenshots wrote into the test suite's database**: the next gate failed + four `usage_events` tests on rows nobody in the suite had written (012 found the same, its finding 6). The + script now names its own database file and the test one was reset; the script is in `scripts/` so the + owner's manual queue runs on the same thing the screenshots came from. +5. **Plug.Static serves a stale gzip.** With code reloading off (the test environment, and production) the + endpoint serves `app.css.gz` beside `app.css`, and `mix assets.build` rewrites only the latter, so the page + showed the previous slice's stylesheet while the file on disk was new. The script says to remove the `.gz` + files; `mix assets.deploy` regenerates them for a release. +6. **A table cell cannot truncate**: `truncate` on a `td` does nothing without `table-fixed` and a block child; + the audit page's arguments column pushed the decider off the screen until the table got fixed column widths + and a `div` per cell. +7. **The hidden `id` field in the always-allow form** collided with the form element's own id (a LiveView + compile warning, an error under the gate); it is `approval_id`. +8. **The `hero-hand-raised` icon did not render until the CSS was rebuilt**, which is finding 5 again from + the other side: a class used for the first time exists only after `mix assets.build`, and the gate builds + no assets (013 finding, unchanged). + +``` +$ mix test test/trinity/permissions test/trinity_web/live/approval_live_test.exs → 29 passed +$ mix gate → exit 0; 233 passed, 10 excluded; plan_check: PASS +$ mix test --cover → 72.45% total (Gate 88.68%, Layered 82.14%, Store 95.83%, PermissionsLive 89.23%) +$ mix credo --strict --all → 885 mods/funs, found no issues +``` + +## Follow-ups +- `Policy.Default` has no test of its own (0% coverage): it is the allow-all a test may configure; a one-line + test or its removal at 022. +- Gateway approvals (070) subscribe to the same topics; the card's four decisions map to four gateway replies. +- 024 reads `approvals` for decision receipts; the `consumed_at` column is what a receipt for an execution cites. +- The persona layer reads `settings["permissions"]`; 030's persona editor is where it gets a UI. +- `/permissions` lists the newest 200 approvals; a filter by session and a page size are 090's activity view. diff --git a/slices/021-permission-gate/PROOF.md b/slices/021-permission-gate/PROOF.md new file mode 100644 index 0000000..81dbdc3 --- /dev/null +++ b/slices/021-permission-gate/PROOF.md @@ -0,0 +1,162 @@ +# Proof for slice 021: Permission gate + approval UI + +Agent: Trinity · Coding Agent · Date: 2026-09-20 · Branch: slice/021-permission-gate · Final commit: (the commit carrying this file; named in the closing correction) + +## Summary +The gate docs/07 specifies: a tier from the tool name alone (written once by the registry from the core +modules' declared risks), a layered policy (session grants, the unspent decision for the fingerprint, persona, +global rules, the default by tier), approvals as rows before broadcasts with a fingerprint over RFC 8785 +canonical JSON re-derived at execution, a Gate with expiries that survive restarts, the Session's +`approval_wait`, the card, the header indicator and the `/permissions` audit. Every decision is +`decide_request/3`; no button carries authority. The canonicalisation library was measured first (NOTES.md): +`rfc8785` refuses this tree's OTP, `jcs` matches the RFC's own vector, which is now a test. Eight findings in +NOTES.md, the sharpest being a screenshot server that wrote into the test database and a stale gzip the +endpoint served over a fresh stylesheet. + +## Gate +``` +$ mix gate (this machine, OTP 28.5.0.5, Elixir 1.20.4, under a 32 GiB cgroup, tree 1f3727f) +885 mods/funs, found no issues. +... SCAN COMPLETE ... (sobelow --exit --skip: no finding) +No retired or security advisory packages found +No vulnerabilities found. +Result: 233 passed, 10 excluded +trinity.coverage: 020 67.18% vs 013 64.41%: OK +plan_check: PASS +exit=0 +``` +`mix credo --strict --all`: 885 mods/funs, found no issues. `mix assets.build`: exit 0. + +## Tests +``` +$ mix test --cover (tree 1f3727f) +Result: 233 passed, 10 excluded + | 0.00% | Trinity.Permissions.Policy.Default | + | 60.00% | Trinity.Permissions.Approval | + | 82.14% | Trinity.Permissions.Policy.Layered | + | 86.36% | Trinity.Permissions.Rule | + | 88.68% | Trinity.Permissions.Gate | + | 89.23% | TrinityWeb.PermissionsLive | + | 89.80% | TrinityWeb.ApprovalComponents | + | 91.67% | Trinity.Permissions | + | 95.83% | Trinity.Permissions.Store | + | 100.00% | Trinity.Permissions.Fingerprint | + | 100.00% | Trinity.Permissions.Policy | + | 72.45% | Total | +``` +`coverage.tsv` row: `021 72.45 1f3727f 2026-09-20` (from 67.18 at 020). + +The 29 tests of `test/trinity/permissions` and `test/trinity_web/live/approval_live_test.exs`, with timings from `--trace`: +``` +test AC1: a read-risk tool runs with no request: the Gate sees nothing * test AC1: a read-risk tool runs with no request: the Gate sees nothing (4.0ms) [L#37] +test AC2 (LiveView half): the card renders with tool, risk and arguments; Allow once runs the tool and the final message follows * test AC2 (LiveView half): the card renders with tool, risk and arguments; Allow once runs the tool and the final message follows (12.2ms) [L#43] +test AC2 (test half): a write-risk call enters approval_wait; allow once runs it; the final message follows * test AC2 (test half): a write-risk call enters approval_wait; allow once runs it; the final message follows (5.0ms) [L#49] +test AC3: allow for session: the second identical call runs without asking; other arguments ask; a new session asks * test AC3: allow for session: the second identical call runs without asking; other arguments ask; a new session asks (1044.2ms) [L#74] +test AC5: deny: the tool row carries a denial the model reads; the turn goes on to a final message * test AC5: deny: the tool row carries a denial the model reads; the turn goes on to a final message (5.0ms) [L#108] +test AC8: killed in approval_wait, the request is still pending and decidable; the restarted session is idle * test AC8: killed in approval_wait, the request is still pending and decidable; the restarted session is idle (7.5ms) [L#136] +test Always allow writes the edited pattern as a rule; Deny denies * test Always allow writes the edited pattern as a rule; Deny denies (50.1ms) [L#70] +test jcs matches the RFC 8785 example vector byte for byte * test jcs matches the RFC 8785 example vector byte for byte (6.4ms) [L#9] +test key=glob: * within a segment, ** across, ? one character, a trailing * is a prefix * test key=glob: * within a segment, ** across, ? one character, a trailing * is a prefix (0.1ms) [L#15] +test keys are sorted and numbers are ES6 shortest, whatever the map's order * test keys are sorted and numbers are ES6 shortest, whatever the map's order (0.02ms) [L#15] +test * matches anything; fp: matches the fingerprint only * test * matches anything; fp: matches the fingerprint only (0.00ms) [L#9] +test /permissions lists every decision with its time and decider, the pending ones decidable, the rules revocable (AC7's page) * test /permissions lists every decision with its time and decider, the pending ones decidable, the rules revocable (AC7's page) (84.9ms) [L#110] +test re: is accepted from a hand-edited row; a broken regex matches nothing * test re: is accepted from a hand-edited row; a broken regex matches nothing (0.03ms) [L#26] +test the changeset refuses a pattern outside the language and a scope outside the vocabulary * test the changeset refuses a pattern outside the language and a scope outside the vocabulary (0.06ms) [L#31] +test the Gate AC6: an undecided request expires into a denial decided by expiry, within the configured timeout * test the Gate AC6: an undecided request expires into a denial decided by expiry, within the configured timeout (1001.6ms) [L#167] +test the Gate AC7: every decision is a row with decided_at, listed newest first * test the Gate AC7: every decision is a row with decided_at, listed newest first (0.8ms) [L#185] +test the Gate a decided request cannot be decided twice; an unknown id is not found * test the Gate a decided request cannot be decided twice; an unknown id is not found (0.5ms) [L#160] +test the Gate always: a global rule with the confirmed pattern; a call outside it still asks (AC4) * test the Gate always: a global rule with the confirmed pattern; a call outside it still asks (AC4) (32.5ms) [L#137] +test the Gate a request is a row, then a broadcast on the session's topic and on all * test the Gate a request is a row, then a broadcast on the session's topic and on all (0.8ms) [L#96] +test the Gate deny: the row is denied, the fingerprint is denied once, then asks again (AC5's core) * test the Gate deny: the row is denied, the fingerprint is denied once, then asks again (AC5's core) (2.2ms) [L#149] +test the Gate once: the row is allowed with decided_at and decider, the fingerprint allows one execution, then asks again * test the Gate once: the row is allowed with decided_at and decider, the fingerprint allows one execution, then asks again (0.8ms) [L#107] +test the Gate session: a grant row scoped to the session with an expiry; the second identical call allows * test the Gate session: a grant row scoped to the session with an expiry; the second identical call allows (0.7ms) [L#127] +test the header indicator counts everyone's pending requests on every page * test the header indicator counts everyone's pending requests on every page (61.4ms) [L#134] +test the layers a global rule with a glob allows inside the pattern and not outside (AC4's core) * test the layers a global rule with a glob allows inside the pattern and not outside (AC4's core) (0.6ms) [L#29] +test the layers an expired session grant no longer allows * test the layers an expired session grant no longer allows (0.4ms) [L#78] +test the layers a persona policy sits above global rules and below session grants * test the layers a persona policy sits above global rules and below session grants (0.7ms) [L#43] +test the layers a session grant is bound to the fingerprint: other arguments ask, another session asks (AC3's core) * test the layers a session grant is bound to the fingerprint: other arguments ask, another session asks (AC3's core) (0.8ms) [L#60] +test the layers the default by tier: read allows, write asks, an unmapped name asks * test the layers the default by tier: read allows, write asks, an unmapped name asks (0.7ms) [L#23] +test the same call is the same digest; a changed argument, scope or cwd is another * test the same call is the same digest; a changed argument, scope or cwd is another (6.0ms) [L#20] +``` + +## Acceptance criteria evidence + +### AC1 [auto]: a read-risk tool executes with no approval (the Gate not called) +`AC1: a read-risk tool runs with no request: the Gate sees nothing`: subscribed to `approvals:all`, a turn calling +`echo` never enters `approval_wait`, no `{:approval, _, _}` arrives, `list_approvals(session_id:)` is empty, the +tool row is the echo. The Gate is a process, not a behaviour, so "not called" is measured as "no row and no +broadcast", which is everything a call would produce. The policy's default: `the default by tier: read allows, +write asks, an unmapped name asks`. + +### AC2 [manual]: write-risk tool → approval_wait; the card renders; allow once → the tool runs → final message +Tests: `AC2 (test half): a write-risk call enters approval_wait; allow once runs it; the final message follows` +(Session: the request broadcast, `state/1` says `approval_wait`, `pending/1` lists it; after `:once` the tool row +reads "wrote 2 bytes", the final message arrives, the approval is `allowed` and consumed) and `AC2 (LiveView +half)` (the card with tool, risk badge and arguments, status `approval_wait`, the header indicator at 1, the +suggested pattern `path=/home/me/notes/*`; Allow once clears the card, the tool result and the final text are on +the page, the row is `allowed once liveview`). Screenshots from the chat on the test registry +(`scripts/dev_chat_on_test_registry.sh`): `proof/ac2-approval-card.png` and `proof/ac2-allow-once-final.png`. + +### AC3 [auto]: allow for session → the second identical call runs without asking; a new session asks again +`AC3: allow for session ...` (Session): after `:session`, the identical call runs with no request; other +arguments under the same grant ask again (M2: the fingerprint differs); a new session asks. Core: `a session +grant is bound to the fingerprint: other arguments ask, another session asks` and `an expired session grant no +longer allows`; the grant row: `session: a grant row scoped to the session with an expiry`. + +### AC4 [auto]: always allow with a path pattern → a persisted rule; a call outside the pattern still asks +`always: a global rule with the confirmed pattern; a call outside it still asks` (the rule row with the pattern; +inside allows, `/home/me/secrets/k` asks; revoked, it asks again) and, through the page, `Always allow writes +the edited pattern as a rule; Deny denies` (the pattern edited to `path=/home/me/**` before the click, the rule +row carries it, the next call runs without a card, a call at `/etc/hosts` asks). The pattern language: +`Trinity.Permissions.RuleTest`. + +### AC5 [auto]: deny → the tool message carries a denial the model can read; the session continues +`AC5: deny: the tool row carries a denial the model reads; the turn goes on to a final message`: two calls in +one turn, one denied and one echo; rows `["user", "assistant", "tool", "tool", "assistant"]`, the denied row +`error: :denied` with `ok: false`, the final message from the next model call. Screenshot +`proof/ac5-denied.png` (the fake's canned final text after the denial is the script's, not the model's). + +### AC6 [auto]: expiry → auto-deny after the configured timeout +`AC6: an undecided request expires into a denial decided by expiry, within the configured timeout`: with +`expiry_ms: 1_000`, the `{:approval, :decided, %{status: "expired", decision: "deny", decided_by: "expiry"}}` +broadcast arrives within 1,500 ms, the row has `decided_at`, and the call asks again afterwards. + +### AC7 [manual]: every decision has an approvals row with decided_at; /permissions lists them +`AC7: every decision is a row with decided_at, listed newest first` and `/permissions lists every decision with its +time and decider, the pending ones decidable, the rules revocable`. Screenshot `proof/ac7-permissions-audit.png` +(nine decisions from the screenshot runs, each with its time, tool, risk, arguments, decision and decider). + +### AC8 [auto]: killing the Session during approval_wait → after restart the approval is still pending and decidable +`AC8: killed in approval_wait, the request is still pending and decidable; the restarted session is idle`: +`Process.exit(pid, :kill)` in `approval_wait`; the supervisor restarts the session idle with nothing pending +(012's reset is total); `pending/1` still lists the row; `decide_request/3` records it and broadcasts; the tool +did not run (the turn died with the process) and the session takes the next message. + +### Platform alignment: M2 and M7 +M2: `Trinity.Permissions.FingerprintTest` (the RFC vector; the same call the same digest; a changed argument, +scope or cwd another) and the AC3 test's "other arguments ask again". M7: the card's buttons and the audit page +push `approval_decide`, which calls `decide_request/3`; the LiveView tests drive the buttons and read the rows. + +## Manual verification for the reviewer +1. AC2: `mix assets.build`, remove `priv/static/assets/**/*.gz`, then `scripts/dev_chat_on_test_registry.sh`; + open the printed port, New session, send anything. Expected: the reply starts, the card appears with + `write_note`, the `WRITE` badge, the arguments and the four buttons; Allow once; the tool result and the + final message follow. +2. AC7: send another message, Deny; open `/permissions`. Expected: both decisions listed with times and + `liveview` as the decider. + +## Deviations from SLICE.md +See NOTES.md: the four stated at G1 (no pre-check, once as a consumed approval, a denial bound to its turn, +the persona layer's shape) and finding 1 (`decide/4`). + +## Versions touched +`VERSIONS.md` updated: yes, `jcs ~> 0.2` added with its row (the `rfc8785` alternative and why not, in the row). +`mix hex.audit` and `mix deps.audit` clean. + +## Git +``` +$ git log --oneline main..HEAD +1f3727f feat(s021): the permission gate: layered policy, fingerprints, the Gate, approval_wait, the card and the audit +897be2b chore(s021): add jcs ~> 0.2 +c3125f8 docs(s021): G1 plan with the canonicalisation measured, and the slice opens +``` From c5bd5fc7e4ba2414501ae97a460beae9edd972eb Mon Sep 17 00:00:00 2001 From: Ayla Croft Date: Sun, 20 Sep 2026 14:21:33 -0400 Subject: [PATCH 5/6] docs(s021): PROOF.md names the closing commit's sha Signed-off-by: Ayla Croft --- slices/021-permission-gate/PROOF.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/slices/021-permission-gate/PROOF.md b/slices/021-permission-gate/PROOF.md index 81dbdc3..3365b6a 100644 --- a/slices/021-permission-gate/PROOF.md +++ b/slices/021-permission-gate/PROOF.md @@ -160,3 +160,8 @@ $ git log --oneline main..HEAD 897be2b chore(s021): add jcs ~> 0.2 c3125f8 docs(s021): G1 plan with the canonicalisation measured, and the slice opens ``` + +## Closing correction, 2026-09-20 +Supersedes the "Final commit" field in the header: the commit carrying this file is `a32d705` +(`feat(s021): complete slice 021 (permission gate and approval UI)`); the `git log` block above lists the +commits before it. The pull request, its merge commit (signed in its body) and the tag come after review. From e8e1e9131487bb3708200834a5488b44b9a26f83 Mon Sep 17 00:00:00 2001 From: Ayla Croft Date: Sun, 20 Sep 2026 14:33:10 -0400 Subject: [PATCH 6/6] fix(s021): the Gate reloads its pending rows after init and survives a missing table Red: the postgres job on pull request #28 (run 35528824468) booted the application before migrating and the Gate's init/1 read the approvals table: `relation "approvals" does not exist`, the application refused to start. The reload is a handle_continue that rescues into a warning, so a Gate that cannot read its table starts empty and the chat starts; a request made before the table exists fails on its own insert. NOTES.md finding 9, PROOF.md correction. Signed-off-by: Ayla Croft --- lib/trinity/permissions/gate.ex | 26 +++++++++++++++++++++++--- slices/021-permission-gate/NOTES.md | 7 +++++++ slices/021-permission-gate/PROOF.md | 6 ++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/trinity/permissions/gate.ex b/lib/trinity/permissions/gate.ex index 2f2508e..8fdad5f 100644 --- a/lib/trinity/permissions/gate.ex +++ b/lib/trinity/permissions/gate.ex @@ -10,6 +10,8 @@ defmodule Trinity.Permissions.Gate do """ use GenServer + require Logger + alias Trinity.Permissions alias Trinity.Permissions.{Approval, Store} @@ -40,10 +42,28 @@ defmodule Trinity.Permissions.Gate do ## GenServer + # The pending rows are reloaded after init returns, and a database that cannot answer (no + # table yet: the postgres CI job boots the application before it migrates, run 35528824468) + # is a warning, not a boot failure: the chat starts, and a request made before the table + # exists fails on its own insert with a reason. + @impl true + def init(_opts), do: {:ok, %{timers: %{}}, {:continue, :reload}} + @impl true - def init(_opts) do - timers = Map.new(Store.pending(), fn a -> {a.id, arm(a)} end) - {:ok, %{timers: timers}} + def handle_continue(:reload, state) do + timers = + try do + Map.new(Store.pending(), fn a -> {a.id, arm(a)} end) + rescue + e -> + Logger.warning( + "permissions gate: pending approvals not reloaded: #{Exception.message(e)}" + ) + + %{} + end + + {:noreply, %{state | timers: timers}} end @impl true diff --git a/slices/021-permission-gate/NOTES.md b/slices/021-permission-gate/NOTES.md index 55a5aa3..c756580 100644 --- a/slices/021-permission-gate/NOTES.md +++ b/slices/021-permission-gate/NOTES.md @@ -126,3 +126,10 @@ $ mix credo --strict --all - 024 reads `approvals` for decision receipts; the `consumed_at` column is what a receipt for an execution cites. - The persona layer reads `settings["permissions"]`; 030's persona editor is where it gets a UI. - `/permissions` lists the newest 200 approvals; a filter by session and a page size are 090's activity view. + +9. **The Gate took the application down when its table was missing.** The postgres job boots the application + (`mix run -e 'Ecto.Adapters.Postgres = Trinity.Repo.__adapter__()'`) before it migrates, and `init/1` read + `approvals` there: run 35528824468, `relation "approvals" does not exist`, the `gate` job green beside it. + The reload moved to a `handle_continue` that rescues and warns; a Gate that cannot read its table at boot + starts empty rather than stopping the chat, and a request made before the table exists fails on its own + insert with a reason. Found by CI, not here: this machine has no Postgres. diff --git a/slices/021-permission-gate/PROOF.md b/slices/021-permission-gate/PROOF.md index 3365b6a..30461f2 100644 --- a/slices/021-permission-gate/PROOF.md +++ b/slices/021-permission-gate/PROOF.md @@ -165,3 +165,9 @@ c3125f8 docs(s021): G1 plan with the canonicalisation measured, and the slice op Supersedes the "Final commit" field in the header: the commit carrying this file is `a32d705` (`feat(s021): complete slice 021 (permission gate and approval UI)`); the `git log` block above lists the commits before it. The pull request, its merge commit (signed in its body) and the tag come after review. + +## Correction, 2026-09-20: the postgres job +The `postgres` check failed on the closing tree (run 35528824468): the Gate's `init/1` read the `approvals` +table in a job that boots the application before migrating (NOTES.md finding 9). Fixed in the commit after this +record: the reload is a `handle_continue` that rescues into a warning. The `gate` job was green on the same tree. +The run that closes this is named in the next correction.