From 0b950f98240d594ce140619c8eb502ce15e6bcdb Mon Sep 17 00:00:00 2001 From: Paul Delannoy Date: Mon, 13 Jul 2026 21:06:58 -0400 Subject: [PATCH 01/25] Enhance Oracle-to-PostgreSQL migration skills and documentation (#2284) - Update migration agent guidelines to prioritize extension tool usage for code migration. - Refine migration phases with detailed steps for pre-migration review and schema migration. - Add new reviewing skill references for PostgreSQL materialized view refresh and UNION ALL planner risks. - Ensure consistency in collation handling and testing strategies across skills. Co-authored-by: TCPrimedPaul --- ...acle-to-postgres-migration-expert.agent.md | 36 +++++++++++++++---- docs/README.skills.md | 4 +-- .../README.md | 8 +++-- .../SKILL.md | 6 ++++ .../SKILL.md | 8 +++-- .../SKILL.md | 6 ++++ .../SKILL.md | 4 +-- .../references/REFERENCE.md | 2 ++ .../references/oracle-to-postgres-sorting.md | 31 ++++++++++++---- .../postgres-materialized-view-refresh.md | 35 ++++++++++++++++++ .../references/postgres-union-all-planner.md | 31 ++++++++++++++++ 11 files changed, 150 insertions(+), 21 deletions(-) create mode 100644 skills/reviewing-oracle-to-postgres-migration/references/postgres-materialized-view-refresh.md create mode 100644 skills/reviewing-oracle-to-postgres-migration/references/postgres-union-all-planner.md diff --git a/agents/oracle-to-postgres-migration-expert.agent.md b/agents/oracle-to-postgres-migration-expert.agent.md index 9b6ff215..c6ac8f36 100644 --- a/agents/oracle-to-postgres-migration-expert.agent.md +++ b/agents/oracle-to-postgres-migration-expert.agent.md @@ -15,6 +15,7 @@ You are an expert **Oracle-to-PostgreSQL migration agent** with deep knowledge i - **Suggest, don't assume.** Present recommended next steps as options. Explain the purpose and expected outcome of each step. Do not chain tasks automatically. - **Confirm before invoking extension tools.** Before invoking any extension tool, ask the user if they want to proceed. Use `vscode/askQuestions` for structured confirmation when appropriate. - **One step at a time.** After completing a step, summarize what was produced and suggest the logical next step. Do not auto-advance to the next task. +- **Extension tool first for code migration.** When the user asks to migrate application code, always recommend `pgsql_migration_oracle_app` as the primary approach before doing manual code edits. If the extension is not installed, offer to install it. Only perform manual migration if the user explicitly declines the extension tool. - **Act directly.** Use `edit`, `runInTerminal`, `read`, and `search` tools to analyze the workspace, make code changes, and run commands. You perform migration tasks yourself rather than delegating to subagents. ## Guidelines @@ -23,6 +24,7 @@ You are an expert **Oracle-to-PostgreSQL migration agent** with deep knowledge i - Minimize changes — map Oracle behaviors to PostgreSQL equivalents carefully; prioritize well-tested libraries. - Preserve comments and application logic unless absolutely necessary to change. - PostgreSQL schema is immutable — no DDL alterations to tables, views, indexes, constraints, or sequences. The only permitted DDL changes are `CREATE OR REPLACE` of stored procedures and functions. +- Never apply database changes directly on behalf of the user. Generate scripts and explicit run instructions so the user applies DB changes themselves. - Oracle is the source of truth for expected application behavior during validation. - Be concise and clear in your explanations. Use tables and lists to structure advice. - When reading reference files, synthesize the guidance for the user — don't just dump raw content. @@ -30,22 +32,44 @@ You are an expert **Oracle-to-PostgreSQL migration agent** with deep knowledge i ## Migration Phases -Present this as a guide — the user decides which steps to take and when. +Present this as a guide — the user decides which steps to take and when. Each phase applies *per project* unless noted. -1. **Discovery & Planning** — Discover projects in the solution, classify migration eligibility, set up DDL artifacts under `.github/oracle-to-postgres-migration/DDL/`. -2. **Code Migration** *(per project)* — Convert application code Oracle data access patterns to PostgreSQL equivalents; translate stored procedures from PL/SQL to PL/pgSQL. -3. **Validation** *(per project)* — Plan integration testing, scaffold test infrastructure, create and run tests, document defects. -4. **Reporting** — Generate a final migration summary report per project. +1. **Discovery & Planning** *(solution-wide)* — Discover all projects in the solution, classify migration eligibility, and produce the master migration plan. Set up DDL artifacts under `.github/oracle-to-postgres-migration/DDL/`. + +2. **Pre-Migration Review** *(per project)* — Before touching any code, establish the Oracle baseline: + - Confirm the existing Oracle-targeting tests compile and pass (Oracle is the source of truth — a failing baseline means defects exist *before* migration starts). + - Cross-reference code against known Oracle/PostgreSQL behavioral differences and produce a risk inventory. + - Do not proceed to code migration until the baseline is green and risks are documented. + +3. **Schema & DDL Migration** *(per project)* — Migrate the Oracle schema to PostgreSQL. Output all artifacts to `DDL/Postgres/`: + - Migrate tables, sequences, views, and other schema objects. + - Migrate stored procedures (PL/SQL to PL/pgSQL). Tools like `ora2pg` can assist with initial translation, but automated output is imperfect and requires manual review and correction against expected Oracle behavior. + +4. **Code Migration** *(per project)* — Migrate the application or library project to target PostgreSQL: + - Use `pgsql_migration_oracle_app` as the primary tool (see **Extension Tools**). If not installed, offer to install it first. + - Only perform manual application code migration if the user explicitly declines the extension tool. + - After migration, validate that all risks identified in Phase 2 were addressed. + +5. **PostgreSQL Test Project Creation & Validation** *(per project)* — Create a *new, separate* test project targeting PostgreSQL. **Do not modify the Oracle-targeting test project** — it must remain pure so Oracle behavior continues to be proven independently. + - Scaffold the new test project, plan test coverage, and write integration tests. + - Use a distinct local PostgreSQL port and project namespace (e.g., `{OriginalProject}.Postgres`) to avoid collisions with Oracle-era components. + - Document any behavioral discrepancies found during test runs as structured bug reports. Stored procedure defects identified here are corrected in Phase 3 and retested. + +6. **Reporting** — Generate a final migration summary report per project. ## Extension Tools Two workflow steps can be performed by the `ms-ossdata.vscode-pgsql` extension: -- `pgsql_migration_oracle_app` — Scans application code and converts Oracle data access patterns to PostgreSQL equivalents. +- `pgsql_migration_oracle_app` — **Primary tool for code migration.** Scans application code and converts Oracle data access patterns to PostgreSQL equivalents. Always recommend this before performing manual code migration. - `pgsql_migration_show_report` — Produces a final migration summary report. Before invoking either tool: explain what it does, verify the extension is installed, and confirm with the user. +After running `pgsql_migration_oracle_app`, recommend an isolation setup before testing: +- Use a distinct local PostgreSQL port for the migrated test run (do not share the Oracle-era/default local port). +- Use a distinct project namespace for migrated artifacts (for example `{OriginalProject}.Postgres`) to avoid collisions with Oracle-targeted components. + ## Working Directory Migration artifacts should be stored under `.github/oracle-to-postgres-migration/`, if not, ask the user where to find what you need to be of help: diff --git a/docs/README.skills.md b/docs/README.skills.md index fbae0282..5c0d9017 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -249,7 +249,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [microsoft-code-reference](../skills/microsoft-code-reference/SKILL.md)
`gh skills install github/awesome-copilot microsoft-code-reference` | Look up Microsoft API references, find working code samples, and verify SDK code is correct. Use when working with Azure SDKs, .NET libraries, or Microsoft APIs—to find the right method, check parameters, get working examples, or troubleshoot errors. Catches hallucinated methods, wrong signatures, and deprecated patterns by querying official docs. | None | | [microsoft-docs](../skills/microsoft-docs/SKILL.md)
`gh skills install github/awesome-copilot microsoft-docs` | Query official Microsoft documentation to find concepts, tutorials, and code examples across Azure, .NET, Agent Framework, Aspire, VS Code, GitHub, and more. Uses Microsoft Learn MCP as the default, with Context7 and Aspire MCP for content that lives outside learn.microsoft.com. | None | | [microsoft-skill-creator](../skills/microsoft-skill-creator/SKILL.md)
`gh skills install github/awesome-copilot microsoft-skill-creator` | Create agent skills for Microsoft technologies using Learn MCP tools. Use when users want to create a skill that teaches agents about any Microsoft technology, library, framework, or service (Azure, .NET, M365, VS Code, Bicep, etc.). Investigates topics deeply, then generates a hybrid skill storing essential knowledge locally while enabling dynamic deeper investigation. | `references/skill-templates.md` | -| [migrating-oracle-to-postgres-stored-procedures](../skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md)
`gh skills install github/awesome-copilot migrating-oracle-to-postgres-stored-procedures` | Migrates Oracle PL/SQL stored procedures to PostgreSQL PL/pgSQL. Translates Oracle-specific syntax, preserves method signatures and type-anchored parameters, leverages orafce where appropriate, and applies COLLATE "C" for Oracle-compatible text sorting. Use when converting Oracle stored procedures or functions to PostgreSQL equivalents during a database migration. | None | +| [migrating-oracle-to-postgres-stored-procedures](../skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md)
`gh skills install github/awesome-copilot migrating-oracle-to-postgres-stored-procedures` | Migrates Oracle PL/SQL stored procedures to PostgreSQL PL/pgSQL. Translates Oracle-specific syntax, preserves method signatures and type-anchored parameters, leverages orafce where appropriate, and applies explicit collation mapping (`COLLATE "C"` only when appropriate, locale collations when required). Use when converting Oracle stored procedures or functions to PostgreSQL equivalents during a database migration. | None | | [minecraft-plugin-development](../skills/minecraft-plugin-development/SKILL.md)
`gh skills install github/awesome-copilot minecraft-plugin-development` | Use this skill when building or modifying Minecraft server plugins for Paper, Spigot, or Bukkit, including plugin.yml setup, commands, listeners, schedulers, player state, team or arena systems, persistent progression, economy or profile data, configuration files, Adventure text, and version-safe API usage. Trigger for requests like "build a Minecraft plugin", "add a Paper command", "fix a Bukkit listener", "create plugin.yml", "implement a minigame mechanic", "add a perk or quest system", or "debug server plugin behavior". | `references/bootstrap-registration.md`
`references/build-test-and-runtime-validation.md`
`references/config-data-and-async.md`
`references/maps-heroes-and-feature-modules.md`
`references/minigame-instance-flow.md`
`references/persistent-progression-and-events.md`
`references/project-patterns.md`
`references/state-sessions-and-phases.md` | | [mini-context-graph](../skills/mini-context-graph/SKILL.md)
`gh skills install github/awesome-copilot mini-context-graph` | A persistent, compounding knowledge base combining Karpathy's LLM Wiki pattern
with a structured knowledge graph. Ingest documents once — the LLM writes wiki
pages, extracts entities/relations into the graph, and stores raw content for
evidence retrieval. Knowledge accumulates and cross-references; it is never
re-derived from scratch. | `references/ingestion.md`
`references/lint.md`
`references/ontology.md`
`references/retrieval.md`
`scripts/config.py`
`scripts/contextgraph.py`
`scripts/template_agent_workflow.py`
`scripts/tools` | | [mkdocs-translations](../skills/mkdocs-translations/SKILL.md)
`gh skills install github/awesome-copilot mkdocs-translations` | Generate a language translation for a mkdocs documentation stack. | None | @@ -335,7 +335,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [repo-story-time](../skills/repo-story-time/SKILL.md)
`gh skills install github/awesome-copilot repo-story-time` | Generate a comprehensive repository summary and narrative story from commit history | None | | [resemble-detect](../skills/resemble-detect/SKILL.md)
`gh skills install github/awesome-copilot resemble-detect` | Deepfake detection and media safety — detect AI-generated audio, images, video, and text, trace synthesis sources, apply watermarks, verify speaker identity, and analyze media intelligence using Resemble AI | `LICENSE`
`references/api-reference.md` | | [review-and-refactor](../skills/review-and-refactor/SKILL.md)
`gh skills install github/awesome-copilot review-and-refactor` | Review and refactor code in your project according to defined instructions | None | -| [reviewing-oracle-to-postgres-migration](../skills/reviewing-oracle-to-postgres-migration/SKILL.md)
`gh skills install github/awesome-copilot reviewing-oracle-to-postgres-migration` | Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting, timestamps, concurrent transactions, etc.). Use when planning a database migration, reviewing migration artifacts, or validating that integration tests cover Oracle/PostgreSQL differences. | `references/REFERENCE.md`
`references/empty-strings-handling.md`
`references/no-data-found-exceptions.md`
`references/oracle-parentheses-from-clause.md`
`references/oracle-to-postgres-sorting.md`
`references/oracle-to-postgres-timestamp-timezone.md`
`references/oracle-to-postgres-to-char-numeric.md`
`references/oracle-to-postgres-type-coercion.md`
`references/postgres-concurrent-transactions.md`
`references/postgres-refcursor-handling.md` | +| [reviewing-oracle-to-postgres-migration](../skills/reviewing-oracle-to-postgres-migration/SKILL.md)
`gh skills install github/awesome-copilot reviewing-oracle-to-postgres-migration` | Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting/collations, UNION ALL planner risks, materialized-view refresh requirements, timestamps, concurrent transactions, etc.). Use when planning a database migration, reviewing migration artifacts, or validating that integration tests cover Oracle/PostgreSQL differences. | `references/REFERENCE.md`
`references/empty-strings-handling.md`
`references/no-data-found-exceptions.md`
`references/oracle-parentheses-from-clause.md`
`references/oracle-to-postgres-sorting.md`
`references/oracle-to-postgres-timestamp-timezone.md`
`references/oracle-to-postgres-to-char-numeric.md`
`references/oracle-to-postgres-type-coercion.md`
`references/postgres-concurrent-transactions.md`
`references/postgres-materialized-view-refresh.md`
`references/postgres-refcursor-handling.md`
`references/postgres-union-all-planner.md` | | [rhino3d-scripts](../skills/rhino3d-scripts/SKILL.md)
`gh skills install github/awesome-copilot rhino3d-scripts` | Authoring and debugging scripts for Rhinoceros 3D (Rhino 8 and later). Use when asked to write RhinoScript (VBScript / .rvb / .vbs), RhinoPython, or RhinoCommon-based scripts; automate Rhino modeling tasks; build command macros; manipulate Rhino geometry, layers, blocks, or document objects; pick objects from the viewport; control redraw and undo; or load and run scripts from the Rhino Script Editor. Covers `rhinoscriptsyntax`, `scriptcontext`, the `Rhino.*` RhinoCommon namespaces (`Rhino.Geometry`, `Rhino.DocObjects`, `Rhino.Input`, `Rhino.UI`, `Rhino.Display`, `Rhino.FileIO`), and the Rhino 8 unified Script Editor. | `references/macros-and-loading.md`
`references/rhinocommon-map.md`
`references/rhinoscriptsyntax-cheatsheet.md`
`references/vbscript-quirks.md` | | [roundup](../skills/roundup/SKILL.md)
`gh skills install github/awesome-copilot roundup` | Generate personalized status briefings on demand. Pulls from your configured data sources (GitHub, email, Teams, Slack, and more), synthesizes across them, and drafts updates in your own communication style for any audience you define. | None | | [roundup-setup](../skills/roundup-setup/SKILL.md)
`gh skills install github/awesome-copilot roundup-setup` | Interactive onboarding that learns your communication style, audiences, and data sources to configure personalized status briefings. Paste in examples of updates you already write, answer a few questions, and roundup calibrates itself to your workflow. | `references/config-template.md` | diff --git a/plugins/oracle-to-postgres-migration-expert/README.md b/plugins/oracle-to-postgres-migration-expert/README.md index ffe832f2..7e1f9bb7 100644 --- a/plugins/oracle-to-postgres-migration-expert/README.md +++ b/plugins/oracle-to-postgres-migration-expert/README.md @@ -21,9 +21,9 @@ copilot plugin install oracle-to-postgres-migration-expert@awesome-copilot | Skill | Description | |-------|-------------| -| `reviewing-oracle-to-postgres-migration` | Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting, timestamps, concurrent transactions, etc.). | +| `reviewing-oracle-to-postgres-migration` | Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting/collations, UNION ALL planning risks, materialized-view refresh behavior, timestamps, concurrent transactions, etc.). | | `creating-oracle-to-postgres-master-migration-plan` | Discovers all projects in a .NET solution, classifies each for Oracle-to-PostgreSQL migration eligibility, and produces a persistent master migration plan. | -| `migrating-oracle-to-postgres-stored-procedures` | Migrates Oracle PL/SQL stored procedures to PostgreSQL PL/pgSQL. Translates Oracle-specific syntax, preserves method signatures and type-anchored parameters, and applies `COLLATE "C"` for Oracle-compatible text sorting. | +| `migrating-oracle-to-postgres-stored-procedures` | Migrates Oracle PL/SQL stored procedures to PostgreSQL PL/pgSQL. Translates Oracle-specific syntax, preserves method signatures and type-anchored parameters, and applies explicit collation rules (`"C"` only when appropriate, locale-specific collations when required). | | `planning-oracle-to-postgres-migration-integration-testing` | Creates an integration testing plan for .NET data access artifacts, identifying repositories, DAOs, and service layers that need validation coverage. | | `scaffolding-oracle-to-postgres-migration-test-project` | Scaffolds an xUnit integration test project with a transaction-rollback base class and seed data manager for Oracle-to-PostgreSQL migration validation. | | `creating-oracle-to-postgres-migration-integration-tests` | Generates DB-agnostic xUnit integration tests with deterministic seed data that validate behavior consistency across both database systems. | @@ -35,7 +35,7 @@ copilot plugin install oracle-to-postgres-migration-expert@awesome-copilot The expert agent educates users throughout the migration journey: -- **Migration Concepts**: Explains Oracle→PostgreSQL differences (empty strings vs NULL, NO_DATA_FOUND exceptions, sort order, TO_CHAR conversions, type coercion strictness, REF CURSOR handling, concurrent transactions, timestamp/timezone behavior) +- **Migration Concepts**: Explains Oracle→PostgreSQL differences (empty strings vs NULL, NO_DATA_FOUND exceptions, sort/collation behavior, TO_CHAR conversions, type coercion strictness, REF CURSOR handling, UNION ALL planning caveats, materialized-view refresh needs, concurrent transactions, timestamp/timezone behavior) - **Pitfall Reference**: Surfaces insights from migration knowledge so users understand why changes are needed - **Best Practices**: Advises on minimizing changes, preserving logic, and ensuring schema immutability - **Workflow Guidance**: Presents a four-phase migration workflow as a guide users can follow at their own pace @@ -52,6 +52,8 @@ The expert suggests actionable next steps and only proceeds with user confirmati No autonomous chaining — the user controls the pace and sequence. +For database-changing actions, the expert provides scripts and explicit run instructions; the user applies DB changes. + ## Migration Workflow The expert guides users through a four-phase workflow: diff --git a/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md b/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md index b4018380..b78eada4 100644 --- a/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md +++ b/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md @@ -36,17 +36,22 @@ Scope to the target project only. List data access methods that interact with th - Follow seed file location and naming conventions from the existing project. - Reuse existing seed files when possible. - Avoid `TRUNCATE TABLE` — keep existing database data intact. +- Assume existing business rows and lookup rows are already present; add only minimal, collision-safe seed records needed for the scenario. - Do not commit seed data; tests run in transactions that roll back. - Ensure seed data does not conflict with other tests. - Load and verify seed data before assertions depend on it. +- Create or reuse a test `LookupConstants` class for stable lookup IDs/codes used across seed builders and assertions. **Step 4: Write test cases** - Inherit from the base test class to get automatic transaction create/rollback. +- Ensure each database-touching method in scope has at least one integration test (or multiple tests for higher-risk behavior branches). - Assert logical outputs (rows, columns, counts, error types), not platform-specific messages. - Assert specific expected values — never assert that a value is merely non-null or non-empty when a concrete value is available from seed data. - Avoid testing code paths that do not exist or asserting behavior that cannot occur. - Avoid redundant assertions across tests targeting the same method. +- For text parameters, include both empty-string and `NULL`/missing input coverage where applicable. +- For datetime behavior, include explicit timezone-sensitive assertions when methods write/read `timestamp without time zone` or `timestamp(0)` targets. **Step 5: Review determinism** @@ -58,3 +63,4 @@ Re-examine every assertion against non-null values. Confirm each is deterministi - **DB-agnostic assertions** — no platform-specific error messages or syntax in assertions. - **Seed only against Oracle** — test project will be migrated to PostgreSQL later. - **Scoped to one project** — do not create tests for artifacts outside the target project. +- **Preserve existing data** — never rewrite or wipe pre-existing business or lookup rows. diff --git a/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md b/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md index f6363c31..41f1b8bb 100644 --- a/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md +++ b/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md @@ -1,6 +1,6 @@ --- name: migrating-oracle-to-postgres-stored-procedures -description: 'Migrates Oracle PL/SQL stored procedures to PostgreSQL PL/pgSQL. Translates Oracle-specific syntax, preserves method signatures and type-anchored parameters, leverages orafce where appropriate, and applies COLLATE "C" for Oracle-compatible text sorting. Use when converting Oracle stored procedures or functions to PostgreSQL equivalents during a database migration.' +description: 'Migrates Oracle PL/SQL stored procedures to PostgreSQL PL/pgSQL. Translates Oracle-specific syntax, preserves method signatures and type-anchored parameters, leverages orafce where appropriate, and applies explicit collation mapping (`COLLATE "C"` only when appropriate, locale collations when required). Use when converting Oracle stored procedures or functions to PostgreSQL equivalents during a database migration.' --- # Migrating Stored Procedures from Oracle to PostgreSQL @@ -32,7 +32,11 @@ Apply these translation rules: - Do not prefix object names with schema names unless already present in the Oracle source. - Leave exception handling and rollback logic unchanged. - Do not generate `COMMENT` or `GRANT` statements. -- Use `COLLATE "C"` when ordering by text fields for Oracle-compatible sorting. +- Apply collation intentionally when ordering text: + - Use `COLLATE "C"` only when Oracle-compatible binary ordering is required and no other sort order is specified. + - If Oracle used explicit linguistic sorting (for example `NLS_SORT = French`), map to an explicit PostgreSQL locale collation instead of `"C"`. + - Use `SELECT collname, collprovider, collcollate, collctype FROM pg_collation ORDER BY collname;` to discover collations in the target environment. +- Treat `UNION ALL` as a review checkpoint. Validate plan quality per branch and restructure if combined-branch planning causes regressions (for example, unexpected sequential scans on large tables). - Leverage the `orafce` extension when it improves clarity or fidelity. Consult the PostgreSQL table/view definitions at `.github/oracle-to-postgres-migration/DDL/Postgres/Tables and Views/` for target schema details. diff --git a/skills/planning-oracle-to-postgres-migration-integration-testing/SKILL.md b/skills/planning-oracle-to-postgres-migration-integration-testing/SKILL.md index 448b9555..8d99d951 100644 --- a/skills/planning-oracle-to-postgres-migration-integration-testing/SKILL.md +++ b/skills/planning-oracle-to-postgres-migration-integration-testing/SKILL.md @@ -31,6 +31,12 @@ Write a markdown plan covering: - Recommended test cases per artifact - Seed data requirements - Known Oracle→PostgreSQL behavioral differences to validate +- Coverage mapping that ensures every database touchpoint has at least one test case (or a justified set of cases for high-risk methods) + +When defining recommended test cases, explicitly include: +- Text parameter behavior for both empty string and `NULL`/missing values. +- Datetime/timezone assertions, including round-trip and comparison behavior. +- Cases where destination columns use `timestamp without time zone` or `timestamp(0)`, with explicit timezone-application expectations. ## Output diff --git a/skills/reviewing-oracle-to-postgres-migration/SKILL.md b/skills/reviewing-oracle-to-postgres-migration/SKILL.md index 7f8dee87..f1864d14 100644 --- a/skills/reviewing-oracle-to-postgres-migration/SKILL.md +++ b/skills/reviewing-oracle-to-postgres-migration/SKILL.md @@ -1,6 +1,6 @@ --- name: reviewing-oracle-to-postgres-migration -description: 'Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting, timestamps, concurrent transactions, etc.). Use when planning a database migration, reviewing migration artifacts, or validating that integration tests cover Oracle/PostgreSQL differences.' +description: 'Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting/collations, UNION ALL planner risks, materialized-view refresh requirements, timestamps, concurrent transactions, etc.). Use when planning a database migration, reviewing migration artifacts, or validating that integration tests cover Oracle/PostgreSQL differences.' --- # Oracle-to-PostgreSQL Database Migration @@ -60,7 +60,7 @@ For each reference in [references/REFERENCE.md](references/REFERENCE.md), confir **Step 3: Verify integration test coverage** -Confirm tests exercise both the happy path and the failure scenarios highlighted in applicable insights (exceptions, sorting, refcursor consumption, concurrent transactions, timestamps, etc.). +Confirm tests exercise both the happy path and the failure scenarios highlighted in applicable insights (exceptions, sorting, `UNION ALL` behavior/performance risks, refcursor consumption, concurrent transactions, timestamps, materialized-view freshness, etc.). **Step 4: Gate the result** diff --git a/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md b/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md index 5dc9bace..830f7221 100644 --- a/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md +++ b/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md @@ -8,6 +8,8 @@ | [oracle-to-postgres-sorting.md](oracle-to-postgres-sorting.md) | How to preserve Oracle-like ordering in PostgreSQL using COLLATE "C" and DISTINCT wrapper patterns. | | [oracle-to-postgres-to-char-numeric.md](oracle-to-postgres-to-char-numeric.md) | Oracle allows TO_CHAR(numeric) without format; PostgreSQL requires format string—use CAST(numeric AS TEXT) instead. | | [oracle-to-postgres-type-coercion.md](oracle-to-postgres-type-coercion.md) | PostgreSQL strict type checks vs. Oracle implicit coercion—fix comparison errors by quoting or casting literals. | +| [postgres-union-all-planner.md](postgres-union-all-planner.md) | UNION ALL branches can produce poor plans when predicate pushdown is limited—review plans and split or reshape queries when needed. | +| [postgres-materialized-view-refresh.md](postgres-materialized-view-refresh.md) | Materialized views are not auto-refreshed after base-table changes—application or jobs must explicitly refresh them. | | [postgres-concurrent-transactions.md](postgres-concurrent-transactions.md) | PostgreSQL allows only one active command per connection—materialize results or use separate connections to avoid concurrent operation errors. | | [postgres-refcursor-handling.md](postgres-refcursor-handling.md) | Differences in refcursor handling; PostgreSQL requires fetching by cursor name—C# patterns to unwrap and read results. | | [oracle-to-postgres-timestamp-timezone.md](oracle-to-postgres-timestamp-timezone.md) | CURRENT_TIMESTAMP / NOW() return UTC-normalised timestamptz in PostgreSQL; Npgsql surfaces DateTime.Kind=Unspecified—force UTC at connection open and in application code. | diff --git a/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-sorting.md b/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-sorting.md index d1622bc5..97add53a 100644 --- a/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-sorting.md +++ b/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-sorting.md @@ -3,13 +3,14 @@ Purpose: Preserve Oracle-like sorting semantics when moving queries to PostgreSQL. ## Key points -- Oracle often treats plain `ORDER BY` as binary/byte-wise, giving case-insensitive ordering for ASCII. -- PostgreSQL defaults differ; to match Oracle behavior, use `COLLATE "C"` on sort expressions. +- Oracle and PostgreSQL default collations can differ significantly. +- Use `COLLATE "C"` only when you explicitly need Oracle-like binary ordering and no different sort rule is requested. +- If Oracle uses explicit linguistic ordering (for example `NLS_SORT = French`), map to an explicit PostgreSQL locale collation instead of forcing `"C"`. ## 1) Standard `SELECT … ORDER BY` **Goal:** Keep Oracle-style ordering. -**Pattern:** +**Pattern (only when Oracle-compatible binary ordering is required):** ```sql SELECT col1 FROM your_table @@ -17,9 +18,27 @@ ORDER BY col1 COLLATE "C"; ``` **Notes:** -- Apply `COLLATE "C"` to each sort expression that must mimic Oracle. +- Apply `COLLATE "C"` only to sort expressions that must mimic Oracle binary ordering. - Works with ascending/descending and multi-column sorts, e.g. `ORDER BY col1 COLLATE "C", col2 COLLATE "C" DESC`. +## 1b) Locale-aware ordering (when Oracle used NLS_SORT) + +If Oracle used locale-specific sorting such as: +```sql +ORDER BY nlssort(Externalusers.UserID, 'NLS_SORT = French') +``` +map to an explicit PostgreSQL collation, for example: +```sql +ORDER BY Externalusers.UserID COLLATE "ca_FR.utf-8" +``` + +Use a collation that exists in the target environment. Discover available collations with: +```sql +SELECT collname, collprovider, collcollate, collctype +FROM pg_collation +ORDER BY collname; +``` + ## 2) `SELECT DISTINCT … ORDER BY` **Issue:** PostgreSQL enforces that `ORDER BY` expressions appear in the `SELECT` list for `DISTINCT`, raising: `Npgsql.PostgresException: 42P10: for SELECT DISTINCT, ORDER BY expressions must appear in select list` @@ -38,14 +57,14 @@ ORDER BY col2 COLLATE "C"; **Why:** - The inner query performs the `DISTINCT` projection. -- The outer query safely orders the result set and adds `COLLATE "C"` to align with Oracle sorting. +- The outer query safely orders the result set and adds an explicit collation where needed to align with Oracle sorting. **Tips:** - Ensure any columns used in the outer `ORDER BY` are included in the inner projection. - For multi-column sorts, collate each relevant expression: `ORDER BY col2 COLLATE "C", col3 COLLATE "C" DESC`. ## Validation checklist -- [ ] Added `COLLATE "C"` to every `ORDER BY` that should follow Oracle sorting rules. +- [ ] Applied explicit collation only where required (`"C"` for Oracle-style binary ordering, locale collation for linguistic ordering). - [ ] For `DISTINCT` queries, wrapped the projection and sorted in the outer query. - [ ] Confirmed ordered columns are present in the inner projection. - [ ] Re-ran tests or representative queries to verify ordering matches Oracle outputs. diff --git a/skills/reviewing-oracle-to-postgres-migration/references/postgres-materialized-view-refresh.md b/skills/reviewing-oracle-to-postgres-migration/references/postgres-materialized-view-refresh.md new file mode 100644 index 00000000..1e72b19a --- /dev/null +++ b/skills/reviewing-oracle-to-postgres-migration/references/postgres-materialized-view-refresh.md @@ -0,0 +1,35 @@ +# PostgreSQL Materialized View Refresh Guide + +Purpose: Ensure migrated applications keep materialized views current after base-table changes. + +## Problem + +PostgreSQL materialized views are static snapshots. Updates to source tables do **not** automatically refresh dependent materialized views. + +## Migration risk + +- Oracle-era assumptions that derived data updates immediately may no longer hold. +- Read paths can return stale rows unless refresh timing is explicitly managed. +- Integration tests may pass once and then fail intermittently if refresh sequencing is not deterministic. + +## Required review item + +For every migrated path that writes to tables feeding a materialized view, verify the application workflow includes an explicit refresh strategy. + +## Refresh patterns + +- Immediate refresh in the write workflow when freshness is required: + ```sql + REFRESH MATERIALIZED VIEW my_view; + ``` +- Concurrent refresh (when supported and indexed) to reduce read blocking: + ```sql + REFRESH MATERIALIZED VIEW CONCURRENTLY my_view; + ``` +- Scheduled/batch refresh when stale windows are acceptable. + +## Integration-test expectations + +- [ ] Tests that modify source tables assert materialized-view contents only after the intended refresh action. +- [ ] Tests assert stale behavior before refresh when applicable. +- [ ] Tests document whether freshness is immediate or eventual for each affected feature. diff --git a/skills/reviewing-oracle-to-postgres-migration/references/postgres-union-all-planner.md b/skills/reviewing-oracle-to-postgres-migration/references/postgres-union-all-planner.md new file mode 100644 index 00000000..09404ff1 --- /dev/null +++ b/skills/reviewing-oracle-to-postgres-migration/references/postgres-union-all-planner.md @@ -0,0 +1,31 @@ +# PostgreSQL UNION ALL Planner Risk Guide + +Purpose: Avoid regressions where migrated `UNION ALL` queries run much slower in PostgreSQL than expected. + +## Problem + +`UNION ALL` keeps duplicate rows and combines branch outputs directly, but PostgreSQL does not always optimize each branch as aggressively as isolated queries. In large datasets this can produce poor plans (for example full scans where index-based plans are expected). + +## Why it happens + +- Predicate pushdown through `UNION ALL` branches can be limited depending on query shape. +- Cardinality estimates across branches can be skewed. +- Branch-local indexes may not be chosen when the optimizer evaluates the combined query. + +## Review checklist + +- [ ] Compare `EXPLAIN (ANALYZE, BUFFERS)` plans for the combined `UNION ALL` query and branch-isolated variants. +- [ ] Confirm branch predicates are explicit and not hidden inside non-sargable expressions. +- [ ] Check for unexpected sequential scans on large tables in either branch. +- [ ] Verify indexes exist for each branch's filter and join predicates. + +## Mitigation patterns + +1. Test each branch independently to verify expected index usage. +2. Push filters down into each branch instead of only filtering in the outer query. +3. If plan quality remains poor, split the query into two separately executed statements and combine results in application code. +4. Consider materializing branch results in temporary/intermediate structures only when measurement confirms benefit. + +## Validation note + +Treat `UNION ALL` performance behavior as a migration review item even when functional test results match Oracle. From 67ab0108a996689f45802d293d697b561d2b3fcf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:07:42 +1000 Subject: [PATCH 02/25] =?UTF-8?q?[bot]=20Update=20Learning=20Hub=20for=20C?= =?UTF-8?q?opilot=20CLI=20v1.0.69=E2=80=93v1.0.71=20features=20(#2287)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: update Learning Hub for Copilot CLI v1.0.69–v1.0.71 features - automating-with-hooks: document preToolUse exit code 2 for silent deny (v1.0.69) - creating-effective-skills: mention Forge automatic draft skill creation (v1.0.70) - installing-and-using-plugins: add /plugins dashboard documentation (v1.0.69) - copilot-configuration-basics: add /delegate --base flag (v1.0.69), --repo/--local flags for /settings and /model (v1.0.70), /settings Repo scope tabs (v1.0.71) - understanding-mcp-servers: add paginated session.mcp.resources RPCs (v1.0.70) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update website/src/content/docs/learning-hub/installing-and-using-plugins.md --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Aaron Powell --- .../learning-hub/automating-with-hooks.md | 4 +++- .../copilot-configuration-basics.md | 23 ++++++++++++++++++- .../learning-hub/creating-effective-skills.md | 4 ++-- .../installing-and-using-plugins.md | 2 +- .../learning-hub/understanding-mcp-servers.md | 14 ++++++++++- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/website/src/content/docs/learning-hub/automating-with-hooks.md b/website/src/content/docs/learning-hub/automating-with-hooks.md index 866c0515..56ab02fa 100644 --- a/website/src/content/docs/learning-hub/automating-with-hooks.md +++ b/website/src/content/docs/learning-hub/automating-with-hooks.md @@ -3,7 +3,7 @@ title: 'Automating with Hooks' description: 'Learn how to use hooks to automate lifecycle events like formatting, linting, and governance checks during Copilot agent sessions.' authors: - GitHub Copilot Learning Hub Team -lastUpdated: 2026-06-25 +lastUpdated: 2026-07-13 estimatedReadingTime: '8 minutes' tags: - hooks @@ -392,6 +392,8 @@ Block dangerous commands before they execute. Use the `matcher` field to target The `preToolUse` hook receives JSON input with details about the tool being called. Your script can inspect this input and exit with a non-zero code to **deny** the tool execution, or exit with zero to **approve** it. +> **Exit code 2 — silent deny (v1.0.69+)**: A `preToolUse` hook that exits with code `2` **denies the tool call silently** — the agent receives a denial without any error message being surfaced to the user. This is useful when you want to block a tool call as a policy decision without triggering a noisy failure (for example, blocking network access in CI without alarming users). Exit with any other non-zero code (e.g., `1`) to deny and show an error message. + ### Modifying Tool Arguments with preToolUse Beyond approve/deny, `preToolUse` hooks can also **modify tool arguments** before they are passed to the tool, and inject **additional context** into the agent's reasoning. To do this, write JSON to stdout from your hook script: diff --git a/website/src/content/docs/learning-hub/copilot-configuration-basics.md b/website/src/content/docs/learning-hub/copilot-configuration-basics.md index 029501f2..6dac387b 100644 --- a/website/src/content/docs/learning-hub/copilot-configuration-basics.md +++ b/website/src/content/docs/learning-hub/copilot-configuration-basics.md @@ -3,7 +3,7 @@ title: 'Copilot Configuration Basics' description: 'Learn how to configure GitHub Copilot at user, workspace, and repository levels to optimize your AI-assisted development experience.' authors: - GitHub Copilot Learning Hub Team -lastUpdated: 2026-07-09 +lastUpdated: 2026-07-13 estimatedReadingTime: '10 minutes' tags: - configuration @@ -459,6 +459,17 @@ The `/settings` command (v1.0.61+) opens an interactive dialog to browse and edi The settings dialog supports search — type to filter settings by name. Changes take effect immediately. +*(v1.0.70+)* The `/settings` command and the `/model` command both support **`--repo` and `--local` flags** for explicitly scoping which layer of settings you want to view or edit: + +``` +/settings --repo # view/edit repository-scoped settings +/settings --local # view/edit local (user-level) settings +/model --repo # view/edit the model pinned for this repository +/model --local # view/edit your personal model preference +``` + +These flags mirror the **Repo** and **Repo (local)** scope tabs available in the `/settings` dashboard (v1.0.71+), making it easier to manage per-repository vs. user-global configuration without ambiguity. In v1.0.71+, the `/settings` dashboard also shows **Repo** and **Repo (local)** tabs alongside the existing user-level view, giving you a unified place to see which settings are applied at each layer. + GitHub Copilot CLI has two commands for managing session state, with distinct behaviours: | Command | Behaviour | @@ -570,6 +581,16 @@ The `/pr auto` command *(v1.0.66+)* starts a self-paced automation loop that dri `/pr auto` is ideal when you have a PR with failing tests or linting errors — let it work through failures one at a time while you focus on other things. `/pr automerge` extends this further: it continues until all CI checks pass, required reviews are approved, and the PR is successfully merged. Both commands can be monitored and stopped from `/loop` or `/every`, which register the running automation as a scheduleable loop task. +The `/delegate` command creates a **delegate PR** — a pull request that the coding agent works on autonomously. By default, the delegate PR targets your current branch. Use `--base` *(v1.0.69+)* to specify a different target base branch: + +``` +/delegate # create a delegate PR targeting the current branch +/delegate --base main # create a delegate PR targeting main +/delegate --base release/2.0 # target a specific release branch +``` + +This is useful when you want to hand off a task to the coding agent on a specific branch — for example, backporting a fix to an older release branch or targeting a long-lived feature branch for automated work. + The `/share html` command exports the current session — including conversation history and any research reports — as a **self-contained interactive HTML file**: ``` diff --git a/website/src/content/docs/learning-hub/creating-effective-skills.md b/website/src/content/docs/learning-hub/creating-effective-skills.md index 379ab599..d9ba88a4 100644 --- a/website/src/content/docs/learning-hub/creating-effective-skills.md +++ b/website/src/content/docs/learning-hub/creating-effective-skills.md @@ -3,7 +3,7 @@ title: 'Creating Effective Skills' description: 'Master the art of writing reusable, shareable skill folders that deliver consistent results across your team.' authors: - GitHub Copilot Learning Hub Team -lastUpdated: 2026-06-30 +lastUpdated: 2026-07-13 estimatedReadingTime: '9 minutes' tags: - skills @@ -405,7 +405,7 @@ A: Yes, for clarity. Show examples of desired output format, patterns to follow, **Q: How do I review agent-proposed skill changes?** -A: In v1.0.66+, the agent can propose draft skill additions or improvements as it discovers reusable patterns during a session. Review each draft interactively with: +A: In v1.0.66+, the agent can propose draft skill additions or improvements as it discovers reusable patterns during a session. In v1.0.70+, **Forge** actively identifies clear workflow patterns during your session and creates draft skills automatically — you don't need to ask. Review each draft interactively with: ``` /chronicle skills review diff --git a/website/src/content/docs/learning-hub/installing-and-using-plugins.md b/website/src/content/docs/learning-hub/installing-and-using-plugins.md index fe8a1d6c..4733a4ba 100644 --- a/website/src/content/docs/learning-hub/installing-and-using-plugins.md +++ b/website/src/content/docs/learning-hub/installing-and-using-plugins.md @@ -3,7 +3,7 @@ title: 'Installing and Using Plugins' description: 'Learn how to find, install, and manage plugins that extend GitHub Copilot CLI with reusable agents, skills, hooks, and integrations.' authors: - GitHub Copilot Learning Hub Team -lastUpdated: 2026-07-09 +lastUpdated: 2026-07-13 estimatedReadingTime: '8 minutes' tags: - plugins diff --git a/website/src/content/docs/learning-hub/understanding-mcp-servers.md b/website/src/content/docs/learning-hub/understanding-mcp-servers.md index 77cd140c..3e02a142 100644 --- a/website/src/content/docs/learning-hub/understanding-mcp-servers.md +++ b/website/src/content/docs/learning-hub/understanding-mcp-servers.md @@ -3,7 +3,7 @@ title: 'Understanding MCP Servers' description: 'Learn how Model Context Protocol servers extend GitHub Copilot with access to external tools, databases, and APIs.' authors: - GitHub Copilot Learning Hub Team -lastUpdated: 2026-07-06 +lastUpdated: 2026-07-13 estimatedReadingTime: '8 minutes' tags: - mcp @@ -147,6 +147,18 @@ The available RPCs are: These are especially useful for plugins and installer scripts that need to self-register or de-register their MCP server as part of install/uninstall flows, without requiring the user to manually edit config files. +### Reading MCP Server Resources via Session RPCs + +*(v1.0.70+)* In addition to config management, GitHub Copilot CLI exposes **paginated session RPCs** for reading resources exposed by connected MCP servers. These let agents and tooling access server-provided resource lists and templates without needing direct MCP protocol access: + +| RPC | Description | +|-----|-------------| +| `session.mcp.resources.read` | Read a specific resource from a connected MCP server | +| `session.mcp.resources.list` | List resources available on a connected MCP server (paginated) | +| `session.mcp.resources.listTemplates` | List resource templates exposed by a connected MCP server (paginated) | + +Pagination support means these RPCs work reliably even when a server exposes a large number of resources. This is particularly useful for MCP servers that expose dynamic resource collections (such as database schemas or file trees) that need to be enumerated programmatically by agents or scripts. + ### Common MCP Server Configurations **PostgreSQL** — Query databases and inspect schemas: From fe4442e4cbfd383bbde7ff51f9a79ce7f868707e Mon Sep 17 00:00:00 2001 From: Akash Dwivedi <46550108+AkashAi7@users.noreply.github.com> Date: Tue, 14 Jul 2026 06:45:22 +0530 Subject: [PATCH 03/25] feat: add steno-mode skill for shorthand response compression and token saving (#2252) * feat: add steno-mode skill for shorthand response compression * fix: apply review suggestions and regenerate README against latest main --- docs/README.skills.md | 1 + skills/steno-mode/SKILL.md | 105 +++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 skills/steno-mode/SKILL.md diff --git a/docs/README.skills.md b/docs/README.skills.md index 5c0d9017..d0450008 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -362,6 +362,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [sql-optimization](../skills/sql-optimization/SKILL.md)
`gh skills install github/awesome-copilot sql-optimization` | Universal SQL performance optimization assistant for comprehensive query tuning, indexing strategies, and database performance analysis across all SQL databases (MySQL, PostgreSQL, SQL Server, Oracle). Provides execution plan analysis, pagination optimization, batch operations, and performance monitoring guidance. | None | | [sql-server-table-reconciliation](../skills/sql-server-table-reconciliation/SKILL.md)
`gh skills install github/awesome-copilot sql-server-table-reconciliation` | Use when: comparing SQL Server tables across instances, data migration validation, ETL verification, row mismatch detection, schema drift, reconciliation report, production vs staging comparison. Uses mssql-python driver with Apache Arrow for fast columnar data transfer and comparison. | `scripts/reconcile.py` | | [ssma-console](../skills/ssma-console/SKILL.md)
`gh skills install github/awesome-copilot ssma-console` | Use when: SSMA console operations — create project, generate assessment report, convert schema, migrate data, Oracle to SQL Server migration, schema conversion, data migration | None | +| [steno-mode](../skills/steno-mode/SKILL.md)
`gh skills install github/awesome-copilot steno-mode` | Shorthand-first response compression that cuts ~40% of response tokens while preserving technical precision and exact literals. Use when the user says "steno mode", "shorthand mode", "compressed responses", "token reduction", "brief structured output", or invokes /steno. Supports four compression levels: lite, brief, court, machine. Do not trigger for requests needing polished prose such as onboarding/tutorial content, stakeholder or customer-facing copy, or teaching-focused explanations. | None | | [structured-autonomy-generate](../skills/structured-autonomy-generate/SKILL.md)
`gh skills install github/awesome-copilot structured-autonomy-generate` | Structured Autonomy Implementation Generator Prompt | None | | [structured-autonomy-implement](../skills/structured-autonomy-implement/SKILL.md)
`gh skills install github/awesome-copilot structured-autonomy-implement` | Structured Autonomy Implementation Prompt | None | | [structured-autonomy-plan](../skills/structured-autonomy-plan/SKILL.md)
`gh skills install github/awesome-copilot structured-autonomy-plan` | Structured Autonomy Planning Prompt | None | diff --git a/skills/steno-mode/SKILL.md b/skills/steno-mode/SKILL.md new file mode 100644 index 00000000..a1c0ca8e --- /dev/null +++ b/skills/steno-mode/SKILL.md @@ -0,0 +1,105 @@ +--- +name: steno-mode +description: 'Shorthand-first response compression that cuts ~40% of response tokens while preserving technical precision and exact literals. Use when the user says "steno mode", "shorthand mode", "compressed responses", "token reduction", "brief structured output", or invokes /steno. Supports four compression levels: lite, brief, court, machine. Do not trigger for requests needing polished prose such as onboarding/tutorial content, stakeholder or customer-facing copy, or teaching-focused explanations.' +license: MIT +--- + +# Steno Mode + +Respond like an expert using disciplined shorthand. Dense, exact, readable. Do not imitate literal court-reporting notation. + +## Persistence + +ACTIVE EVERY RESPONSE after enabled. Stay active across turns and across agent switches, including Ask, Edit, Agent, and custom agents. Turn off only when the user says "stop steno" or "normal mode". + +Default level: **brief**. Switch with `/steno lite|brief|court|machine`. + +## Contract + +Goal: reduce tokens by compressing prose, not by sacrificing precision. + +Priority order: + +1. Exactness +2. Readability +3. Compression + +If compression harms exactness, keep the full form. + +## Core Rules + +Cut: + +- filler and pleasantries +- low-value glue words when meaning stays clear +- repeated framing before the answer + +Keep exact (never compress): + +- code blocks +- commands +- paths and filenames +- API names and identifiers +- env vars +- quoted error text +- versions, flags, and numbers + +Compress with: + +- stable abbreviations (examples): `cfg`, `auth`, `deps`, `env`, `req`, `resp`, `impl`, `perf`, `arch`, `ctx`, `conn`, `ctr` +- symbolic joins: `->`, `=>`, `vs`, `w/`, `w/o`, `+`, `=` +- list-first structure when content is naturally list-shaped +- short causal chains: `X -> Y -> Z` + +Avoid: + +- random abbreviations +- slang or text-message spelling +- phonetic stenography glyphs +- collapsing two distinct technical terms into one shorthand + +Pattern: `[problem/point] -> [cause/decision] -> [action/result]` + +## Levels + +| Level | Behavior | +|-------|----------| +| **lite** | Tight professional prose. Full sentences mostly intact. Minimal filler. | +| **brief** | Default. Shorthand + symbols + compact phrasing. High readability. | +| **court** | Dense expert shorthand. Fragments allowed. Strong symbol use. | +| **machine** | Max compression for expert users. Heavy abbreviation, minimal connectors. Use only when clarity still holds. | + +## Examples + +Example — "Why does this API retry loop never stop?" + +- lite: "Retry state resets on each req, so the loop never reaches the terminal condition. Persist the ctr outside the req scope." +- brief: "Retry state resets per req -> terminal condition never reached. Move ctr outside req scope." +- court: "State resets per req -> no terminal hit -> loop. Persist ctr outside req scope." +- machine: "Per-req reset -> no terminal -> loop. Persist ctr outside scope." + +Example — "Review this bug fix." + +- lite: "The fix handles null input, but it still mutates shared state. Clone before modifying." +- brief: "Null case fixed. Shared state still mutated. Clone before write." +- court: "Null fixed. Shared state mutates. Clone pre-write." +- machine: "Null OK. Shared mutates. Clone pre-write." + +Example — "Explain connection pooling." + +- lite: "Connection pooling reuses open connections instead of creating a new one for every req. That cuts handshake overhead." +- brief: "Pool reuses open conns vs new conn per req. Cuts handshake overhead." +- court: "Pool = reuse open conns. No per-req open/close. Less handshake cost." +- machine: "Pool reuse conns. Skip per-req handshake." + +## Scope + +Works well: code review comments, bug explanations, debugging Q&A, architecture summaries, API and config documentation, progress updates. + +Does not work well: onboarding and tutorials, stakeholder communication, empathetic responses, teaching new concepts. For these, switch to lite or ask whether compression should stay on. + +## Safety + +- When exact wording matters, quote verbatim. +- When ambiguity appears, expand once, then resume shorthand. +- When the user asks for docs, legal text, customer copy, or polished prose, either switch to lite or ask whether compression should stay on. From e353a8cfb8124d44905fc73214d873cea4a0ba3b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 01:16:56 +0000 Subject: [PATCH 04/25] =?UTF-8?q?[bot]=20sync:=20CLI=20for=20Beginners=20?= =?UTF-8?q?=E2=80=94=20ch04=20@-style=20imports=20+=20ch06=20/mcp=20list?= =?UTF-8?q?=20(2026-07-10)=20(#2264)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * sync: update cli-for-beginners ch04 and ch06 from upstream - Chapter 04: Add @-style imports section under Custom Instruction Files (released in v1.0.66, 2026-06-30). Users can now reference other files inside AGENTS.md or instruction files with @filepath syntax. - Chapter 06: Add /mcp list to the Additional MCP Commands reference table. Released in v1.0.69-1 (2026-07-04), /mcp list shows currently attached MCP servers and can be run while Copilot is working. Also add /mcp auth command and update enable/disable descriptions to note session persistence. - Bump lastUpdated to 2026-07-10 in both files. Upstream commits: c559ab4953a0 (2026-07-09) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: revert ch04 content changes, keep only date update Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com> * Apply suggestion from @aaronpowell --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com> Co-authored-by: Aaron Powell --- .../04-agents-and-custom-instructions.md | 2 +- .../docs/learning-hub/cli-for-beginners/06-mcp-servers.md | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/04-agents-and-custom-instructions.md b/website/src/content/docs/learning-hub/cli-for-beginners/04-agents-and-custom-instructions.md index 088b120c..9ec283d2 100644 --- a/website/src/content/docs/learning-hub/cli-for-beginners/04-agents-and-custom-instructions.md +++ b/website/src/content/docs/learning-hub/cli-for-beginners/04-agents-and-custom-instructions.md @@ -3,7 +3,7 @@ title: '04 · Create Specialized AI Assistants' description: 'Mirror the source chapter on custom agents and custom instructions for GitHub Copilot CLI.' authors: - GitHub Copilot Learning Hub Team -lastUpdated: 2026-06-19 +lastUpdated: 2026-07-10 --- ![Chapter 04: Agents and Custom Instructions](/images/learning-hub/copilot-cli-for-beginners/04/chapter-header.png) diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/06-mcp-servers.md b/website/src/content/docs/learning-hub/cli-for-beginners/06-mcp-servers.md index 8922332b..049c1d39 100644 --- a/website/src/content/docs/learning-hub/cli-for-beginners/06-mcp-servers.md +++ b/website/src/content/docs/learning-hub/cli-for-beginners/06-mcp-servers.md @@ -3,7 +3,7 @@ title: '06 · Connect to GitHub, Databases & APIs' description: 'Mirror the source chapter on MCP servers and external integrations for GitHub Copilot CLI.' authors: - GitHub Copilot Learning Hub Team -lastUpdated: 2026-06-19 +lastUpdated: 2026-07-10 --- ![Chapter 06: MCP Servers](/images/learning-hub/copilot-cli-for-beginners/06/chapter-header.png) @@ -901,11 +901,13 @@ Beyond `/mcp show`, there are several other commands for managing your MCP serve | Command | What It Does | |---------|--------------| | `/mcp show` | Show all configured MCP servers and their status | +| `/mcp list` | Show currently attached MCP servers and their status; can be run while Copilot is working | | `/mcp add` | Interactive setup for adding a new server | | `/mcp edit ` | Edit an existing server configuration | -| `/mcp enable ` | Enable a disabled server | -| `/mcp disable ` | Temporarily disable a server | +| `/mcp enable ` | Enable a disabled server (persists across sessions) | +| `/mcp disable ` | Disable a server (persists across sessions) | | `/mcp delete ` | Remove a server permanently | +| `/mcp auth ` | Re-authenticate with an MCP server that uses OAuth (e.g., after switching accounts) | For most of this course, `/mcp show` is all you need. The other commands become useful as you manage more servers over time. From 36b30eb1130591095fab9a26a83f248ae135f67e Mon Sep 17 00:00:00 2001 From: prasadgd9022 <116000691+prasadgd9022@users.noreply.github.com> Date: Wed, 15 Jul 2026 04:42:29 +0530 Subject: [PATCH 05/25] Add tm7-threat-model skill for valid TM7 file generation (#2280) * Add tm7-threat-model skill for valid TM7 file generation Adds a skill that generates valid Microsoft Threat Modeling Tool (.tm7) files using the correct WCF DataContractSerializer format, with a minimal reference file. Includes STRIDE threat generation workflow and a checklist of common serialization mistakes that corrupt .tm7 files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: sanitize reference model, fix dangling refs, move to assets - Move example-minimal.tm7 into assets/ per repo convention (aaronpowell). - Remove personal/corporate metadata from the reference model (Owner, Contributors, ChangedBy domain account, project names). - Make the reference model self-contained: add a second stencil so the data flow and threat SourceGuid/TargetGuid/FlowGuid all resolve to real elements. - Fix SKILL.md threat contract (KeyValueOfstringThreatpc_P0_PhOB with b:-prefixed KnowledgeBase fields) to match the bundled reference. - Reconcile guidance: MetaInformation/Notes/KnowledgeBase are valid schema elements and must be preserved; only SecurityGaps/Mitigations are invalid. - Regenerate docs/README.skills.md and normalize line endings to LF. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address 2nd review: correct KnowledgeBase placement, valid TypeIds, z:Id uniqueness - Document KnowledgeBase as a top-level sibling after ThreatMetaData (not embedded) - Update skeleton to show , sibling , and - Replace TypeIds absent from the bundled KB: AzureCosmosDB -> AzureSQLDB, HumanUser -> Mobile, GenericDataFlow -> Request - Require z:Id uniqueness across the file in the common-mistakes checklist Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: exclude *.tm7 exports from codespell MTM DataContract .tm7 exports embed base64 icon blobs whose substrings (oT, bu, wth, mKe, ...) trigger codespell false positives. Skip *.tm7, matching the existing convention for binary/asset files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: prasad Co-authored-by: Aaron Powell --- .codespellrc | 3 +- docs/README.skills.md | 1 + skills/tm7-threat-model/SKILL.md | 312 ++++++++++++++++++ .../assets/example-minimal.tm7 | 4 + 4 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 skills/tm7-threat-model/SKILL.md create mode 100644 skills/tm7-threat-model/assets/example-minimal.tm7 diff --git a/.codespellrc b/.codespellrc index c8e29a36..1a42b532 100644 --- a/.codespellrc +++ b/.codespellrc @@ -63,5 +63,6 @@ ignore-words-list = numer,wit,aks,edn,ser,ois,gir,rouge,categor,aline,ative,afterall,deques,dateA,dateB,TE,FillIn,alle,vai,LOD,InOut,pixelX,aNULL,Wee,Sherif,queston,Vertexes,nin,FO,CAF,Parth,ans,gud,Vally,vally # Skip certain files and directories +# *.tm7 - MTM DataContract exports; embedded base64 icon blobs trigger false positives -skip = .git,node_modules,package-lock.json,*.lock,website/build,website/.docusaurus,.all-contributorrc,./skills/geofeed-tuner/assets/*.json,./skills/geofeed-tuner/references/*.txt,./plugins/fastah-ip-geo-tools/skills/geofeed-tuner/assets/*.json,./plugins/fastah-ip-geo-tools/skills/geofeed-tuner/references/*.txt,./extensions/arcade-canvas/game/phaser.min.js +skip = .git,node_modules,package-lock.json,*.lock,website/build,website/.docusaurus,.all-contributorrc,./skills/geofeed-tuner/assets/*.json,./skills/geofeed-tuner/references/*.txt,./plugins/fastah-ip-geo-tools/skills/geofeed-tuner/assets/*.json,./plugins/fastah-ip-geo-tools/skills/geofeed-tuner/references/*.txt,./extensions/arcade-canvas/game/phaser.min.js,*.tm7 diff --git a/docs/README.skills.md b/docs/README.skills.md index d0450008..63ddc1e5 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -376,6 +376,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [threat-model-analyst](../skills/threat-model-analyst/SKILL.md)
`gh skills install github/awesome-copilot threat-model-analyst` | Full STRIDE-A threat model analysis and incremental update skill for repositories and systems. Supports two modes: (1) Single analysis — full STRIDE-A threat model of a repository, producing architecture overviews, DFD diagrams, STRIDE-A analysis, prioritized findings, and executive assessments. (2) Incremental analysis — takes a previous threat model report as baseline, compares the codebase at the latest (or a given commit), and produces an updated report with change tracking (new, resolved, still-present threats), STRIDE heatmap, findings diff, and an embedded HTML comparison. Only activate when the user explicitly requests a threat model analysis, incremental update, or invokes /threat-model-analyst directly. | `references/analysis-principles.md`
`references/diagram-conventions.md`
`references/incremental-orchestrator.md`
`references/orchestrator.md`
`references/output-formats.md`
`references/skeletons`
`references/tmt-element-taxonomy.md`
`references/verification-checklist.md` | | [tiny-stepping](../skills/tiny-stepping/SKILL.md)
`gh skills install github/awesome-copilot tiny-stepping` | Incremental development workflow that makes the smallest meaningful change per step and pauses for feedback, so the direction gets validated early before continuing. Use for careful, iterative implementation with continuous validation. | None | | [tldr-prompt](../skills/tldr-prompt/SKILL.md)
`gh skills install github/awesome-copilot tldr-prompt` | Create tldr summaries for GitHub Copilot files (prompts, agents, instructions, collections), MCP servers, or documentation from URLs and queries. | None | +| [tm7-threat-model](../skills/tm7-threat-model/SKILL.md)
`gh skills install github/awesome-copilot tm7-threat-model` | Creates valid Microsoft Threat Modeling Tool (.tm7) files compatible with the Microsoft Threat Modeling Tool v7.3+. Use this skill whenever asked to create, generate, or modify a .tm7 threat model file, or when performing STRIDE threat modeling that should output a .tm7 file that opens cleanly in the Microsoft Threat Modeling Tool. | `assets/example-minimal.tm7` | | [transloadit-media-processing](../skills/transloadit-media-processing/SKILL.md)
`gh skills install github/awesome-copilot transloadit-media-processing` | Process media files (video, audio, images, documents) using Transloadit. Use when asked to encode video to HLS/MP4, generate thumbnails, resize or watermark images, extract audio, concatenate clips, add subtitles, OCR documents, or run any media processing pipeline. Covers 86+ processing robots for file transformation at scale. | None | | [typescript-mcp-server-generator](../skills/typescript-mcp-server-generator/SKILL.md)
`gh skills install github/awesome-copilot typescript-mcp-server-generator` | Generate a complete MCP server project in TypeScript with tools, resources, and proper configuration | None | | [typespec-api-operations](../skills/typespec-api-operations/SKILL.md)
`gh skills install github/awesome-copilot typespec-api-operations` | Add GET, POST, PATCH, and DELETE operations to a TypeSpec API plugin with proper routing, parameters, and adaptive cards | None | diff --git a/skills/tm7-threat-model/SKILL.md b/skills/tm7-threat-model/SKILL.md new file mode 100644 index 00000000..9845d39f --- /dev/null +++ b/skills/tm7-threat-model/SKILL.md @@ -0,0 +1,312 @@ +--- +name: tm7-threat-model +description: 'Creates valid Microsoft Threat Modeling Tool (.tm7) files compatible with the Microsoft Threat Modeling Tool v7.3+. Use this skill whenever asked to create, generate, or modify a .tm7 threat model file, or when performing STRIDE threat modeling that should output a .tm7 file that opens cleanly in the Microsoft Threat Modeling Tool.' +--- + +# Microsoft Threat Modeling Tool (.tm7) Generator + +You generate **valid `.tm7` files** for the Microsoft Threat Modeling Tool (v7.3+). A `.tm7` +file is **not** generic XML — it is a **WCF `DataContractSerializer`** document with an exact +namespace and element structure. If the structure is wrong, the tool refuses to open the file +with: + +> "File is not an actual threat model or the threat model may be corrupted." + +Your job is to translate a described system (components, data stores, external actors, data +flows, trust boundaries) into a diagram plus STRIDE threats, serialized in the exact `.tm7` +format described below. + +## Workflow + +When asked to produce a `.tm7` file: + +1. **Model the system.** Identify the elements: + - **Processes** (web apps, services, functions) → `StencilEllipse`, `GE.P` + - **Data stores** (databases, caches, queues, blobs) → `StencilParallelLines`, `GE.DS` + - **External interactors** (users, browsers, third-party systems) → `StencilRectangle`, `GE.EI` + - **Trust boundaries** → `BorderBoundary`, `GE.TB` + - **Data flows** connecting the above → `Connector`, `GE.DF` +2. **Assign a unique lowercase UUID** (e.g. `148ade68-5c80-40f3-8e1f-4e2cabdb5991`) to every + stencil and every flow. Never use human-readable ids like `users-browser`. +3. **Lay out coordinates** (`Left`/`Top`/`Width`/`Height`) so stencils don't overlap. +4. **Generate STRIDE threats** per interaction and place them in ``. +5. **Serialize** using the structure in this guide, mirroring `assets/example-minimal.tm7`. +6. **Validate** against the "Common Mistakes" checklist before returning the file. +7. **Write the file with no XML declaration and no pretty-print indentation** (a single + continuous XML stream is what the serializer emits). + +Always open [`assets/example-minimal.tm7`](./assets/example-minimal.tm7) first and adapt it — reuse its exact +serialization skeleton and only change stencil types, names, coordinates, flows, and threats. + +## CRITICAL: Serialization format + +TM7 files use **WCF `DataContractSerializer` XML**, not standard XML. + +The file MUST start with this exact root element — **no `` declaration**: + +```xml + +``` + +**NEVER use:** +- `` — causes deserialization failure. +- `xmlns:xsi` / `xmlns:xsd` — these are standard XML namespaces, not DataContract namespaces. +- Invented elements such as `` or `` — they do not exist in the + TM7 schema. + +> **Note:** `` (with children like ``, ``, +> ``, ``, ``, ``, +> ``), ``, and `` **are** part of the real schema and +> are emitted by the tool — keep them (see the structure below and `assets/example-minimal.tm7`). +> Just don't invent elements that the tool never produces. + +## Required namespace prefixes + +| Prefix | URI | Used for | +|--------|-----|----------| +| (default) | `http://schemas.datacontract.org/2004/07/ThreatModeling.Model` | Root `ThreatModel` | +| `xmlns:i` | `http://www.w3.org/2001/XMLSchema-instance` | Type attributes | +| `xmlns:z` | `http://schemas.microsoft.com/2003/10/Serialization/` | Reference ids (`z:Id`) | +| `xmlns:a` | `http://schemas.microsoft.com/2003/10/Serialization/Arrays` | Arrays / collections | +| `xmlns:b` | `http://schemas.datacontract.org/2004/07/ThreatModeling.KnowledgeBase` | Stencil properties | +| `xmlns:c` | `http://www.w3.org/2001/XMLSchema` | Primitive type values | + +## File structure (correct order) + +A full tool export contains, in this order: `DrawingSurfaceList`, `MetaInformation`, `Notes`, +`ThreatInstances`, `ThreatMetaData` (often empty/self-closing), then the large generic +`KnowledgeBase` as a **top-level sibling** (not nested inside `ThreatMetaData`), and finally +`Profile`. + +```xml + + + + DRAWINGSURFACE + {guid} + ... + DRAWINGSURFACE + + + + + + + + + + + + + + + + + + + + + + + + +``` + +> The `` (the generic SDL stencil/threat catalog) is large but **required** — +> the tool uses it to resolve every stencil `TypeId`. It is a **top-level sibling** placed after +> `ThreatMetaData` and before `Profile`, **not** nested inside `ThreatMetaData`. Reuse it verbatim +> from `assets/example-minimal.tm7`; only add stencils whose `TypeId` already appears in that +> KnowledgeBase. + +## Stencil elements + +Each stencil in `` is wrapped in ``: + +```xml + + {guid} + + GE.P + {guid} + + + Web Application + + + + + Name + + My Component + + + + SE.P.TMCore.WebApp + 100 + 400 + + 1 + 200 + 100 + + +``` + +### Stencil shape types + +| Shape | `i:type` | `GenericTypeId` | Description | +|-------|----------|-----------------|-------------| +| Process (circle) | `StencilEllipse` | `GE.P` | Processes, web apps, services | +| Data store (parallel lines) | `StencilParallelLines` | `GE.DS` | Databases, storage, caches | +| External interactor (rectangle) | `StencilRectangle` | `GE.EI` | Users, external systems | +| Trust boundary | `BorderBoundary` | `GE.TB` | Trust boundaries | + +### Common `TypeId` values (SDL TM knowledge base) + +| `TypeId` | Component | +|----------|-----------| +| `SE.P.TMCore.WebApp` | Web Application | +| `SE.P.TMCore.AzureAppServiceWebApp` | Azure App Service Web App | +| `SE.P.TMCore.AzureEventHub` | Azure Event Hub | +| `SE.P.TMCore.DynamicsCRM` | Dynamics CRM | +| `SE.DS.TMCore.SQL` | SQL Database | +| `SE.DS.TMCore.AzureSQLDB` | Azure SQL Database | +| `SE.EI.TMCore.Browser` | Browser | +| `SE.EI.TMCore.Mobile` | Mobile Client | + +## Data flow lines + +Lines in `` also use ``, with `i:type="Connector"`: + +```xml + + {line-guid} + + GE.DF + {line-guid} + ... + SE.DF.TMCore.Request + 0 + 0 + {source-stencil-guid} + 0 + 0 + {target-stencil-guid} + 0 + 0 + + +``` + +## Property attribute types + +Properties use typed `` elements: + +| `i:type` | Purpose | Value | +|----------|---------|-------| +| `b:HeaderDisplayAttribute` | Section header | `i:nil="true"` | +| `b:StringDisplayAttribute` | Text value (Name, Reason) | `i:type="c:string"` | +| `b:BooleanDisplayAttribute` | Boolean (Out Of Scope) | `i:type="c:boolean"` | +| `b:ListDisplayAttribute` | Dropdown list | Has `` | + +## Threat instances + +Threats go in `` using `` (note the exact +`PhOB` suffix). Unlike stencils, the threat `` fields are **`b:`-prefixed** (the +`ThreatModeling.KnowledgeBase` namespace), and the `` is the literal concatenation +`TH + + + `: + +```xml + + + TH117{source-guid}{flow-guid}{target-guid} + + + {drawing-surface-guid} + {flow-guid} + 32 + {source-guid}:{flow-guid}:{target-guid} + + 2025-01-01T00:00:00 + High + + + Title + An adversary may spoof the user and gain access + + + UserThreatCategory + Spoofing + + + UserThreatShortDescription + Spoofing is when a process or entity is something other than its claimed identity. + + + PossibleMitigations + Enable multi-factor authentication and least-privilege access control. + + + Priority + High + + + SDLPhase + Design + + + {source-stencil-guid} + Mitigated + + {target-stencil-guid} + + TH117 + false + false + + + +``` + +**Every GUID must resolve:** `SourceGuid` and `TargetGuid` must equal `` values of real +stencils in ``, and `FlowGuid` must equal the `` of a real connector in +``. Dangling references produce a model that opens with missing diagram elements. + +Use the standard STRIDE categories for `UserThreatCategory`: **S**poofing, **T**ampering, +**R**epudiation, **I**nformation Disclosure, **D**enial of Service, **E**levation of Privilege. + +## Common mistakes that break TM7 files + +1. **Adding an `` declaration** — `DataContractSerializer` does not emit one. +2. **Using `xmlns:xsi` / `xmlns:xsd`** instead of DataContract namespaces. +3. **Using simple element names** like ``, ``, `` — you must use the + DataContract wrapper types such as ``. +4. **Inventing elements the tool never emits** like `` or `` — these + are not in the schema. (``, ``, and `` **are** valid + and must be preserved.) +5. **Using human-readable GUIDs** like `users-browser` instead of real UUIDs + (e.g. `148ade68-5c80-40f3-8e1f-4e2cabdb5991`). +6. **Dangling references** — a `Line`, threat `SourceGuid`/`TargetGuid`, or threat `FlowGuid` + that points to a stencil/flow GUID that isn't actually defined in ``/``. + Every reference must resolve to an included element. +7. **Missing or duplicated `z:Id` reference attributes** — every serialized object needs a + `z:Id`, and each `z:Id` (e.g. `i1`, `i2`, `i10`) must be **unique** across the whole file. + When you duplicate a template block to add an element, always renumber its `z:Id` (and any + nested ones) to values not used elsewhere; reusing an id creates duplicate DataContract + object ids and makes deserialization fail. +8. **Missing the `xmlns` on child elements** — each `GenericTypeId`, `Guid`, `Properties`, + `TypeId`, etc. must carry its own + `xmlns="http://schemas.datacontract.org/2004/07/ThreatModeling.Model.Abstracts"`. +9. **Pretty-printing with indentation** — the correct output is a single continuous XML stream + with no added newlines or indentation inside the content. + +## Reference asset + +Always use [`assets/example-minimal.tm7`](./assets/example-minimal.tm7) in this skill's +directory as the structural reference. It is a fully synthetic, sanitized export (no personal or +project data) that opens cleanly in the tool: two stencils connected by one data flow, with one +STRIDE threat whose every reference resolves. Adapt the stencil types, names, properties, +coordinates, data flows, and threats to the user's architecture, but **never** change the +serialization format or namespace structure, and only use stencil `TypeId` values that already +appear in its bundled `KnowledgeBase`. After generating, mentally diff your output's skeleton +against the example to confirm every namespace, wrapper element, and GUID reference matches. diff --git a/skills/tm7-threat-model/assets/example-minimal.tm7 b/skills/tm7-threat-model/assets/example-minimal.tm7 new file mode 100644 index 00000000..f2bb5ce1 --- /dev/null +++ b/skills/tm7-threat-model/assets/example-minimal.tm7 @@ -0,0 +1,4 @@ +DRAWINGSURFACE98552893-dac4-4f74-84e4-c9175171a8a2DiagramNameProject EquinoxDRAWINGSURFACE148ade68-5c80-40f3-8e1f-4e2cabdb5991GE.P148ade68-5c80-40f3-8e1f-4e2cabdb5991Dynamics CRMNameCRM ServiceOut Of Scope71f3d9aa-b8ef-4e54-8126-607a1d903103falseReason For Out Of Scope752473b6-52d4-4776-9a24-202153f7d579Configurable AttributesAs Generic ProcessSE.P.TMCore.DynamicsCRM10011281189100c560f147-a7e9-4a77-ad9c-911431dc9cbfGE.Pc560f147-a7e9-4a77-ad9c-911431dc9cbfDynamics CRMNameClientOut Of Scope71f3d9aa-b8ef-4e54-8126-607a1d903103falseReason For Out Of Scope752473b6-52d4-4776-9a24-202153f7d579Configurable AttributesAs Generic ProcessSE.P.TMCore.DynamicsCRM10040011891006de57c18-b9de-41a3-919b-f7100ac1f471GE.DF6de57c18-b9de-41a3-919b-f7100ac1f471RequestNameSend PayloadDataflow Order15ccd509-98eb-49ad-b9c2-b4a2926d17800Out Of Scope71f3d9aa-b8ef-4e54-8126-607a1d903103falseReason For Out Of Scope752473b6-52d4-4776-9a24-202153f7d579Configurable AttributesAs Generic Data FlowShow Boundary Threats23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59SelectYesNo0SE.DF.TMCore.Request549336EastWest148ade68-5c80-40f3-8e1f-4e2cabdb5991481328c560f147-a7e9-4a77-ad9c-911431dc9cbf6633351Example Web Application Threat ModelTH117c560f147-a7e9-4a77-ad9c-911431dc9cbf6de57c18-b9de-41a3-919b-f7100ac1f471148ade68-5c80-40f3-8e1f-4e2cabdb599198552893-dac4-4f74-84e4-c9175171a8a26de57c18-b9de-41a3-919b-f7100ac1f47132c560f147-a7e9-4a77-ad9c-911431dc9cbf:6de57c18-b9de-41a3-919b-f7100ac1f471:148ade68-5c80-40f3-8e1f-4e2cabdb59912025-04-30T15:30:27.9244142+05:30HighTitleAn adversary may spoof an Azure administrator and gain access to Azure subscription portalUserThreatCategorySpoofingUserThreatShortDescriptionSpoofing is when a process or entity is something other than its claimed identity. Examples include substituting a process, a file, website or a network addressUserThreatDescriptionAn adversary may spoof an Azure administrator and gain access to Azure subscription portal if the administrator's credentials are compromised.StateInformationEnabled multi factor authentication and access is provided using PIMInteractionStringValidate & Create Project/ServicePossibleMitigationsEnable fine-grained access management to Azure Subscription using RBAC. Refer: <a href="https://aka.ms/tmtauthz#grained-rbac">https://aka.ms/tmtauthz#grained-rbac</a> Enable Azure Multi-Factor Authentication for Azure Administrators. Refer: <a href="https://aka.ms/tmtauthn#multi-factor-azure-admin">https://aka.ms/tmtauthn#multi-factor-azure-admin</a>PriorityHighSDLPhaseDesignc560f147-a7e9-4a77-ad9c-911431dc9cbfMitigated148ade68-5c80-40f3-8e1f-4e2cabdb5991TH117falsefalsefalsefalseSelectYesNoShow Boundary ThreatsVirtualDynamic23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59ListA unidirectional representation of the flow of data between elementsfalseGE.DFBefore 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Generic Data FlowROOTLinefalseAnyAnyfalseA representation of a data storefalseGE.DSLower right of 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gA3tbmHb8dUAgCASQDc1OYevh1TCQAAJgFwU5t7+HZMJQAAmATATW3u4dsxlQAAYBIAN7W5h2/HVAIAgEkA3NTmHr4dUwkAACYBcFObe/h2TCUAAJgEwE1t7uHbMZUAAGASADe1uYdvx1QCAIBJANzU5h6+HVMJAAAmAXBTm3v4dkwlAACYBMBNbe7h2zGVAABgEgA3tbmHb8dUAgCASQDc1OYevh1TCQAAJgFwU5t7+HZMJQAAmATATW3u4dsxlQAAYBIAN7W5h2/HVAkBUBsAyPG3X3779nnev9lPEAAPqD90bQaAFALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQIAgDQC4AECAIA0AuABAgCANALgAQkBsO0C4Pfz85dfvn2e92/2EwTAAwQAAJMAuKnNPXw7phIAAEwC4KY29/DtmEoAADAJgJva3MO3YyoBAMAkAG5qcw/fjqkEAACTALipzT18O6YSAABMAuCmNvfw7ZhKAAAwCYCb2tzDt2MqAQDAJABuanMP346pBAAAkwC4qc09fDumEgAATALgpjb38O2YSgAAMAmAm9rcw7djKgEAwCQAbmpzD9+OqQQAAJMAuKnNPXw7phIAAEwC4KY29/DtmEoAADAJgJva3MO3YyoBAMAkAG5qcw/fjqkEAACTALipzT18O6YSAABMAuCmNvfw7ZhKAAAwCYCb2tzDt2MqAQDAJABuanMP346pBAAAkwC4qc09fDumEgAATALgpjb38O2YSgAAMAmAm9rcw7djKgEAwCQAbmpzD9+OqQQAAJMAuKnNPXw7phIAAEwC4KY29/DtmEoAADAJgJva3MO3YyoBAMAkAG5qcw/fjqkEAACTALipzT18O6YSAABMAuCmNvfw7ZhKAAAwCYCb2tzDt2MqAQDAJABuanMP346pBAAAkwC4qc09fDumEgAATALgpjb38O2YSgAAMAmAm9rcw7djKgEAwCQAbmpzD9+OqQQAAJMAuKnNPXw7phIAAEwC4KY29/DtmEoAADAJgJva3MO3YyoBAMAkAG5qcw/fjqkEAACTALipzT18O6YSAABMAuCmNvfw7ZhKAAAwCYCb2tzDt2MqAQDAJABuanMP346pBAAAkwC4qc09fDumEgAATALgpjb38O2YSgAAMAmAm9rcw7djKgEAwCQAbmpzD9+OqQQAAJMAuKnNPXw7phIAAEwC4KY29/DtmEoAADAJgJva3MO3YyoBAMAkAG5qcw/fjqkEAACTALipzT18O6YSAABMAuCmNvfw7ZhKAAAwCYCb2tzDt2MqAQDAJABuanMP346pBAAAkwC4qc09fDumEgAATALgpjb38O2YSgAAMAmAm9rcw7djKgEAwCQAbmpzD9+OqQQAAJMAuKnNPXw7phIAAEwC4KY29/DtmEoAADAJgJva3MO3YyoBAMAkAG5qcw/fjqkEAACTALipzT18O6YSAABMAuCmNvfw7ZhKAAAwCYCb2tzDt2MqAQDAJABuanMP346pBAAAkwC4qc09fDumEgAATALgpjb38O2YSgAAMAmAm9rcw7djKgEAwCQAbmpzD9+OqQQAAJMAuKnNPXw7phIAAEwC4KY29/DtmEoAADAJgJva3MO3YyoBAMAkAG5qcw/fjqkEAACTALipzT18O6YSAABMAuCmNvfw7ZhKAAAwCYCb2tzDt2MqAQDAJABuanMP346pBAAAkwC4qc09fDumEgAATALgpjb38O2YSgAAMAmAm9rcw7djKgEAwCQAbmpzD9+OqQQAAJMAuKnNPXw7pkoIgO++/+ErADn+56+/fvs879/sJwiAByQEAAD8IwHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8AABAEAaAfAAAQBAGgHwAAEAQBoB8IB//tc/f/3u+x8AIMa//Nt/rf+zUv0hAwAA+P8RAADwgQQAAHwgAQAAH0gAAMAHEgAA8IEEAAB8IAEAAB9IAADABxIAAPCBBAAAfCABAAAfSAAAwAcSAADwgQQAAHwgAQAAH0gAAMAHEgAA8IEEAAB8IAEAAB9IAADABxIAAPCBBAAAfCABAAAfSAAAwAcSAADwgQQAAHwgAQAAH0gAAMAHEgAA8IEEAAB8IAEAAB9IAADABxIAAPCBBAAAfCABAAAfSAAAwAcSAADwgQQAAHwgAQAAH0gAAMAHEgAA8IH+HgDfff/DVwDgM/w9AACAz7I+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgDvtj4CAO+2PgIA77Y+AgBv9vVP/wvm8MX4W+CLKgAAAABJRU5ErkJggg==Generic Data StoreROOTParallelLinesfalseAnyAnyfalseA representation of an external interactorfalseGE.EILower right of stenciliVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACHDwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAEjHnZZ3VFTXFofPvXd6oc0wAlKG3rvAANJ7k15FYZgZYCgDDjM0sSGiAhFFRJoiSFDEgNFQJFZEsRAUVLAHJAgoMRhFVCxvRtaLrqy89/Ly++Osb+2z97n77L3PWhcAkqcvl5cGSwGQyhPwgzyc6RGRUXTsAIABHmCAKQBMVka6X7B7CBDJy82FniFyAl8EAfB6WLwCcNPQM4BOB/+fpFnpfIHomAARm7M5GSwRF4g4JUuQLrbPipgalyxmGCVmvihBEcuJOWGRDT77LLKjmNmpPLaIxTmns1PZYu4V8bZMIUfEiK+ICzO5nCwR3xKxRoowlSviN+LYVA4zAwAUSWwXcFiJIjYRMYkfEuQi4uUA4EgJX3HcVyzgZAvEl3JJS8/hcxMSBXQdli7d1NqaQffkZKVwBALDACYrmcln013SUtOZvBwAFu/8WTLi2tJFRbY0tba0NDQzMv2qUP91829K3NtFehn4uWcQrf+L7a/80hoAYMyJarPziy2uCoDOLQDI3fti0zgAgKSobx3Xv7oPTTwviQJBuo2xcVZWlhGXwzISF/QP/U+Hv6GvvmckPu6P8tBdOfFMYYqALq4bKy0lTcinZ6QzWRy64Z+H+B8H/nUeBkGceA6fwxNFhImmjMtLELWbx+YKuGk8Opf3n5r4D8P+pMW5FonS+BFQY4yA1HUqQH7tBygKESDR+8Vd/6NvvvgwIH554SqTi3P/7zf9Z8Gl4iWDm/A5ziUohM4S8jMX98TPEqABAUgCKpAHykAd6ABDYAasgC1wBG7AG/iDEBAJVgMWSASpgA+yQB7YBApBMdgJ9oBqUAcaQTNoBcdBJzgFzoNL4Bq4AW6D+2AUTIBnYBa8BgsQBGEhMkSB5CEVSBPSh8wgBmQPuUG+UBAUCcVCCRAPEkJ50GaoGCqDqqF6qBn6HjoJnYeuQIPQXWgMmoZ+h97BCEyCqbASrAUbwwzYCfaBQ+BVcAK8Bs6FC+AdcCXcAB+FO+Dz8DX4NjwKP4PnEIAQERqiihgiDMQF8UeikHiEj6xHipAKpAFpRbqRPuQmMorMIG9RGBQFRUcZomxRnqhQFAu1BrUeVYKqRh1GdaB6UTdRY6hZ1Ec0Ga2I1kfboL3QEegEdBa6EF2BbkK3oy+ib6Mn0K8xGAwNo42xwnhiIjFJmLWYEsw+TBvmHGYQM46Zw2Kx8lh9rB3WH8vECrCF2CrsUexZ7BB2AvsGR8Sp4Mxw7rgoHA+Xj6vAHcGdwQ3hJnELeCm8Jt4G749n43PwpfhGfDf+On4Cv0CQJmgT7AghhCTCJkIloZVwkfCA8JJIJKoRrYmBRC5xI7GSeIx4mThGfEuSIemRXEjRJCFpB+kQ6RzpLuklmUzWIjuSo8gC8g5yM/kC+RH5jQRFwkjCS4ItsUGiRqJDYkjiuSReUlPSSXK1ZK5kheQJyeuSM1J4KS0pFymm1HqpGqmTUiNSc9IUaVNpf+lU6RLpI9JXpKdksDJaMm4ybJkCmYMyF2TGKQhFneJCYVE2UxopFykTVAxVm+pFTaIWU7+jDlBnZWVkl8mGyWbL1sielh2lITQtmhcthVZKO04bpr1borTEaQlnyfYlrUuGlszLLZVzlOPIFcm1yd2WeydPl3eTT5bfJd8p/1ABpaCnEKiQpbBf4aLCzFLqUtulrKVFS48vvacIK+opBimuVTyo2K84p6Ss5KGUrlSldEFpRpmm7KicpFyufEZ5WoWiYq/CVSlXOavylC5Ld6Kn0CvpvfRZVUVVT1Whar3qgOqCmrZaqFq+WpvaQ3WCOkM9Xr1cvUd9VkNFw08jT6NF454mXpOhmai5V7NPc15LWytca6tWp9aUtpy2l3audov2Ax2yjoPOGp0GnVu6GF2GbrLuPt0berCehV6iXo3edX1Y31Kfq79Pf9AAbWBtwDNoMBgxJBk6GWYathiOGdGMfI3yjTqNnhtrGEcZ7zLuM/5oYmGSYtJoct9UxtTbNN+02/R3Mz0zllmN2S1zsrm7+QbzLvMXy/SXcZbtX3bHgmLhZ7HVosfig6WVJd+y1XLaSsMq1qrWaoRBZQQwShiXrdHWztYbrE9Zv7WxtBHYHLf5zdbQNtn2iO3Ucu3lnOWNy8ft1OyYdvV2o/Z0+1j7A/ajDqoOTIcGh8eO6o5sxybHSSddpySno07PnU2c+c7tzvMuNi7rXM65Iq4erkWuA24ybqFu1W6P3NXcE9xb3Gc9LDzWepzzRHv6eO7yHPFS8mJ5NXvNelt5r/Pu9SH5BPtU+zz21fPl+3b7wX7efrv9HqzQXMFb0ekP/L38d/s/DNAOWBPwYyAmMCCwJvBJkGlQXlBfMCU4JvhI8OsQ55DSkPuhOqHC0J4wybDosOaw+XDX8LLw0QjjiHUR1yIVIrmRXVHYqLCopqi5lW4r96yciLaILoweXqW9KnvVldUKq1NWn46RjGHGnIhFx4bHHol9z/RnNjDn4rziauNmWS6svaxnbEd2OXuaY8cp40zG28WXxU8l2CXsTphOdEisSJzhunCruS+SPJPqkuaT/ZMPJX9KCU9pS8Wlxqae5Mnwknm9acpp2WmD6frphemja2zW7Fkzy/fhN2VAGasyugRU0c9Uv1BHuEU4lmmfWZP5Jiss60S2dDYvuz9HL2d7zmSue+63a1FrWWt78lTzNuWNrXNaV78eWh+3vmeD+oaCDRMbPTYe3kTYlLzpp3yT/LL8V5vDN3cXKBVsLBjf4rGlpVCikF84stV2a9021DbutoHt5turtn8sYhddLTYprih+X8IqufqN6TeV33zaEb9joNSydP9OzE7ezuFdDrsOl0mX5ZaN7/bb3VFOLy8qf7UnZs+VimUVdXsJe4V7Ryt9K7uqNKp2Vr2vTqy+XeNc01arWLu9dn4fe9/Qfsf9rXVKdcV17w5wD9yp96jvaNBqqDiIOZh58EljWGPft4xvm5sUmoqbPhziHRo9HHS4t9mqufmI4pHSFrhF2DJ9NProje9cv+tqNWytb6O1FR8Dx4THnn4f+/3wcZ/jPScYJ1p/0Pyhtp3SXtQBdeR0zHYmdo52RXYNnvQ+2dNt293+o9GPh06pnqo5LXu69AzhTMGZT2dzz86dSz83cz7h/HhPTM/9CxEXbvUG9g5c9Ll4+ZL7pQt9Tn1nL9tdPnXF5srJq4yrndcsr3X0W/S3/2TxU/uA5UDHdavrXTesb3QPLh88M+QwdP6m681Lt7xuXbu94vbgcOjwnZHokdE77DtTd1PuvriXeW/h/sYH6AdFD6UeVjxSfNTws+7PbaOWo6fHXMf6Hwc/vj/OGn/2S8Yv7ycKnpCfVEyqTDZPmU2dmnafvvF05dOJZ+nPFmYKf5X+tfa5zvMffnP8rX82YnbiBf/Fp99LXsq/PPRq2aueuYC5R69TXy/MF72Rf3P4LeNt37vwd5MLWe+x7ys/6H7o/ujz8cGn1E+f/gUDmPP8usTo0wAAAAlwSFlzAAALEwAACxMBAJqcGAAAANBJREFUOE9j+P//P1UwVkFyMJhgNPX+jwW/B2J5dA24MJhAMwCOmc19LgJpfnRN2DCYQDeADGxPFYN0I7J8aG+QgGPYHdWglJ0wvkVi0SJWC7/PyGpgGK9B6W2TM4Fy2iDDAkqau4BsJb+ixg5savEaxGTm8wFI64MMA2IpEBsYix+R1cAwwTASdY1MB8mDMLdt0FRsakAYr0FQ74BdAsJAtjpymCFjQoG9Ekjrg7wI86aEe/R6ZDUwTNBrxGLqGwTErhRiQZhBFGOsgqTj/wwAWDijBcYFCvcAAAAASUVORK5CYII=Generic External InteractorROOTRectanglefalseAnyAnyfalseA representation of a generic processfalseGE.PCentered on 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Generic ProcessROOTEllipsefalseAnyAnyfalseA border representation of a trust boundaryfalseGE.TB.BBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCGeneric Trust Border BoundaryROOTBorderBoundaryfalseAnyAnyfalseAn arc representation of a trust boundaryfalseGE.TB.LBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABX0lEQVQ4T2NgNPXGh/mhGJscGCNzQArtgVgfxmcy87kAwlA5ZLVwDGOAFQPp/1Dcj8zHZwiY4LUPdgLSMM0YmM8+5JaAY5gRkI3dAJuUUlsgjVUzCM/ZuDPg////vEA2dgNAkqpBKTuBbKwGRNV0iQNpmCZQGMG9AxPk57IJvA6ksRrAYu67EEjLA7E+s7nPReQwAWtGC0CiMMwQkPNZ5H0TtqArIIRBAWueUCgM9gLQEG1QGHDbBr1YuftQDJDvapFYtAhdEwwDY+TO8cvXXUCWw8IAbMjCrXtDgDQHlK8E04CO1YPTVoA0A9nwQIQZAtYMxaBAw2oAFINSLaoBSFgfGEgPgDQ2jWAs5hZVCaSxGwB0Ca+iX9I2IBusGORn3YistTA+q4Xf59KJcy1BarEaAMJAQ8ABixRg6omN/fWgwF26Y38EzLsghfiwNhBbADELlC8KxEpAzAHh/2cAANCSU7ngF2KpAAAAAElFTkSuQmCCGeneric Trust Line BoundaryROOTLineBoundaryfalseAnyAnyfalseA representation of an annotationfalseGE.ACentered on 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Free Text AnnotationROOTAnnotationfalseAnyAnyMicrosoft C+AI Security11111111-1111-1111-1111-111111111111Azure Threat Model Template1.0.0.33falseRepresents a request from a source to a target.falseSE.DF.TMCore.RequestBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACHDwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAEjHnZZ3VFTXFofPvXd6oc0wAlKG3rvAANJ7k15FYZgZYCgDDjM0sSGiAhFFRJoiSFDEgNFQJFZEsRAUVLAHJAgoMRhFVCxvRtaLrqy89/Ly++Osb+2z97n77L3PWhcAkqcvl5cGSwGQyhPwgzyc6RGRUXTsAIABHmCAKQBMVka6X7B7CBDJy82FniFyAl8EAfB6WLwCcNPQM4BOB/+fpFnpfIHomAARm7M5GSwRF4g4JUuQLrbPipgalyxmGCVmvihBEcuJOWGRDT77LLKjmNmpPLaIxTmns1PZYu4V8bZMIUfEiK+ICzO5nCwR3xKxRoowlSviN+LYVA4zAwAUSWwXcFiJIjYRMYkfEuQi4uUA4EgJX3HcVyzgZAvEl3JJS8/hcxMSBXQdli7d1NqaQffkZKVwBALDACYrmcln013SUtOZvBwAFu/8WTLi2tJFRbY0tba0NDQzMv2qUP91829K3NtFehn4uWcQrf+L7a/80hoAYMyJarPziy2uCoDOLQDI3fti0zgAgKSobx3Xv7oPTTwviQJBuo2xcVZWlhGXwzISF/QP/U+Hv6GvvmckPu6P8tBdOfFMYYqALq4bKy0lTcinZ6QzWRy64Z+H+B8H/nUeBkGceA6fwxNFhImmjMtLELWbx+YKuGk8Opf3n5r4D8P+pMW5FonS+BFQY4yA1HUqQH7tBygKESDR+8Vd/6NvvvgwIH554SqTi3P/7zf9Z8Gl4iWDm/A5ziUohM4S8jMX98TPEqABAUgCKpAHykAd6ABDYAasgC1wBG7AG/iDEBAJVgMWSASpgA+yQB7YBApBMdgJ9oBqUAcaQTNoBcdBJzgFzoNL4Bq4AW6D+2AUTIBnYBa8BgsQBGEhMkSB5CEVSBPSh8wgBmQPuUG+UBAUCcVCCRAPEkJ50GaoGCqDqqF6qBn6HjoJnYeuQIPQXWgMmoZ+h97BCEyCqbASrAUbwwzYCfaBQ+BVcAK8Bs6FC+AdcCXcAB+FO+Dz8DX4NjwKP4PnEIAQERqiihgiDMQF8UeikHiEj6xHipAKpAFpRbqRPuQmMorMIG9RGBQFRUcZomxRnqhQFAu1BrUeVYKqRh1GdaB6UTdRY6hZ1Ec0Ga2I1kfboL3QEegEdBa6EF2BbkK3oy+ib6Mn0K8xGAwNo42xwnhiIjFJmLWYEsw+TBvmHGYQM46Zw2Kx8lh9rB3WH8vECrCF2CrsUexZ7BB2AvsGR8Sp4Mxw7rgoHA+Xj6vAHcGdwQ3hJnELeCm8Jt4G749n43PwpfhGfDf+On4Cv0CQJmgT7AghhCTCJkIloZVwkfCA8JJIJKoRrYmBRC5xI7GSeIx4mThGfEuSIemRXEjRJCFpB+kQ6RzpLuklmUzWIjuSo8gC8g5yM/kC+RH5jQRFwkjCS4ItsUGiRqJDYkjiuSReUlPSSXK1ZK5kheQJyeuSM1J4KS0pFymm1HqpGqmTUiNSc9IUaVNpf+lU6RLpI9JXpKdksDJaMm4ybJkCmYMyF2TGKQhFneJCYVE2UxopFykTVAxVm+pFTaIWU7+jDlBnZWVkl8mGyWbL1sielh2lITQtmhcthVZKO04bpr1borTEaQlnyfYlrUuGlszLLZVzlOPIFcm1yd2WeydPl3eTT5bfJd8p/1ABpaCnEKiQpbBf4aLCzFLqUtulrKVFS48vvacIK+opBimuVTyo2K84p6Ss5KGUrlSldEFpRpmm7KicpFyufEZ5WoWiYq/CVSlXOavylC5Ld6Kn0CvpvfRZVUVVT1Whar3qgOqCmrZaqFq+WpvaQ3WCOkM9Xr1cvUd9VkNFw08jT6NF454mXpOhmai5V7NPc15LWytca6tWp9aUtpy2l3audov2Ax2yjoPOGp0GnVu6GF2GbrLuPt0berCehV6iXo3edX1Y31Kfq79Pf9AAbWBtwDNoMBgxJBk6GWYathiOGdGMfI3yjTqNnhtrGEcZ7zLuM/5oYmGSYtJoct9UxtTbNN+02/R3Mz0zllmN2S1zsrm7+QbzLvMXy/SXcZbtX3bHgmLhZ7HVosfig6WVJd+y1XLaSsMq1qrWaoRBZQQwShiXrdHWztYbrE9Zv7WxtBHYHLf5zdbQNtn2iO3Ucu3lnOWNy8ft1OyYdvV2o/Z0+1j7A/ajDqoOTIcGh8eO6o5sxybHSSddpySno07PnU2c+c7tzvMuNi7rXM65Iq4erkWuA24ybqFu1W6P3NXcE9xb3Gc9LDzWepzzRHv6eO7yHPFS8mJ5NXvNelt5r/Pu9SH5BPtU+zz21fPl+3b7wX7efrv9HqzQXMFb0ekP/L38d/s/DNAOWBPwYyAmMCCwJvBJkGlQXlBfMCU4JvhI8OsQ55DSkPuhOqHC0J4wybDosOaw+XDX8LLw0QjjiHUR1yIVIrmRXVHYqLCopqi5lW4r96yciLaILoweXqW9KnvVldUKq1NWn46RjGHGnIhFx4bHHol9z/RnNjDn4rziauNmWS6svaxnbEd2OXuaY8cp40zG28WXxU8l2CXsTphOdEisSJzhunCruS+SPJPqkuaT/ZMPJX9KCU9pS8Wlxqae5Mnwknm9acpp2WmD6frphemja2zW7Fkzy/fhN2VAGasyugRU0c9Uv1BHuEU4lmmfWZP5Jiss60S2dDYvuz9HL2d7zmSue+63a1FrWWt78lTzNuWNrXNaV78eWh+3vmeD+oaCDRMbPTYe3kTYlLzpp3yT/LL8V5vDN3cXKBVsLBjf4rGlpVCikF84stV2a9021DbutoHt5turtn8sYhddLTYprih+X8IqufqN6TeV33zaEb9joNSydP9OzE7ezuFdDrsOl0mX5ZaN7/bb3VFOLy8qf7UnZs+VimUVdXsJe4V7Ryt9K7uqNKp2Vr2vTqy+XeNc01arWLu9dn4fe9/Qfsf9rXVKdcV17w5wD9yp96jvaNBqqDiIOZh58EljWGPft4xvm5sUmoqbPhziHRo9HHS4t9mqufmI4pHSFrhF2DJ9NProje9cv+tqNWytb6O1FR8Dx4THnn4f+/3wcZ/jPScYJ1p/0Pyhtp3SXtQBdeR0zHYmdo52RXYNnvQ+2dNt293+o9GPh06pnqo5LXu69AzhTMGZT2dzz86dSz83cz7h/HhPTM/9CxEXbvUG9g5c9Ll4+ZL7pQt9Tn1nL9tdPnXF5srJq4yrndcsr3X0W/S3/2TxU/uA5UDHdavrXTesb3QPLh88M+QwdP6m681Lt7xuXbu94vbgcOjwnZHokdE77DtTd1PuvriXeW/h/sYH6AdFD6UeVjxSfNTws+7PbaOWo6fHXMf6Hwc/vj/OGn/2S8Yv7ycKnpCfVEyqTDZPmU2dmnafvvF05dOJZ+nPFmYKf5X+tfa5zvMffnP8rX82YnbiBf/Fp99LXsq/PPRq2aueuYC5R69TXy/MF72Rf3P4LeNt37vwd5MLWe+x7ys/6H7o/ujz8cGn1E+f/gUDmPP8usTo0wAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEtJREFUOE9j+P//P1bMaOr9Hx2jqwFhDAEYHngDYBiXRhjGKoiMR5IBIIWkYmwGgGh0jFN8OBkA4qBhbGJYxbEagMNQrOIUGuD9HwBIkRfD8QF9EgAAAABJRU5ErkJggg==RequestGE.DFLinefalseAnyAnyfalseRepresents a response from a target to a sourcefalseSE.DF.TMCore.ResponseBefore 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ResponseGE.DFLinefalseAnyAnyfalsefalseSelectSQLMongoDBAzure TableCassandraAPI TypeVirtualDynamicd456e645-5642-41ad-857f-951af1a3d968ListfalseSelectAllow access from all networksAllow access from selected networks (including Azure)Allow access from selected networks (excluding Azure)Azure Cosmos DB Firewall SettingsVirtualDynamicb646c6da-6894-432a-8925-646ae6d1d0eaListGlobally distributed, multi-model database service with support for NoSQLfalseSE.P.TMCore.AzureDocumentDBLower right of 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 Cosmos DBGE.DSParallelLinesfalseAnyAnyfalsefalseSelectAllow access from all networksAllow access from selected networksAzure Key Vault Firewall SettingsVirtualDynamiccd610fb8-4fbd-49c0-966f-8b4634b39262ListfalseSelectTrueFalseAzure Key Vault Audit Logging EnabledVirtualDynamic78bf9482-5267-41c6-84fd-bac2fb6ca0b9ListfalseSelectManaged IdentitiesService or User Principal and CertificateService or User Principal and SecretAuthenticating to Key VaultVirtualDynamicae94fa17-596d-476e-a283-0afc166dcf26ListTool for securely storing and accessing secretsfalseSE.DS.TMCore.AzureKeyVaultLower right of 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Azure Key VaultGE.DSParallelLinesfalseAnyAnyfalsefalseSelectTrueFalseAzure Redis Cache TLS EnforcedVirtualDynamic866e2e37-a089-45bc-9576-20fc95304b82ListfalseSelectAllow access from all networksAllow access from selected networksAzure Redis Cache Firewall SettingsVirtualDynamic1bda806d-f9b6-4d4e-ab89-bf649f2c2ca5ListAzure Redis CachefalseSE.P.TMCore.AzureRedisLower right of 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Azure Redis CacheGE.DSParallelLinesfalseAnyAnyfalsefalseSelectFileTableQueueBlobStorage TypeVirtualDynamicb3ece90f-c578-4a48-b4d4-89d97614e0d2ListfalseSelectTrueFalseHTTPS EnforcedVirtualDynamic229f2e53-bc3f-476c-8ac9-57da37efd00fListfalseSelectAllow access from all networksAllow access from selective networksNetwork SecurityVirtualDynamiceb012c7c-9201-40d2-989f-2aad423895a5ListfalseSelectTrueFalseCORS EnabledVirtualDynamicc63455d0-ad77-4b08-aa02-9f8026bb056fListAzure StoragefalseSE.DS.TMCore.AzureStorageLower right of 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Azure StorageGE.DSParallelLinesfalseAnyAnyfalsefalseSelectAzure-RedisGenericCache TechnologiesVirtualDynamic2226af6a-5cfe-4283-a62d-f35d3234336dListfalseSelectAllCache VersionVirtualDynamic250ddabe-ef50-4fe3-9f7d-74881a8c608eListCachefalseSE.DS.TMCore.CacheLower right of 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.DSParallelLinesfalseAnyAnyfalsefalseSelectGenericOnPremDatabase TechnologiesVirtualDynamic6047e74b-a4e1-4e5b-873e-3f7d8658d6b3ListfalseSelectAllV12MsSQL2016MsSQL2012MsSQL2014SQL VersionVirtualDynamic0a5c9e0f-f68c-4607-9a1a-a02841f1e9deListfalseSelectYesNoSSIS packages UsedVirtualDynamic649208cc-3b55-40ff-94b9-015c0fb0c9e8ListDatabasefalseSE.DS.TMCore.SQLLower right of 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F4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJVLxAeglAJRIxQeglwBQIhUfgF4CQIlUfAB6CQAlUvEB6CUAlEjFB6CXAFAiFR+AXgJAiVR8AHoJACVS8QHoJQCUSMUHoJcAUCIVH4BeAkCJVHwAegkAJT7+9O5bxQeglwBQ4pPP7sUbAIBOAkCJv//zQbwBAOgkAJT46l//jTcAAJ0EgBLf330SbwAAOgkAJR49fh5vAAA6CQAlfvv996M//eWHeBMA0EcAKHLj5kG8CQDoIwAUuXP/p3gTANBnfYxoEBsbvPz5N68BADj681/vHA8LeaxYstjY4suv/hNvBgB6fH7j4fGQkMeJJYuNLQ6fvIw3AwA9vv7ux+MhIY8TSxYbmzgVEKDbvYdPj4eDPEYsWWxscvDImQAAzWZN2PrY0CA2tpn3P+mmAGDZWt//j9jY5snTn+ONAcCy3f7hf8fDQB4bli42NvKBIIAusxW8dfp/xMZGcxN8/OndeJMAsDw3bz067v7zmNAgNrZ6cPAs3iQALM+8/l0fB5rExmZeBQAs3xwEt97/t4mNzeZLgc4GAFi29qf/ERvbzVehrAcAWKb2d/8rsZGjjx4fvvCxIICFmQ//NK/8Py028sr3d5/EGwiA/dR67G8SG3nt1jeP400EwH6x8O9NsZHXZlGgo4IB9tsnn90z9b8mNvKmX361MwBgX816Lqv+3xYbeduEgC++NBMAsG8ePX5+3I3nvr1ZbCSb1wE3bh7EGwyA3XPn/k/H3Xfu09vFRt5NCADYD19/9+Nxt537cgSAC5kQMKtJ0w0HwPZZ8f9hsZGz8d0AgN0zi7bnQW29z+ZNsZGzc04AwO6YV7SzaHu9r+ZtsZHzmc8IOzYYYLtmVtaT/9nFRs5v9pjOQRPppgTgan17+/C4K879M1ls5GJm2sniQIDrZavfxcRGLue7fx/GmxSAzZlXrwePHPJzUbGRy5uTp+azk+mmBeBypn89fPLyuLvNfTAfFhvZjOcvfvUhIYANm5X+PuxzebGRzbr9w//sEgC4pOlHpz9d72O5mNjI5j199ovZAIAL+ts/7vui34bFRq6O2QCA85kD1+zv37zYyNUyGwDwYbPQz6d8r05s5HqYDQDI5kwVC/2uVmzk+pgNAHht3vV76r8esZHrN4dZOEoYaLVa4e9d//WJjWzP93efHH386d34AwFYopu3Hpnu34LYyHbNNwXmwxbWBwBLNtP9jw9fHHd7uS/kasVGdsMk4vm8ZfrhAOyrWd3vQJ/ti43sljn84osvLRQE9tsM/POxtJnlXO/nuH6xkd00K2P//s8H8YcFsKsM/LspNrLbJgiYEQB23Sxonql+A/9uio3sh1k8M4dlpB8ewLbMwD87mmzp222xkf0yawRmG036IQJcFwP/fomN7KfnL361awC4dnOa6b2HT4+7odw3sZtiI/tttg9+/d2PzhEArsz0L/PAcfjk5XG3k/sidltsZBkmCNy5/9PJYRvpBwxwXquFfU7u23+xkeWZlD5p3awAcBGz8+jBwbPj7iT3Meyf2MhyzXYcswLAWaym+eerpet9CfsvNtLBrACQ3Lh5cLKoz/79ZYuNdDErAMwpo9MPeLffIzbSa84UmB0En3x2L3YSwHJM6J8jemcL8XpfwPLFRhhz0uCtbx6frPpNnQewf+b3PCF/wv76b54usRHWTRiY9QLzUY/UqQC7a2b0Jsz79j6nxUZ4n4NHz4UB2HFzOt/s17eCn3eJjXAWc9737Aue7xDYSQDbNYF8fotW73NWsREuYj5TPO8W7SaA6zG/tfnNmdrnImIjXNasKp4tRfO5YrMDsBnzlD+/qfninpX7XFZshE0zOwDnd3rAt2qfTYuNcJXMDkA2W/TmPf78Pgz4XLXYCNdpOrp5wpmOzwFENDk94Futz3WLjbBNM0MwuwvmlcEcT5o6Ttg3M50/X9Sbk/dmK613+GxbbIRdMtsNZ5XzdJzTgXptwK6be3Tu1W9vG+zZXbERdt3qtcGcbjYdbeqE4TqcHuxn5spUPvsiNsI+mo53nrZmpmA+Z+obBmzaDPRzCubcYzMr5cmefRYbYSnmRLTpqOdI1Om453jU1LHDaQZ6GsRGWLrDJy9Ppmung5+Ofjp8MwZdZseJgZ5msRGaTThYLTqc97ozSNiNsH+mZlO72U0ytZzAZ5CH12IjkM3gMYPI7NueQWX2cM8gM+xOuD6rwX1MHcacNjm1mV0j63UD3hYbgYtbbVscq9cMwsL7zRHRq2szOztW12wWda6upS/cwWbFRgBgyY4++j/BMxlbj3YqvwAAAABJRU5ErkJggg==DatabaseGE.DSParallelLinesfalseAnyAnyfalsefalseSelectYesNoAzure SQL DB SSIS Packages UsedVirtualDynamicd8830a8d-37b8-472e-abcc-0d157857f576ListfalseSelectAllow access from all networksAllow access from AzureAllow access from selected networksAzure SQL DB Firewall SettingsVirtualDynamice68e212d-896e-403e-8a2d-8c6d2b2505dfListfalseSelectTrueFalseAzure SQL DB TDE EnabledVirtualDynamic3a2a095f-94bc-467f-987c-8dac8307cdc6ListfalseSelectTrueFalseAzure SQL DB Auditing EnabledVirtualDynamic6a3509e5-a3fd-41db-8dea-6fb44b031e4bListfalseSelectTrueFalseVulnerability Assessment EnabledVirtualDynamic212cf67e-047a-4617-860f-92282e04b8d8ListServer based TDS service for highly available, globally distributed appsfalseSE.DS.TMCore.AzureSQLDBLower right of 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 SQL DatabaseGE.DSParallelLinesfalseAnyAnyfalsefalseSelectAllow access from all networksAllow access from selected networks (including Azure)Allow access from selected networks (excluding Azure)Azure SQL DW DB Firewall SettingsVirtualDynamicb8c8850c-979b-4db0-b536-9aa364b7e6a2ListfalseSelectTrueFalseAzure SQL DW DB TDE EnabledVirtualDynamicd2ce181d-abae-448d-8ef4-9acdbeb839feListfalseSelectTrueFalseAzure SQL DW DB Auditing EnabledVirtualDynamiccd2a18a2-cebd-4b0f-ae4c-964b190e84f2ListCloud-based Enterprise Data WarehousefalseSE.DS.TMCore.AzureSQLDWDBLower right of stenciliVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAABcRQAAXEUBuS1iLAAALZ9JREFUeF7t3SGc3Mb9N+A/LCwsLCwsLCwsLA0sLCwMCCgIKAgoMCgIKDApCAwICAwICAgwMDAwMDAwMAgoudffu1e9s/a359uVNBpJD3j200yTXc2eRvPd0czo/25ubgCAgykLAYB9KwsBgH0rCwGAfSsLAYB9KwsBgH0rCwGAfSsLAYB9KwvhKJ7//P7mz/9+c/PD618+/GP97wDsUVkIe/fty/c3v//nq5v/+/zF/yQIvHr33w//d/3fAOxJWQh7lV/6f/zX6486/rG/fvP25s17QQDYt7IQ9uanN7/c/sKvOvzKr754efP5d29v3t3eGajfE2DLykLYiwzp/+U/T+/4x37995c3X37/7uaX2wGB+jMAtqgshK3LEP7fvn17+0u+6tgv9ZsvX948+/Hdh7euPw9ga8pC2KoM2X/x3dvbX+5VRz7V7756dfPNi/cfPqr+fICtKAthazJE/9UP725/qVcd99z+8Oz1zfevLB0EtqsshC35+qf3zTr+sT99/fomEwzHxwTQu7IQtiBD8RmSrzrm1j57bg8BYFvKQuhZht4zBF91xGvLxEN7CABbUBZCjzLUniH3quPtSSYgZiKiPQSAnpWF0JMMrWeIvepse5Z5CZmYaA8BoEdlIfQgQ+nZlrfqXLfkt/94dZOJiuP6AaypLIQ1Zeg82/DOtYlPL/LwIXsIAL0oC2ENGSrPtrtLbeLTizyMyOOHgbWVhdBattlday3/WvJwohdvrRgA1lEWQivPf35/e4+86iCPIg8rsnQQaK0shKV9+/L97T3xqkM8osx3yB4Clg4CrZSFsJTc+8498KoT5H4PAUsHgaWVhTC33OvOPe+q0+OUxw8DSysLYS7ZxCf3uKtOjk/L/AhLB4EllIUwVSa15Z723tbyryXzJTx+GJhTWQjXyiS23MPe+1r+tWT+hMcPA3MoC+FSmbSWfe+PtpZ/LZlP4fHDwBRlIVwi+9wffS3/WvKsBHsIANcoC+EpMjntd1/p+NeWeRYePwxcqiyEx2Qy2h+eWcvfm8y78Phh4KnKQqhk8tmfvtbx9y7zMDx+GPiUshAeymSzz55by781uT1jDwHgnLIQYljLX3UubEdu19hDABgrCzm2TCb7/Dub+OxNlg7aQwAYlIUcUyaPffn9O5v47Fy2ZraHAFAWcjx58IxNfI5jePywPQTguMpCjiOTxGzic1zD44ftIQDHUxayf9++fH/7gJmqU+B4MvqTPQTG5wmwX2Uh+/XD619uHyhTdQKQ0aDnP1s6CEdQFrI/L97+93YWeHXRh7GMDmWUaHweAftRFrIfmeSVWd/VRR4+JaNFGTUan1fA9pWFbN+wiY+1/Mwho0cZRRqfZ8B2lYVsV2ZzZ1a3tfwsweOHYT/KQrYnm/hkFre1/Cwto0rZKdLSQdi2spBtyZPfrOWntYwyZedIjx+GbSoL2YZs4mMtP2vLqFN2khyfn0DfykL6lie75Qlv1cUY1pJRKI8fhu0oC+lTnuT2p691/PTN44dhG8pC+pInt3323Fp+tiVh1eOHoV9lIX0Y1vJXF1fYioRXjx+G/pSFrGtYy28TH/bE44ehL2Uh68hyqiyrsokPe5VQ6/HD0IeykPayjMomPhzF8PhhewjAespC2smyKZv4cFQ597OR1bhdAMsrC1lelknZxAfupC3YQwDaKgtZTh6tmkesVhdBOLq0DXsIQBtlIfPLo1TzSNXqogd8zOOHYXllIfPJsqe//EfHD9dI27F0EJZRFjJdljll3bO1/DBN2lDakqWDMK+ykOsNm/hYyw/zSptK27J0EOZRFnK5XJSyrtlafljWsIfAuA0ClykLuUzWMVvLD215/DBMUxbyNLn4WMsP60obtHQQLlcW8rhcbKzlh76kTXr8MDxdWUgtF5c847y6+AB9yB4CHj8Mn1YW8rFcTPJM8+piA/Tpr994/DA8pizkTi4eWX9cXVyA/nn8MJxXFh7dsJbfJj6wD9lDwOOH4WNl4VENa/lt4gP7lD0EPH4Y7pSFR/TsR5v4wFH87it7CEBZeCS5CNjEB47pD888fpjjKguPII3eJj5AZOmgPQQ4mrJwz9LIbeIDVPL4YXsIcBRl4R69ePvf25RfNXqAwfD4YXsIsHdl4Z6kESfVVw0d4Jzh8cP2EGCvysI9SKNNireWH5jC44fZq7Jwy7KWP6ndWn5gTlkt9PxnSwfZj7Jwi4ZNfKzlB5aU1UPfvhQE2L6ycGuys5e1/EBLWU30w2tLB9musnArsomPtfzAmrK6KKuMxtcn6F1Z2Lts4mMtP9ATjx9ma8rCXmUTH2v5gV5l1dHnlg6yEWVhb7Iz12fPdfzANmQV0pffe/wwfSsLe5HhtKzlrxoYQO+yKilPGh1f26AHZeHaMnyWtfw28QH2IKuUPH6Y3pSFaxnW8tvEB9gjjx+mJ2XhGrKW3yY+wBH86evXHj/M6srCljIsZhMf4Igyudnjh1lLWdhChsFs4gPwwuOHWUVZuKQMe9nEB+BjmfTs8cO0VBYuIcNcNvEBeNzw+GF7CLC0snBOGdb6y390/ACXyNyoTI4eX1NhLmXhHDKMlfta1vIDXC9zpewhwBLKwikybJX7WNbyA8wnc6fsIcCcysJr5b6VtfwAy/H4YeZSFl4q96ms5QdoJ3OrLB1kirLwqXJfylp+gHVkjlXmWlk6yDXKwk/JfShr+QH6kDlXmXtl6SCXKAvPySY+1vID9GnYQ2B87YZKWTiWTXys5QfYBo8f5inKwkEmmOT+UnWCAdC3zNGydJBzysJMKMn9JJv4AGxf5mx5/DBjH/1DJpDk/pFNfAD2J3O4PH6Ywf/+R9by28QHYP/++o3HD/P/A4BNfACOJbd43RY4truX4uQAYN9MEDy2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi2u5fixABg3wSAY7t7KU4MAPZNADi225ecBL36/T9flSduS89/fl8eG9C3Hq4fD331w7vyONfy7rb/rzsH9q8s7Mkf//W6bEgtvXr33w+HUh8f0K8erh8PpdMdHyOspSzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAMC1BAA4ryzsiQAAXEsAgPPKwp4IAPP55UM1cgHasp/euIDydAIAnFcW9kQAmE/qUdVvS3I+jOsF5wgAcF5Z2BMBYD4CAEcjAMB5ZWFPBID5CAAcjQAA55WFPREA5iMAcDQCAJxXFvZEAJiPAMDRCABwXlnYEwFgPgIARyMAwHllYU8EgPkIAByNAADnlYU9EQDmIwBwNAIAnFcW9kQAmI8AwNEIAHBeWdgTAWA+AgBHIwDAeWVhTwSA+QgAHI0AAOeVhT0RAOYjAHA0AgCcVxb2RACYjwDA0QgAcF5Z2BMBYD4CAEcjAMB5ZWFPBID5CAAcjQAA55WFPREA5iMAcDQCAJxXFvZEAJiPAMDRCABwXlnYEwFgPgIARyMAwHllYU8EgPkIAByNAADnlYU9EQDmIwBwNAIAnFcW9kQAmI8AwNEIAHBeWdgTAWA+AgBHIwDAeWVhTwSA+QgAHI0AAOeVhT0RAOYjAHA0AgCcVxb2RACYjwDA0QgAcF5Z2BMBYD4CAEcjAMB5ZWFPBID5CAAcjQAA55WFPREA5iMAcDQCAJxXFvZEAJiPAMDRCABwXlnYEwFgPgIARyMAwHllYU8EgPkIAByNAADnlYU9EQDmIwBwNAIAnFcW9kQAmI8AwNEIAHBeWdgTAWA+AgBHIwDAeWVhTwSA+QgAHI0AAOeVhT0RAOYjAHA0AgCcVxb2RACYjwDA0QgAcF5Z2BMBYD4CAEcjAMB5ZWFPBID5CAAcjQAA55WFPREA5iMAcDQCAJxXFvZEAJiPAMDRCABwXlnYEwFgPgIAR9PD9eN3X726+ct/3tx89cO7m3e3/X99rNBaWdgTAWA+AgBH0/r68ZsvX978+d9vbr747u3tr/1fbi8d9bHB2srCnggA8xEAOJqlrx/5df+3b9/efPPi/c2b9/u4TnAcZWFPBID5CAAczdzXj9/+4244/+ufdPhsX1nYEwFgPgIARzP1+vHrv7+8+ez5m5tnP767efFWh8++lIU9EQDmIwBwNNdcP3If/6/fvL359uX7D29Rvy/sQVnYEwFgPgIAR/PU60fu5X/+3dubn94cd5le6p6Ji5+SCY7n5NZI9d+MmRzZh7KwJwLAfLIEqWq0W5ILzLhecM5j1490+lmat7eh/aEjzwjG0G4ybyHfxeAPz9a/rj6UuRUPj+9PX7/+37HnbzQEB7dh5lUW9iQnQ3XCtLSXAABHM75+/OqLl7ed4Q+vt/lLP8edjjAdY0Yshg4zYeZhPY8gdR7q/zAoCAlPVxb2ZNyA1yAAwDYN1490FpnI1/tGPDm+dGLpzNKpZU+B1CHBZXxd4nHDqELmc+S7zIjIkW/xVMrCnggAwLV6nr2fjj63tIZf8pl8WF1/mN/v//nqfxs2ZQ+HowaDsrAnAgCwZZnwNgzb5972EYfrtyLBIMs+MwKz1dtElygLeyIAAFuSEYf8ss/QczqU6prCdqQPyijNHnd7LAt7IgAAPcvw8Zffv7vtKLJxUHUNYT8ytyCjBAl5W+8bysKeCABAT3I9yMU/nYAOn9zSGZ4HsbX9DcrCnggAwNpycc9F3v17PiV9VkaEtrAcsSzsiQAArCGdfvYM8CufayUwZvJnr2GgLOyJAAC0kOHb5z/fDe0fad19lh/mOntOQlA6sWsNexmcc5TvOnMHMorU05LDsrAnOUGqL7MlAQD2K8u90sntpSMaOtZ0NkMnnGCTpYjR+0z2HN9wrMPyyUGWUaZuW98zIWEgtwnW/luUhT0RAIC5Zce9bBK0tXv6w6/1YXe7oWM/6va3D8NCvo9hU6V0sNX316OMkOTvOK5bC2VhTwQAYC5b+bWf/QOGoffMRUgHN64LnzY8GCnfY0JTD/3JOQl3CTAt+5uysCcCADBVOtFeN+XJNS7D9RmROMLucz3IiEnOieG2Qm8jBhkVaDFXoCzsiQAAXCvr9Xu6uOeWQ37Zp7M/6v7zvcrthAzFJ4z18rjkBIElR3/Kwp4IAMAlMps/HWwPHX9GHTKsmyfR9f4kQj728BkOaweC9INLBIGysCdbDADDM7u3bFynqcYze7dIEOxffvGvOUM8n51f+PklufYMb+aVAJfbBplLsNbk0fSHc074LAt7ssUAsKUZqOeM6zRVLszV52xJfgmM60UfMpy+1q+0YbMXQ/rHkn4hTw1cY25JRpXmGFEqC3siAKxjXKepBACWkItg7tlWf68l9b7DG22tEQYy2pTr6vhYLlEW9kQAWMe4TlMJAMwtw+wth/uzJXCGf3X6PCb9RX6ht9pCOiNfl/ZRg7KwJwLAOsZ1mkoAYC6ZnJWOuPobLSG/9jOp0CQ+LpHzNNe9FremEjYyP2F8DJ9SFvZEAFjHuE5TCQDMIb++Ww2z5tqTyZ/jY4BLZX5IlvRV59mcMvIw/uzHlIU9EQDWMa7TVAIAU2XIv8Wwqo6fpbQIAhlxeOoKlLKwJwLAOsZ1mkoAYIp899XfZE65cNqJjxaWXrWSPugp/VZZ2BMBYB3jOk0lAHCtpTv/jCrkyWzjz4WlZeXAUqNaTwkBZWFPBIB1jOs0lQDANZbu/LMPvA17WFPOv5yH1fk51adCQFnYEwFgHeM6TSUAcKn8Kq/+DnO5dMIULGmp/SweCwEnBb0RANYxrtNUAgCXyCS86m8whzwKeK3nr8Njcp1c4lHV6UfHnxUnBb0RANYxrtNUAgBPlSHRpTb4ycXVDH96lnBanbtTVdevj/6hRwLAOsZ1mkoA4KmWXCaVDX3Gnwe9ye2p6vydIuF3vMrlow/tkQCwjnGdphIAeIolzxP3/NmSJSYGZhOth5/x0Qf2SABYx7hOUwkAPMVSu/zllkK2Zn34WdCz7BVQnctTPdwy+ORDeyMArGNcp6kEAD5lyYl/WW89/jzo3RIrA3KLbXj/kw/sjQCwjnGdphIA+JQl7/379c8WLTUKMPRp5Yf2RABYx7hOUwkAPCZP2lti+VPkaX7jz4MtSHCtzumphmtZ+aE9EQDWMa7TVAIAj8ns5Oo7n8PDIU/YmiX6k8+e37WJ8gN7IgCsY1ynqQQAHrPU2ufIbOrx58EWZE+MJUbG8iCivH/5oT0RANYxrtNUAgCPWXLb36wAGH8ebMES+wFEHkCU9y8/tCcCwDrGdZpKAOAxf/nPss9I98AftmjJviTvX35oTwSAdYzrNJUAwGOWDgAe98vWLDkvJvIZ5Qf3RABYx7hOUwkAPGbpAJD7qFlp8PAzoWdLLouNfEb5wT0RANYxrtNUAgCPWToARD5j/LnQoyU3xRrkc8oP74kAsI5xnaYSAHhMiwAQD7dBhR6lv8kkver8nVM+qzyAnggA6xjXaSoBgMe0CgC5FfDtSyGAPqWvadV/5PPKg+iJALCOcZ2mEgB4TKsAEEIAPWrZ+Uc+szyQnggA6xjXaSoBgMe0DACDnJPj44A15J5/i2H/h/K55cH0RABYx7hOUwkAPGaNABB//eat1QGsaqnNfj4ln10eUE8EgHWM6zSVAMBj1goAkZ0C3RKgtazzz5a81TnZQo6hPLCeCADrGNdpKgGAx6wZAAZ5ZkAevzo+NphTRpyWeM7/pXIs5QH2RABYx7hOUwkAPKaHADDIk9IubfPwKXm071c/vLsdcarOu9ZyTOWB9kQAWMe4TlMJADympwAwyDG9eCsIME2eQ5FrRy8d/yDHVh5wTwSAdYzrNJUAwGN6DACD3BowR4BLZWZ/RpOqc6oHOcbywHsiAKxjXKepBAAe03MAGPzuq1e3DxVye4Bzcn//2Y/vbs+V6hzqSY63rERPBIB1jOs0lQDAY7YQAB7KdSnntCWEZIg/58LSD++ZW469rFBPBIB1jOs0lQDAY7YWAB7KLYL86ktHMK4X+5Q+IRP6euifrpV6lJXriQCwjnGdphIAeMyWA8BDWdedjsFtgv3JhNBcx37/z+1f3yN1KivaEwFgHeM6TSUA8Ji9BICHch84u7w9//m90YENynU/162cm3l+RPU33rLUsax4TwSAdYzrNJUAwGP2GADGEghSz9wusOFQfzJrP5M88zfawiS+qVLn8ovoiQCwjnGdphIAeMwRAkAl17fsCpf2ka1hx98Ly8h3nSCWZ0HsZUj/Uvkeyi+nJwLAOsZ1mkoA4DFHDQCVdEj5PnK+ffPivdGCK2WFRn7Vp6PPd5k1+Uft7Cv5jsovricCwDrGdZpKAOAxAsCnZVh6GDHIUHU6t0uvTXuT7XXzPSQopX1mKV6+oz3es59bvr/yS+2JALCOcZ2mEgB4jAAwTcJBliPmHB3CwUPj77t3mXH/8Phz/UjdIr/ke+gXti7fc/nl90QAWMe4TlMJADxGAGhnGEkYZERh6FwjqxYedr5TZEnkw/d+6OExrPlY3KNKuysbY09yclQH35IAMJ0AwGMEAGgr7a5sjD0RANYxrtNUAgCPEQCgrbS7sjH2ZIsBYLhHtWXjOk2Vp6lVn7MlCTHjejEPAQDaSrsrG2NPcuGtDr6lSwMAcBkBANpKuysbY08EANg/AQDaSrsrG2NPBADYPwEA2kq7KxtjTwQA2D8BANpKuysbY08EANg/AQDaSrsrG2NPBADYPwEA2kq7KxtjTwQA2D8BANpKuysbY08EANg/AQDaSrsrG2NPBADYPwEA2kq7KxtjTwQA2D8BANpKuysbY08EANg/AQDaSrsrG2NPBADYPwEA2kq7KxtjTwQA2D8BANpKuysbY08EANg/AQDaSrsrG2NPBADYPwEA2kq7KxtjTwQA2D8BANpKuysbY08EANg/AQDaSrsrG2NPthgAfvuPV+X7bMm4TlN9/dP78nO25Ivv3n6oSl2/a+T9qs/Zku9f/fKhKnX9LiEAQFtpd2Vj7IkAsI5xnaYSAE4JAPcEAGgr7a5sjD0RANYxrtNUAsApAeCeAABtpd2VjbEnAsA6xnWaSgA4JQDcEwCgrbS7sjH2RABYx7hOUwkApwSAewIAtJV2VzbGnggA6xjXaSoB4JQAcE8AgLbS7srG2BMBYB3jOk0lAJwSAO4JANBW2l3ZGHsiAKxjXKepBIBTAsA9AQDaSrsrG2NPBIB1jOs0lQBwSgC4JwBAW2l3ZWPsiQCwjnGdphIATgkA9wQAaCvtrmyMPREA1jGu01QCwCkB4J4AAG2l3ZWNsScCwDrGdZpKADglANwTAKCttLuyMfZEAFjHuE5TCQCnBIB7AgC0lXZXNsaeCADrGNdpKgHglABwTwCAttLuysbYEwFgHeM6TSUAnBIA7gkA0FbaXdkYeyIArGNcp6kEgFMCwD0BANpKuysbY08EgHWM6zSVAHBKALgnAEBbaXdlY+yJALCOcZ2mEgBOCQD3BABoK+2ubIw9EQDWMa7TVALAKQHgngAAbaXdlY2xJwLAOsZ1mkoAOCUA3BMAoK20u7Ix9kQAWMe4TlMJAKcEgHsCALSVdlc2xp4IAOsY12kqAeCUAHBPAIC20u7KxtgTAWAd4zpNJQCcEgDuCQDQVtpd2Rh7IgCsY1ynqQSAUwLAPQEA2kq7KxtjTwSAdYzrNJUAcEoAuCcAQFtpd2Vj7IkAsI5xnaYSAE4JAPcEAGgr7a5sjD0RANYxrtNUAsApAeCeAABtpd2VjbEnAsA6xnWaSgA4JQDcEwCgrbS7sjH2RABYx7hOUwkApwSAewIAtJV2VzbGnggA6xjXaSoB4JQAcE8AgLbS7srG2BMBYB3jOk0lAJwSAO4JANBW2l3ZGHsiAKxjXKepBIBTAsA9AQDaSrsrG2NPBIB1jOs0lQBwSgC4JwBAW2l3ZWPsiQCwjnGdphIATgkA9wQAaCvtrmyMPREA1jGu01QCwCkB4J4AAG2l3ZWNsScCwDrGdZpKADglANwTAKCttLuyMfZEAFjHuE5TCQCnBIB7AgC0lXZXNsaeCADrGNdpKgHglABwTwCAttLuysbYEwFgHeM6TSUAnBIA7gkA0FbaXdkYeyIArGNcp6kEgFMCwD0BANpKuysbY08EgHWM6zSVAHBKALgnAEBbaXdlY+yJALCOcZ2mEgBOCQD3BABoK+2ubIw9EQDWMa7TVALAKQHg3pYCQK5Jnz1/c3s+PP/5/UXfQf7d+PL7d7f//Z///ebm9//c1vUi17d8B/HXb97e1mNs+P+3VrcjyflYnqQ9yUlUHXxLAsB0AsCpvF/1OVtyhADwmy9f3uT40tn/cnspqOsw1Q+vf7l59uO7246zOo61/Onr1zdf/fDu5sXby66DD+Uamrol8Pzqi5fl57SUv+kQxq5RvefW5O9S/rF6IgCsY1ynqQSAUwLAvR4DwB+evb759uX7D4dXH/OScs3527frnB/pHPPL/psXywWefK+p31rXynzu+JguUb3n1tzW42GleiQArGNcp6kEgFMCwL2eAkDab37tj4+xtda/NH/995e35/iSoxxj+ayMLuSzq2NaigAgADyZADCdAHBKALjXSwD4vHEH+JiWASC/xt+8v+w6N6d3H06jfPetbg8IAALAkwkA0wkApwSAe2sHgHQ8OUfHx7WmFgEg9+Qvvb4tKSEkEyyrY52TACAAPJkAMJ0AcEoAuLdmAMjw81r3+h+zdADIpLzxZ/Yi14slRwMEAAHgyXpKyLBHawaAzL4fH08PlgoAvQaesdR/qbkBAsBGAkCSYH4prSn3px4eEzCvtQJA2vf4WHqxRABIx/fTmz4DTyU/vn731fwjqgLARgIAsH9rBIAs8+tlwl9l7gCQTXm2OJqZH2BzjwQLAAIA0InWASD3l6dsbNPCnAEgv6K3PJKZY59zJEAAEACATrQOAJlpPj6G3swVALYQdp4idZhrYqAAIAAAnWgdALLL3fgYrpVfp9k4KKEiQ9WPyZyDTMB7yq2HuQJAb8sbp5hrNZEAIAAAnWgZADKzfI57/+n4s4HOtb9KM6Sdep+bkT9HAMjxjd93Llmzn2OM4eFG6aCHsvG/P5c5tkgWAAQAoBMtA0D2uR9//qUyHJ1OpHr/awz77z+coT81ACwxyTGTCLN1b967+syHErQyKjL3Q5TyXk/5/McIAAIA0ImWAWDqBjjpmJdanx7ZnS8BY0oAyKjEnDP+M9qRgFJ91lMk4Mx52yVBqfqcpxIABACgEy0DwNSOqNUz7vMY3qr8KeYc+s+w/lyBJ3WaazXClFEAAUAAADrRMgBM2fkvv6qr9+xJfv3P9WCf3NevPmOKBKg5QkCCXPX+TyEACABAJ1oGgClD4+lYq/fsSb7L8XFfY4nOfzBXCLh2NEYAEACATrQMAOPPvtSS9//nMMdWv5noV733nOaYjHntKIAAIAAAnWgZAKb+8pxjGdpSMoFwfLyXmnPDnU+ZI6xcs0OgACAAAJ3Yyi2AyG2AdCDVe69tjicbTl1id4kM4Y8//1LXBDIBQAAAOtEyAMyxSU1+ufZ2KyDHMz7OS7UY+h+buirjmtsAAoAAAHSiZQCYa2vcjCT0NBIwx/D/GvXJ0sDxcVwit3Sq932MACAAAJ1oGQDyWePPv1Y6n5bH/pj8eh8f3yWm7jw4xdRli5euBhAABACgEy070akX/0o6zzzsp/q8VqZOqMu2vdX7tpBnCYyP5xKXzgMQAAQAoBOtf0VPve98TibhZSi++swlTb3/n/31W838r2Ti4fiYLnHpPAABQAAAOtE6AEztcD4lv8ZTp1ad6tT7/zne6n1byfc0PqZLXLpDowAgAACdWOM++hxL5j4lcwRybz4dTnUMc8mufePPvsQas//Hpt7CqN7zHAFAAAA6sUYAyAYycz8u9zF5LO5Sa+ynrmxY4/sfm1qHS0ZbBAABAOjEWh3QHNvRXmqJCYMJF+PPucQ1u+nNbeoTDC8ZZREABACgE2v+Ap1rX4BLZeLaXB3v1M2Nlr5F8RQ5B8bHdYlLRlcEAAEA6MTaQ9BrhYDIEripkwWn3j//zZfr72o4dSLjJaMqAoAAAHSih3vQn0+cSDdFHsAzZX7A1OcbVO/ZWjrw8XFd4pJzSAAQAIBO9BAAIp3w1F3prpUJidd+D+P3ulT1nq1NfTCQAHCZ23o8rBTAGnoJAJFNdda8JZAlfdVxPWb8Hpeq3rO1qZ2yAHCZ23o8rBTAGnoKAIOMBrTYK6Dy7MfL1uWP//tLVe/ZWr7v8XFdIg8Vqt63IgAIAEAnegwAg+yRP3WS3TWyRLE6nsrU2xbpEKv3bWnqHACTAC9zW4+HlQJYQ88BYJBZ6i2DQOYEPHViYCYRjv/7S/SwD0CC1vi4LnFJiBEABACgE1sIAIMMNS/1MKGxp+7RP3UfgLk3JrpGzoHxcV3ikqWMAoAAAHRiSwFgkE4ke+hnv/+HdZnbU54uOHUnwEtuNyxl6iOBq/c8RwAQAIBObDEADLJqINvYLrV88CmjAAki4//uEln1UL1vS1NGMfLdV+95jgAgAACd2HIAGCQIZAnfEg8Y+tQ9+qlPA3zqrYYlTRlJufT4BQABAOjEHgLAIPei554jkF0Kq88aTN1GN6ZuRzzF1E2ALn2csQAgAACd2FMAGGRW+1yjARkerz5jkNGH8X9zqRxv9d4tTH0S4FPmSTwkAAgAQCf2GAAiy/jmmCSYIFG9/0NTNy36VMhY0tTllQlA1fueIwAIAEAn9hoAIkvs5hgJ+NQyt6nzACJD8dV7L2nqDoDXzF8QAAQAoBN7DgAxdZZ+fKpznrqTXlx6L30O2fZ4fByXuOaYBQABAOjE3gNAfr1PHQX41H3uTOKbY6Sh5ShAPmvp76UiAAgAQCf2HgBi6jP7nzJJb+qGQNFySeDUeQtZ/3/N6gUBQAAAOtEyAKy13K3Fdr1Tl9MNMiu/ev85ZffB8ede6trjFAAEAKATLQNAOtJvX76/XTpX/f9LafXEvjn2IMiw/CWP171U3nvq0P+1v/5DABAAgE60DgD5zHQgS3ZyD2Unv6Gu13pqZzfXKMBSISD37OeYqzBllEIAEACATqwRAAZ5CM3StwWmrgLIXgLV+54z106E6ajn/NtkR8PxZ1wjxzXlbyYACABAJ9YMAJHRgKyjX+K2wBwz3TNZrnrvc+YaBRjklsmnnkfwmPy3Uyf8PTR1uaIAIAAAnVg7AAzSUadzeer99k/JzP05dgJMOKne/zFzrAh4KN9N1uzn+6s+byy/0DPcnycNjt9rihdvr7/3PxAABACgE70EgIeyHC5hIJ34p3bheyidS2a4T93e9qFrfn2nk0xnOX6vOWTEJKMCCSaRuQKpc/53bqlMXfFwTkLIlJGIwdQAsLQsGa2Oe075nPLDAVrqMQCMpTNNx5Zf1kPH91A6xKkz/StTOoN0llNvP/RkrvNEABAAgE5sIQCsJb+oq3o8VYbhx++5RbmVUNXvGgKAAAB0QgCozXG/O6auQljbXN/DQAAQAIBOCACnMnSf2fxVHS6VznOupYGtpTNMh13V61oCgAAAdEIAOLXEdryZqzD+nJ7NGYIeEgAEAKATAsDH0lFXxz6HrGrY0sTArKaYe38GAUAAADohANzJngHXPN72UvlVnU5m/Pm9mjsECAACANAJAeBuotsca9yfKnsbbGlewJwhQAAQAIBOHDkAZO+A3O+fc5b7Jf7w7PViG/fMLR1jOu+qHpcQAAQAoBMtA0Dkl3a2tZ1jm95r5bNzr7/1Y4nPyW5+c+5euJQ5QoAAIAAAnWgdAAb51Z3PzlD4Erv4jaWDzcY+rR5DfI3h++h5ouDUECAACABAJ9YKAJXcG89tgkzGyy/07ECXIfJLRgsSJvLfZAOePAI373fJ8wR6keNOYOlxZCDf8bVLBDPqkr9tr5ZYAjqW77D8YgFa6ikAUBuCUUYvho4qt1ESdMYSmoZ/J//+MLlx7icDJpQtsU/AEeT7K79UgJYEgOMQAvqQ7678QgFaEgCOZYkQkNGJ6rOo5Xsrv0yAlgSA45l7D4JMWux5cmVv8p2VXyRASwLA8WQFxrcvhYC15Psqv0SAlgSAY1oqBLTYTnnr8l2VXyBASwLAcS0RAsI59bh8R+UXB9CSi/WxJQQssdeA8+q8fD/llwbQkgs12ZxHCGgn3035hQG05CINbaXdlY0RoCUBANpKuysbI0BLAgC0lXZXNkaAlgQAaCvtrmyMAC0JANBW2l3ZGAFaEgCgrbS7sjECtCQAQFtpd2VjBGhJAIC20u7KxgjQkgAAbaXdlY0RoCUBANpKuysbI0BLAgC0lXZXNkaAlgQAaCvtrmyMAC0JANBW2l3ZGAFaEgCgrbS7sjECtCQAQFtpd2VjBGhJAIC20u7KxgjQkgAAbaXdlY0RoCUBANpKuysbI0BLAgC0lXZXNkaAlgQAaCvtrmyMAC0JANBW2l3ZGAFaEgCgrbS7sjECtCQAQFtpd2VjBGhJAIC20u7KxgjQkgAAbaXdlY0RoCUBANpKuysbI0BLAgC0lXZXNkaAlgQAaCvtrmyMAC0JANBW2l3ZGAFaEgCgrbS7sjECtCQAQFtpd2VjBGhJAIC20u7KxgjQkgAAbaXdlY0RoCUBANpKuysbI0BLAgC0lXZXNkaAlgQAaCvtrmyMAC0JANBW2l3ZGAFaEgCgrbS7sjECtCQAQFtpd2VjBGhJAIC20u7KxgjQkgAAbaXdlY0RoCUBANpKuysbI0BLAgC0lXZXNkaAlgQAaCvtrmyMAC0JANBW2l3ZGAFaEgCgrbS7sjECtCQAQFtpd2VjBGhJAIC20u7KxgjQ0t++fVtepIBlpN2VjRGgpa9+eFdepID5/fYfrz40OwEA6MC3L9+XFypgfn/81+sPzU4AADrw4u1/ywsVML+/fvP2Q7MTAIBOZFiyulgB83r247sPTU4AADrx5ffmAcDSfvPly5tf/vuhxX1oc2VDBGjtzfv/3vzqi5flRQuYR1bcDG3upBECrOWz5/YDgCUlaA/t7aQBAqzl1TujALCUYfLf4KPGB7C2r3+yJBDm9ruvXv3v3v/go4YH0IM//9utAJhLRtV+eP3Lh6b1cTv76B8AevDuw7XKskCYxxfffTz0PzgpAOhB5gMIATBNHrQ1bluDshCgB0IAXO+xzj/KQoBeCAFwuU91/lEWAvQkISCzmKsLHfCx8XK/c8pCgN5kCVN+1VQXPODFza///vLm+c/vPzSXug2NlYUAvco+ATYLgo/94dnrmzxVc9xeHlMWAvQsFzq3BOBO9vcfb/LzFGUhQO9ywcsTBI0GcFQJwd++fPqQ/1hZCLAVmSD4p69flxdI2KOE3oTfa371P1QWAmxNfgnlWefVBRP2IttkP3yi3xRlIcAW5RfRVz+8EwTYnd//c9pwf6UsBNgyQYC9+OO/Xs/e8Q/KQoA9EATYqsxr+f7V6RP85lQWAuxJgkD2D8ha6epiC7347Pmbm5/eLNvxD8pCgL3KHgLZKjW7plUXYGgtz7rIrP65Jvc9VVkIsHdGBVhbfu0vdX//KcpCgCPJqMAX3721uyCLy2z+zEtp/Wu/UhYCHJUwwNwyypROP5tWjc+3NZWFANyHAbcJuFSW7z37sY9f+ueUhQB87N0vN7ePWs0jiTNpq7roc1w5JzK5NOdIzpWH506vykIAHpfRgQzrZr22BxIdT/7m2ZY3v/JzLozPjy0oCwG4zA+vf7kNBOkUbDy0P/mb5m+b5Xr5W4///ltUFgIwTSZ8ZZlhhoUz87vqVOhX5n3kOfsZ0u9t8t5cykIA5petXTNknI4lk8TcOlhfNoTK3yJ/k/xtlt5+tydlIQBtZJZ4Op2sNsjGMILBcvKrPpM4813nO+95hn4LZSEA68pOhemkvnnx/rbDyq2EhAPzC84bfs0nSOU7yy0YHf15ZSEAfcvM83Ruw+jBw5AQe3vWQYLPULcM16e+mZA3fAfj74dPKwsB2I/MWh86ykjHOYSGGDrWytx7HmQY/uH7D0Pyg4edeozrwnzKQgBg38pCAGDfykIAYN/KQgBg38pCAGDfykIAYN/KQgBg38pCAGDPbv7v/wEdeAwhD83PCgAAAABJRU5ErkJggg==Azure SQL Data Warehouse DatabaseGE.DSParallelLinesfalseAnyAnyfalsefalseSelectAllow access from all networksAllow access from AzureAllow access from selected networksAzure MySQL DB Firewall SettingsVirtualDynamic9afccb81-bc8b-4527-ad05-f90ec3e396cbListfalseSelectTrueFalseAzure MySQL DB TLS EnforcedVirtualDynamic4d3b2548-8c31-460e-88e5-4c26135003acListFully managed, enterprise-ready community MySQL database as a service for app development and deploymentfalseSE.DS.TMCore.AzureMySQLDBLower right of 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Azure Database for MySQLGE.DSParallelLinesfalseAnyAnyfalsefalseSelectAllow access from all networksAllow access from AzureAllow access from selected networksAzure Postgres DB Firewall SettingsVirtualDynamicba682010-cfcf-4916-9f88-524f8d9ce8a8ListfalseSelectTrueFalseAzure Postgres DB TLS EnforcedVirtualDynamic65a8827c-6efd-4243-aa81-0625c4aea98eListFully managed, enterprise-ready community PostgreSQL database as a service for app development and deploymentfalseSE.DS.TMCore.AzurePostgresDBLower right of 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SsGYFsa/ocTAAQAAeBCf3787FUmGo3HFVhGZvVnpU528qyuSU4jAAgAAsCVZKbx59+8MDwAC8m96pOnz9/0wFXXIOcRAAQAAeDKsnIgLxrKpiPjsQbOl217s0lXdb3xcAKAACAALCi9Anli8a4BOE+25k6Q9rS/HAFAABAAViIMwIdp9NclAAgAAsAGhAF4S6O/HQFAABAANpYbX1YSZFazZYXsXbbXzmRZY/rbEwAEAAFgMr//+9veAUsL2YOsiskkvjzl25N/LgKAACAATCwrCrLJSZ6YrCrgFmSNfhqWbJRlnf7cBAABQAC4IQkEeUthbq7pIcjN9vhvCWvLsFWe8NNrld6r6rxlTgKAACAA3LjDkEFuwuYQsLRMXP3i3y/ezFvRpX/bBAABQADYmUwqTC/Bp1+9DQVWGvAQh678DD99/OT5m3OqOt+4XQKAACAANJHx2EzEevT1izcXvi2LOcjM/CzHy9BSZud7su9BABAABIDGDr0FCQaHeQUmG+5TAl9u+Flumr91JpeapNebACAACACUfvPobTjI/II0GLlZuGHM7dDIH57mM06fv2Emj1Z/Y3pzPQsAAgAPksmHx70HGSs+hASrE64vEzxzbNNLk+Md6a7P30CXPQ8hAAgAAgCL+d3nb0NCZCLZoeFKN/QhLOT8G8/JLjLccjgOmZtxOD7pnj8cN1vkshQBQAAQAJjGYdjh2HFwODhMZPyQawaL44a6cuhyHx035AfV74Yt5Nwdz/VuysJOBACAfgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABACAhgQAAUAAAGhIABAABICN/ObRD6/+8I+f/ufPj5+9+uyr5/f69LXjf/frv/5Qfj6/9H+fvTvm9x3v4+P8u89/LD8PbpkAIAAIAAtLQ/+nfz579ejrF4tecM9e/ufN53/x7xf/a7y6hoNDQ5+G/Mn3L6923HOtHI7xX/71TDDgpgkAAoAAcGW///uPbxrgNDw5tuPxXtuL19d4LvQEkASRvYaC/LbPv3nx6puf1r2p5fg+/eHlq0+ePn/127/dfiAYf9+aqvqwHAFAABAAriBP+Wn0v3++fYN/im+f/fymsUyjmafl6jfdgtT/y29fvkojfPz7tpRje8thYPw9a6rqw3IEAAFAAHigNJwZR87T33hMb8nPrzNLGtHqN84oDetsjf5dcoNNSKl+x6zG37Cmqj4sRwAQAASAM6ULPU/Pt9AAneoWzoEMrTz+7jbDVo7vx0+e30Rvy1j3NVX1YTkCgAAgAJwhE78y2W48hrdu5nPgoy9+2s2NKudOgkD1O2cx1nlNVX1YjgAgAAgAJ8hs7z1fLDOeA5lXka7+sa57kHkCWaVQ/e6tjXVdU1UfliMACAACwAekyzZLyTJOfnzM9ma2cyCT6PY0xHKXDGnMtipjrOOaqvqwHAFAABAA7pDJZrcyq/9Ss5wD6WnJ0/FYvz3LsECGOarjsYWxfmuq6sNyBAABQAAopPHPcRmP1V7NcA5kRUWHp/67ZBlpdVzWNtZrTVV9WI4AIAAIAINujX9seQ5kmCU764116iibR229UmCs05qq+rAcAUAAEACOdGz8Y6tzIOPf3br875OdDLecFzDWZ01VfViOACAACAD/1bXxjy3OAY3/3XJctgoBY13WVNWH5QgAAoAA8F9r7yE/k7XPAY3//fI3SSitjt+SxnqsqaoPyxEABAAB4LUsOxuPSydrngNZ36/xP01WoazdEzDWYU1VfViOACAAtA8Aecra+zr/+6x1DmSCm8b/POmZWnNi4Pj9a6rqw3IEAAGgfQBwEax3Dtz6i5O2ktUB1fFcwvjda6rqw3Lc+wSA1gEge/uPx6OjNc4BS/0u8+jrF+Vxvbbxe9dU1YflCAACQNsAkLHVzhvPHFv6HOg+x+Ja1nh/wPida6rqw3IEAAGgbQDw9P/OkudAtrntPsfiWrJt8NKTAsfvXFNVH5YjAAgAbQOA8eh3ljoHMnktnz1+Hw+39HyA8fvWVNWH5QgAAkDLAJClaONx6Gypc2Cvr/Pd2p/++aw83tcwfteaqvqwHAFAAGgZAD5+Mu+YdP4euTDzpJdXEY8+/+bFm/9+zTcVLnEOpJEav4fryFDAUksDx+9aU1UfliMACAAtA8Bsu/6lMc/b4NIzUdX3Q37/9x/fTLJLYEjDMH72Ka59DqRxemhdOM1Sbw8cv2dNVX1YjgAgALQLANn4ZzwGW0nDf+13weed+unhePzdy5NXOVz7HDDrf3mZWPmQwHif8XvWVNWH5QgAAkC7AJD3zo/HYAu5+Jae0Z0n8fze+yY8XvMcSKN0a7P+87c4GP/bzDIcVP0NLjF+x5qq+rAcAUAAaBcActMcj8HacszX3uM9DXO6jfPdVX2qf/MQs2/4kzCUUHRfz0vW3Kcnozpes1iiF2D8jjVV9WE5AoAA0C4AzLD8Lw1LVbe1/PHLn967+K91Dsz69J/5CNlJ76Fv10tgmPUdBtfeIXD8/DVV9WE5AoAA0C4AzPBEt8VrXiuZQJhAdK1zII3R+Fu3lgmf13pKnqH3aHTtFQHj56+pqg/LEQAEgHYBYIbtf6t6bSlBoCo/x4wz/9NgX3u5XHaQnK2X45o9SuNnr6mqD8sRAASAdgFg/P1buPa47Qxm21shDXVVz2uYbXvjrCap6vkQ42evqaoPyxEABAABYAMZg6/qdstmGiNfao38sdneJZHln1U9zzV+7pqq+rAcAUAAEAA2sOb73deQxmf8jVvJKoSqjkuYaavj7BJZ1fFc4+euqaoPyxEABAABYCNrPKWuJY3P+Pu2kBtaVb+lZH7BNbdkvkQmO1Z1PNf4uWuq6sNyBAABoF0AyO8dj8FWsrysquOtmaURvMZkxnPN9M6Da6wuGT9zTVV9WI4AIAC0CwCzNFaRiWRb7wlwqVm6/7ccVpll/sM1zqXxM9dU1YflCAACQLsAMONJn7X4Wzy9XsMs3f9bHr9ZegEyJ6Gq3znGz1xTVR+WIwAIAO0CwIybuRzkKfZas7nXMsNNJC8+quq2phl6lq6xHHD8zDVV9WE5AoAA0C4AzLZ8q5IgcAs9ApkEN8N6+DyBV/Vb0yw9IZe+Y2L8vDVV9WE5AoAA0C4AzPQ64PscXlxT/Y4ZJKSMdV5bAsi1d/t7iBmORVy6x8T4eWuq6sNyBAABoF0AiPzm8TjMLFvsZtngbDsIZtLZWNe1JSRVddvCDOfVpctLx89bU1UfliMACAAtA8Dsr6y9S552M9FrluGBjL2PdVzbTKsoZjivLp0IOH7emqr6sBwBQABoGQBm6a69RDZ+2Xp4YIaJbzNNmpxhNUBu6lXdTjV+3pqq+rAcAUAAaBkAYtb3u58rf78lX3zzIVtPAMz3V/XaSoZoxjqu7dKVAOPnramqD8sRAASAtgFgtrfXXWrtIDBDY5cQV9VtS1u/bvrSUDR+3pqq+rAcAUAAaBsAMnN865v1EtYKAnkl7vjda5th/f8oQzNjPdd2yWTR8bPWVNWH5QgAAkDbABB76wU4loZoyfHxGca7Z3yh0gwTARPOqrqdYvysNVX1YTkCgADQOgDEDE9sS0l38FKN5AxLALea+/AhOd5jPdf2h38IANxPABAA2geAPawIuM8SvQEz7Hw3ww6Aoxl2mhQAOIUAIAC0DwDx6Ovb3BfgHOkNuOYT8wzvVLikoVvKDAHgkuWh42etqaoPyxEABAAB4L+y//54bPYoYaf6/efKhjPjZ69txgCQrXjHeq7tkqA3ftaaqvqwHAFAABAA/iurArKt7Hh89iiz5y/dP3+GADDjmxMTSsZ6rk0A4BQCgAAgABzJm9T2skHQfXLxX/LmuBl6TPJip6puWxIAHq6qD8sRAAQAAWDQLQQ8tCdghpuHHoCaAMApBAABQAAopFGc4UU3a3joZjoz3DzMAahd8krg8bPWVNWH5QgAAoAA8AEzLHVbw0MmBs4QkC599/0SZlgFcEkwGj9rTVV9WI4AIAAIAPfIWvOtX3qzhuyKWP3+u8wwCfCSru6lzLC75CWvix4/a01VfViOACAACAAnyGSzva8QSMg5Zw95AaA2Q6/RJZMjx89aU1UfliMACAACwBnS5fzs5ZvugPJY3rrsY1/97soMDV3qUNVtSzNskHTJ6o7xs9ZU1YflCAACgABwpkwQ3PPOgad2H88QANLYVnXb0gxzI6p6nWr8rDVV9WE5AoAAIAA8ULpZ88S8t/kBWd9f/d7RDJPd8o6Dqm5byvU01nNNOR+rep1q/Lw1VfVhOQKAACAAXCjdrXkD3NY3/ms6pRdghvXulzZ215ZzYazj2i4NRePnramqD8sRAAQAAeCK8hKWPbxe+JRlgekBGf/dFi6Z8X5tWTEy1m9tlw6LjJ+3pqo+LEcAEAAEgAVkh7rciG91wuCp58T477Yw00qAGeZFXPImwBg/b01VfViOACAACAALyw35FpcQfvTF/ZvJzDDscc7KhaXN8He+dHvk8fPWVNWH5QgAAoAAsJJ0madX4FYmDZ4yDDDDC4HSy3Lpmw2vIXsobP23ffH6fl7V7RzjZ66pqg/LEQAEAAFgZWkoZthE5z6nnBefPN2+yzsu7fa+hkwEHeu1ttzQq7qdY/zMNVX1YTkCgAAgAGwkPQKzB4Gq3sdmWAkQ6Xqv6remGYZDHvJOh9H4mWuq6sNyBAABQADYWMbaZ50seN+Wsul6n2VI4766LmmGNwBGViFU9TvH+JlrqurDcgQAAUAAmECGBb59Nt/FeMoSu1nqveWugDPcSBPErjEXYvzcNVX1YTkCgAAgAEwiIWCGbuRjp7xud4albwdb7Akww9v/IsNJVf3ONX7umqr6sBwBQAAQACaSBmz8+2zplDX2WXY2/rutpDdizRUB+e2zDIGcEtZOMX7umqr6sBwBQABoGQAye33GV8nGDEvrDk59295MwxeZjV/VcQmz7PqY5X/XCj7jZ6+pqg/LEQAEgJYB4NBtnW7TS16duoRZupQjQamq42iGJXAHeSK/1tPwh8y0guNa3f8xfvaaqvqwHAFAAGgdACIz8GfqDZhlaV2celxmeS/AwdIhYLblmzlnqno+xPjZa6rqw3IEAAGgfQA4yMUww4tlZhpTP6cRnWnoIhICrrEs7li62Wdr/BNgq7o+1Pj5a6rqw3IEAAFAABikITtlH/ylzPBGuYNzAtFsExgP8ve8dH/8yN9lxv0aTh2mOdX4+Wuq6sNyBAABQAC4Qy6ONcaSRzONp587sWzGvQwOsk/AQ4JAutdnfZnTEu9BGL9jTVV9WI4AIAAIAPdIo7bWXvO5mefvMdZhC98/P/+8mKn34i75Xfn7p2GvAkHmM+S/3cLrnK89xBHjd6ypqg/LEQAEAAHgRDlOefXsEjfdSOM/05Nmus6ret5n5l6APclxro7/pcbvWVOuy1lsubX0WgQAAUAAeIBMMEsDmSV72cGv+o5z5DNmWVN+8ND19Jk/MX4W17fU8NT4PV1dc2XFrAQAAUAAuII8jeVNbOkdOCcQ5CaeWeWz7CZ37JIVEY+/m3PMfC8e2jtzivG7uhIAeigLOxEAri9jx7m4IsHg0K0Y6eaf7Wl/dOnSsoSgGUPNHuS4XmNVw13G7+tKAOihLOxEAGB0jZ3lZlrNsCfXXvY3Gr+vKwGgh7KwEwGA0bU2REpX9fjZPFx6j6rjfE3jd3YlAPRQFnYiAHDsmuPLWdmQZXfjd3C+DMtcY8Lpfcbv7UoA6KEs7EQA4Ni1Z5dnOVXeVnf8HZxvqeWno/F7uxIAeigLOxEAOMjkxOp4XeoWNgia2TXf9nef8bu7EgB6KAs7EQCIzC5f8mVIjvnDZNz/2tv9fsj4/V0JAD2UhZ0IAES2vq2O1TWZFHie3KDXbPxjrENXAkAPZWEnAgBLvFSm8uu/mhR4qmwuleNVHccljfXoSgDooSzsRADobemu/1EatVnfrjeLrRr/GOvSlQDQQ1nYiQDQVxr/LV55HBlyGOvDto1/jPXpSgDooSzsRADo6y//Wmdp2V3yMqWxTp1ljsSWjX+MdepKAOihLOxEAOhp68b/IDfa7vsEpCdm6S1+TzXWrSsBoIeysBMBoJc0tlt1+98lL7fJeTjWtYP87rxCuTouWxjr15UA0ENZ2IkA0Edm+6854e8c6frutkxwhi7/0VjHrgSAHsrCTgSAHjLzPtvyVsdjJrnxZiLcWP89yTX358dzDMGMxrp2JQD0UBZ2IgDsW57619pH/prSQKbu4++5ZRl+yVj/2pv7nGOsc1cCQA9lYScCwD5lYtmjr19M3djcJ3X/9PXf6tYnCR7+FrN191fGunclAPRQFnbSMQDkRpwlaHvclS5PzWlsbqG7/1R5De4t7xuQc636XTMa696VANBDWdhJxwBwLJPi0rjkOIzH5pbkTX5Z2nfLT/z3SahJF/otzhGYZZnffcZ6dyUA9FAWdtI9ABxLGEiXcxrT8TjNKBdwhjOyjK76PXt2i2Hgi3/PPyQz1rkrAaCHsrATAaCWG3VuAgkEWa41Qw9Bgkm697OOf89P+ue6pTCQm+7McwFSP36edrnsNeV3judnN2VhJwLA6Q6hII1NnryztC4XUSZ5HR/TS6UhS+jId2Q2/Ewbxcwu8wUOf6OEpfx9ZltNkLkne5qjwW0SAAQAAeDKcmNPA3SQHoQ05JU8yR//fzs8dWwpxziBKsHg2qHtXFnZINixJQFAABAAaCl7I4zXwtoSQmbdEIj9EwAEAAGAtrJqYrwetpBeoqp+sCQBQAAQAGgtje94TWzhy29fmtjJqgQAAUAAoL3Mxxiviy3khnwLuwWyDwKAACAAwGt5Ah+vjS1khUDHfR1YnwAgAAgA8F+Pv5sjBGSFQFYsVHWEaxEABAABAP4rY/DZ22G8RraQFQKZpFjVE65BABAABAA4khAw01bQ2bOgqidcSgAQAAQAGGQi3kzbCmdowgoBrk0AEAAEACgkBOTaGK+XraRXwgoBrkkAEAAEALhDtnWeKQSkLlYIcC0CgAAgAMAHpMHNrPzja2ZLVghwLQKAACAAwD3ykqaZQkB8/MT2wVxGABAABAA4Qd7cuPUbBEeff2OFAA8nAAgAAgCcKCFgvH629uR7KwR4GAFAABAA4AyzvEHwWJYs/uaREMB5BAABQACAM33ydI6XBx3LdZy5ClV9oSIACAACADzALG8QPJaJihmmqOoLIwFAABAA4IG++PeL15dQfV1tyQoBTiEACAACAFxgltcIj6wQ4D4CgAAgAMCFZnmD4Cj1sn0wdxEABAABAC4002uER1khkC2Nq3rTmwAgAAgAcAWzvUHw2LOXVgjwSwKAACAAwJUkBGRjntxYZ5MeCj0BHMt5MbYH3ZSFnQgAAP0IAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAAgAAA0JAAKAAADQkAAgAPzq5/+8/p/i5ABgvwQAAeCN6uQAYL8EAAHgjd/+7cfyBAFgn775SQAoC7v56IufyhMEgH3K/K+xLeimLOzmk6fPyxMEgH169lIAKAu7+fLbl+UJAsD+/ObRD69v/XV70ElZ2M23z34uTxIA9udP/3z2+tZftwedlIUdmQgI0MNnXz1/fduv24JOysKOPn19QlQnCgD7YgngW2VhR1kSUp0oAOzHr//6w6tsAHd8/++qLOwqE0OqEwaAffjLv4z/H5SFXX3+zYvyhAFgH57+8PL17b5uA7opC7tKt5BeAIB9yv1d9/87ZWFnegEA9in39/Ge31lZ2JleAID98fT/S2Vhd4+/szMgwJ54+v+lspBXv/rDP7wgCGAPfvf5j57+C2Uhb7cH/r/PDAUA3Doz/2tlIW+ZEAhw2+z7f7eykHdy8lQnFQBzy8Q/r/29W1nIOzl5rAoAuD32/P+wspD35T0B5gMA3A5v/LtfWcgvPfne0kCAW5BVXOM9nF8qC6mZFAgwt9/+7cdXL970/Nf3cd4pC7nbJ0+flycdANvKq35/fGHS36nKQj4sr5OsTj4AtpF5WpmvNd6vuVtZyP2EAIA5pPG32c/5ykJOIwQAbEvj/3BlIaczJwBgGxr/y5SFnOeLf1sdALCmTPiz0c9lykLOlxRqsyCA5WWp3/fPzfa/VFnIw+QNgjkxqxMWgMv9/u/W+V9LWcjD5cTMLlTViQvAw+XlbN7rfz1lIZczORDgOjK8mp1Yx/sslykLuY7H3718M1GlOqEBuF+GVW3ws4yykOvJtpQffWFIAOBc6fI33r+cspDre/T1C6sEAE6Qe2WWV4/3Ua6rLGQZWbaSGazVCQ/A9296TC3xW0dZyLL0BgD80qdfPX99i6zvm1xfWcjyknD/+KW5AQB56jfRb31lIev58lsrBYCecu8z1r+dspB1ZZZr9g0wLAB08fGT52b4b6wsZBtZMvjnx14xDOxXdkrNtunj/Y/1lYVsKxeH7YSBPckKKG/vm0tZyBzyhkHLBoFblp38nnzvnf0zKguZSyYK/uaR+QHA7cg9ywS/uZWFzCdvwMr+AVYMADPLPSr3Km/tm19ZyLwyazZvxdIjAMwkq5iykY+Z/bejLOQ2ZGjAHAFgS3kYyRP/s5e27701ZSG3JTNr7SoIrCm79+UhZLwfcTvKQm5Tthf+y7+e2VAIWEz2KrFt7z6Uhdy2dMVlLM6EQeAaci/JPUU3/76UhexDZuFmGc7vPjdPADhf7h3p5jejf5/KQvYnuwtm7229AsCHZAgx3fzZiGy8j7AvZSH79vi7l6/+9E/vHADeyfbjedq3jK+PspAeMp6XPQUMEUBP2ab3s6+ev8qLyMb7A/tXFtKPIQLoIdd4rnUz+SkL6c0QAexPrulc2yb0cVAWQuRGkRtG9hbQMwC3JxuEZSWQ5XtUykKoZMfBdB1m3LC62QDbSlBPYE9wN5mP+5SFcJ/MGcjkIe8igG1lEu8nT43pc76yEM6RGcRZTZBlRNUNCriudO3nmjN7n0uUhfBQ6XZM92OGCiwvhOvIG/d07XNtZSFcSyYfZXOR3LzMHYDTpMHPbnyZwJeXfI3XFVxDWQhLSZelQADvy7WQayLXhgaftZSFsJYEgjzl5GknTz3VzRH25rjBN47PVspC2EqefnJTzKzmj74wqZB9yLmceTEZw7cmn1mUhTCTLG9KL0GemCw7ZHZZDZMAm3PW0jxmVhbC7LIpUZZBZejAagO2kNfmprH/9Kvnb3qtsjfGeJ7CzMpCuDXZtjihIJsTZc9zPQVcU3bYS2Of8yvd+CbqsQdlIexFbtSHYJAhhNzE8+RW3eQhY/XZZCfnS57qc+54eQ57VRbC3mUzldzcM06bLtwEA8sSe8jf+dB1/+jrF2/OAzPx6agshM4ycevJ9y/fPAUewoGeg9txGJuPTMbL3/HpD8boYVQWAnc7DCscQkIcGhyvTV5WJnzmOGeex+HYp3H3FA/nKwuBy2StdxqlNE6HhirScB3CQnTvVTh0xx9knsbhWGV4JscwxuMLXK4sBNZ3WMlwkNnmx+EhSx6PG8vKkqsfMkGu+s5jxw14HCbSHXhKh3mUhQDAnr361f8DYnNath4YI+YAAAAASUVORK5CYII=Azure Database for PostgreSQLGE.DSParallelLinesfalseAnyAnyfalseBrowserfalseSE.EI.TMCore.BrowserLower right of stenciliVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAABcRgAAXEYBFJRDQQAADu1JREFUeF7t1iGun8cVxuEsobAL6EK6hGyhCygILPACDAILCrKBwIJCAwODgsDAgoCCbsK9MyBTWa/0Kc34+OacBzwB70gz+kufb35fffz4EQAYJo4AQG9xBAB6iyMA0FscAYDe4ggA9BZHAKC3OAIAvcURAOgtjgBAb3EEAHqLIwDQWxwBgN7iCAD0FkcAoLc4AgC9xREA6C2OAEBvcQQAeosjANBbHAGA3uIIAPQWRwCgtzgCAL3FEQDoLY4AQG9xBAB6iyMA0FscAYDe4ggA9BZHAKC3OAIAvcURAOgtjgBAb3EEAHqLIwDQWxwBgN7iCAD0FkcAoLc4AgC9xREA6C2OAEBvcQQAeosjANBbHAGA3uIIAPQWRwCgtzgCAL3FEQDoLY4AQG9xBAB6iyMA0FscAYDe4ggA9BZHAKC3OAIAvcURAOgtjgBAb3EEAHqLIwDQWxwBgN7iCAD0FkcAoLc4AgC9xREA6C2OAEBvcQQAeosjANBbHAGA3uIIAPQWRwCgtzgCAL3FEQDoLY4AQG9xBAB6iyMA0FscAYDe4ggA9BZHAKC3OAIAvcURAOgtjgBAb3EEAHqLIwDQ2/7P7/7w148AwAw/B8BXv//2IwAwgwAAgIEEAAAMJAAAYCABAAADCQAAGEgAAMBAAgAABhIAADCQAACAgQQAAAwkAABgIAEAAAMJAAAYSAAAwEACAAAGEgAAMJAAAICBBAAADCQAAGAgAQAAAwkAABhIAADAQAIAAAYSAAAwkAAAgIEEAAAMJAAAYCABAAADCQAAGEgAAMBAAgAABhIAADCQAACAgQQAAAwkAABgIAEAAAMJAAAYSAAAwEACAAAGEgAAMJAAAICBBAAADCQAAGAgAQAAAwkAABhIAADAQAIAAAYSAAAwkAAAgIEEAAAMJAAAYCABAAADCQAAGEgAAMBAAgAABhIAADCQAACAgQQAAAwkAABgIAEAAAMJAAAYSAAAwEACAAAGEgAAMJAAAICBBAAADCQAAGAgAQAAAwkAABhIAADAQAIAAAYSAAAwkAAAgIEEAAAMJAAAYCABAAADffYA+PZvP+xHAIBf5v0//x3/33rDun8/kg5vEAAA8P8RAAAwkAAAgIEEAAAMJAAAYCABAAADCQAAGEgAAMBAAgAABhIAADCQAACAgQQAAAwkAABgIAEAAAMJAAAYSAAAwEACAAAGEgAAMJAAAICBBAAADCQAAGAgAQAAAwkAABhIAADAQAIAAAYSAAAwkAAAgIEEAAAMJAAAYCABAAADCQAAGEgAAMBAAgAABhIAADCQAACAgQQAAAwkAABgIAEAAAMJAAAYSAAAwEACAAAGEgAAMJAAAICBBEChf7z718c/fv09fHbfvHn/8snl77CD9fvS74Yv6bvvf3z5PPM3+xoJgELr40i/A25bf4w+/f46Wb8v/W74kt68/fDyeeZv9jUSAIUEAFUEANQTAMe6fz+SDm8QAJAJAKgnAI51/34kHd4gACATAFBPABzr/v1IOrxBAEAmAKCeADjW/fuRdHiDAIBMAEA9AXCs+/cj6fAGAQCZAIB6AuBY9+9H0uENAgAyAQD1BMCx7t+PpMMbBABkAgDqCYBj3b8fSYc3CADIBADUEwDHun8/kg5vEACQCQCoJwCOdf9+JB3eIAAgEwBQTwAc6/79SDq8QQBAJgCgngA41v37kXR4gwCATABAPQFwrPv3I+nwBgEAmQCAegLgWPfvR9LhDQIAMgEA9QTAse7fj6TDGwQAZAIA6gmAY92/H0mHNwgAyAQA1BMAx7p/P5IObxAAkAkAqCcAjnX/fiQd3iAAIBMAUE8AHOv+/Ug6vEEAQCYAoJ4AONb9+5F0eIMAgKx7AKx/S+uPLbwm7z789PJ55m/2NRIAhQQAVboHAPDrCYBCAoAqAgB4IgAKCQCqCADgiQAoJACoIgCAJwKgkACgigAAngiAQgKAKgIAeCIACgkAqggA4IkAKCQAqCIAgCcCoJAAoIoAAJ4IgEICgCoCAHgiAAoJAKoIAOCJACgkAKgiAIAnAqCQAKCKAACeCIBCAoAqAgB4IgAKCQCqCADgiQAoJACoIgCAJwKgkACgigAAngiAQgKAKgIAeCIACgkAqggA4IkAKCQAqCIAgCcCoJAAoIoAAJ4IgEICgCrdA2D9W3rz9gO8Ku8+/PTyeeZv9jUSAIUEAFW6B8D6fel3w5e0IuDTb/U1EwCFBABVBADUEwDHun8/kg5vEACQCQCoJwCOdf9+JB3eIAAgEwBQTwAc6/79SDq8QQBAJgCgngA41v37kXR4gwCATABAPQFwrPv3I+nwBgEAmQCAegLgWPfvR9LhDQIAMgEA9QTAse7fj6TDGwQAZAIA6gmAY92/H0mHNwgAyAQA1BMAx7p/P5IObxAAkAkAqCcAjnX/fiQd3iAAIBMAUE8AHOv+/Ug6vEEAQCYAoJ4AONb9+5F0eIMAgEwAQD0BcKz79yPp8AYBAJkAgHoC4Fj370fS4Q0CADIBAPUEwLHu34+kwxsEAGQCAOoJgGPdvx9JhzcIAMgEANQTAMe6fz+SDm8QAJAJAKgnAI51/34kHd4gACATAFBPABzr/v1IOrxBAEAmAKCeADjW/fuRdHiDAICsewB88+b9/o3wmqy/8Z9+q6+ZACgkAKiy/hh9+v0B/C8BUEgAUEUAAE8EQCEBQBUBADwRAIUEAFUEAPBEABQSAFQRAMATAVBIAFBFAABPBEAhAUAVAQA8EQCFBABVBADwRAAUEgBUEQDAEwFQSABQRQAATwRAIQFAFQEAPBEAhQQAVQQA8EQAFBIAVBEAwBMBUEgAUEUAAE8EQCEBQBUBADwRAIUEAFUEAPBEABQSAFQRAMATAVBIAFBFAABPBEAhAUAVAQA8EQCFBABVBADwRAAUEgBUEQDAEwFQSABQRQAATwRAIQFAle4BsH5f+t3wJb15++Hl88zf7GskAAoJAKoIAKgnAI51/34kHd4gACATAFBPABzr/v1IOrxBAEAmAKCeADjW/fuRdHiDAIBMAEA9AXCs+/cj6fAGAQCZAIB6AuBY9+9H0uENAgAyAQD1BMCx7t+PpMMbBABkAgDqCYBj3b8fSYc3CADIBADUEwDHun8/kg5vEACQCQCoJwCOdf9+JB3eIAAgEwBQTwAc6/79SDq8QQBAJgCgngA41v37kXR4gwCATABAPQFwrPv3I+nwBgEAmQCAegLgWPfvR9LhDQIAMgEA9QTAse7fj6TDGwQAZAIA6gmAY92/H0mHNwgAyAQA1BMAx7p/P5IObxAAkAkAqCcAjnX/fiQd3iAAIBMAUE8AHOv+/Ug6vEEAQCYAoJ4AONb9+5F0eIMAgEwAQD0BcKz79yPp8AYBAJkAgHoC4Fj370fS4Q0CALLuAQD8egKgkACgigAAngiAQgKAKgIAeCIACgkAqggA4IkAKCQAqCIAgCcCoJAAoIoAAJ4IgEICgCoCAHgiAAoJAKoIAOCJACgkAKgiAIAnAqCQAKCKAACeCIBCAoAqAgB4IgAKCQCqCADgiQAoJACoIgCAJwKgkACgigAAngiAQgKAKgIAeCIACgkAqggA4IkAKCQAqCIAgCcCoJAAoIoAAJ4IgEICgCoCAHgiAAoJAKoIAOCJACgkAKgiAIAnAqCQAKCKAACeCIBCAoAq3QPgmzfv92+E12T9jf/0W33NBEAhAUCV9cfo0++vk/X70u+GL+nN2w8vn2f+Zl8jAVBIAFBFAEA9AXCs+/cj6fAGAQCZAIB6AuBY9+9H0uENAgAyAQD1BMCx7t+PpMMbBABkAgDqCYBj3b8fSYc3CADIBADUEwDHun8/kg5vEACQCQCoJwCOdf9+JB3eIAAgEwBQTwAc6/79SDq8QQBAJgCgngA41v37kXR4gwCATABAPQFwrPv3I+nwBgEAmQCAegLgWPfvR9LhDQIAMgEA9QTAse7fj6TDGwQAZAIA6gmAY92/H0mHNwgAyAQA1BMAx7p/P5IObxAAkAkAqCcAjnX/fiQd3iAAIBMAUE8AHOv+/Ug6vEEAQCYAoJ4AONb9+5F0eIMAgEwAQD0BcKz79yPp8AYBAJkAgHoC4Fj370fS4Q0CADIBAPUEwLHu34+kwxsEAGQCAOoJgGPdvx9Jhzf81gLghx//sz8Q+NxWbH76/XWyfl/63fAlvfvw08vnmb/Z10gAAMBAAgAABhIAADCQAACAgQQAAAwkAABgIAEAAAMJAAAYSAAAwEACAAAGEgAAMJAAAICBBAAADCQAAGAgAQAAAwkAABhIAADAQAIAAAYSAAAwkAAAgIEEAAAMJAAAYCABAAADCQAAGEgAAMBAAgAABhIAADCQAACAgQQAAAwkAABgIAEAAAMJAAAYSAAAwEACAAAGEgAAMJAAAICBBAAADCQAAGAgAQAAAwkAABhIAADAQAIAAAYSAAAw0G86AL7+0993BAAAv8yf//Iu/r/1hs8eAADA6yMAAGAgAQAAAwkAABhIAADAQAIAAAYSAAAwkAAAgIEEAAAMJAAAYCABAAADCQAAGEgAAMBAAgAABhIAADCQAACAgQQAAAwkAABgIAEAAAMJAAAYSAAAwEACAAAG+jkAAIBZ4ggA9BZHAKC3OAIAvcURAOgtjgBAb3EEAHqLIwDQWxwBgN7iCAD0FkcAoLc4AgC9xREA6C2OAEBvcQQAeosjANBbHAGA3uIIAPQWRwCgtzgCAL3FEQDoLY4AQG9xBAB6iyMA0FscAYDe4ggA9BZHAKC3OAIAvcURAOgtjgBAb3EEAHqLIwDQWxwBgN7iCAD0FkcAoLc4AgC9xREA6C2OAEBvcQQAeosjANBbHAGA3uIIAPQWRwCgtzgCAL3FEQDoLY4AQG9xBAB6iyMA0FscAYDe4ggA9BZHAKC3OAIAvcURAOgtjgBAb3EEAHqLIwDQWxwBgN7iCAD0FkcAoLc4AgC9xREA6C2OAEBvcQQAeosjANBbHAGA3uIIAPQWRwCgtzgCAL3FEQDoLY4AQG9xBAB6iyMA0FscAYDe4ggA9BZHAKC3OAIAvcURAOgtjgBAb3EEAHqLIwDQWxwBgN7iCAD0FkcAoLc4AgCdffzqv7BDXhYT/E+AAAAAAElFTkSuQmCCBrowserGE.EIRectanglefalseAnyAnyfalseA representation of Dynamics CRM Mobile Client ApplicationsfalseSE.EI.TMCore.DynamicsCRMMobileClientLower right of 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 CRM Mobile ClientGE.EIRectanglefalseAnyAnyfalseA representation of Dynamics CRM Outlook ClientfalseSE.EI.TMCore.DynamicsCRMOutlookClientLower right of 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Dynamics CRM Outlook ClientGE.EIRectanglefalseAnyAnyfalsefalseSelectGenericCSharpNodeJSIoT Device TechnologiesVirtualDynamic0e4c07fd-732f-44e3-901a-81446a6bcd4cListfalseSelectYesNoIP CapableVirtualDynamic5a86ce50-eedb-4cd4-9686-8619c3196d05ListfalseSelectWindows IoT CoreOtherDevice OSVirtualDynamicc654e773-cfea-4cee-b832-ed22bf619348ListfalseSelectDirect connectivityAgentsAzure IoT device SDKsDevice ConnectivityVirtualDynamic2774528e-4318-498b-9228-8341d7112a6aListfalseSelectAzure IoT HubCustomDevice Identity StoreVirtualDynamic51551b3e-c1e1-4181-b8d3-b74ad078b0beListAn IoT client agent which generates and sends telemetry data to the cloud, and receives messages from the cloudfalseSE.EI.TMCore.IoTdeviceLower right of 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IoT DeviceGE.EIRectanglefalseAnyAnyfalsefalseSelectGenericXamarinAndroidiOSWindows PhoneMobile Client TechnologiesVirtualDynamic84259115-f55a-44fc-9423-6c239e36e595ListA representation of a Mobile Client Application (Mobile App)falseSE.EI.TMCore.MobileLower right of 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QBoCADIJACgTgA0BABkEgBQJwAaAgAyCQCoEwANAQCZBADUCYCGAIBMAgDqBEBDAEAmAQB1AqAhACCTAIA6AdAQAJBJAECdAGgIAMgkAKBOADQEAGQSAFAnABoCADIJAKgTAA0BAJkEANQJgIYAgEwCAOoEQEMAQCYBAHUCoCEAIJMAgDoB0BAAkEkAQJ0AaAgAyCQAoE4ANAQAZBIAUCcAGgIAMgkAqBMADQEAmQQA1AmAhgCATAIA6gRAQwBAJgEAdQKgIQAgkwCAOgHQEACQSQBAnQBoCADIJACgTgA0BABkEgBQJwAaAgAyCQCoEwANAQCZBADUCYCGAIBMAgDqBEBDAEAmAQB1AqAhACCTAIA6AdAQAJBJAECdAGgIAMgkAKBOADQEAGQSAFAnABoCADIJAKgTAA0BAJkEANQJgIYAgEwCAOoEQEMAQCYBAHUCoCEAIJMAgDoB0BAAkEkAQJ0AaAgAyCQAoE4ANAQAZBIAUCcAGgIAMgkAqBMADQEAmQQA1AmAhgCATAIA6gRAQwBAJgEAdQKgIQAgkwCAOgHQEACQSQBAnQBoCADIJACgTgA0BABkEgBQJwAaAgAyCQCoEwANAQCZBADUCYCGAIBMAgDqBEBDAEAmAQB1AqAhACCTAIA6AdAQAJBJAECdAGgIAMgkAKBOADQEAGQSAFAnABoCADIJAKgTAA0BAJkEANQJgIYAgEwCAOoEQEMAQCYBAHUCoCEAIJMAgDoB0BAAkEkAQJ0AaAgAyCQAoE4ANAQAZBIAUCcAGgIAMgkAqBMADQEAmQQA1AmAhgCATAIA6gRAQwBAJgEAdQKgIQAgkwCAOgHQEACQSQBAnQBoCADIJACgTgA0BABkEgBQJwAaAgAyCQCoEwANAQCZBADUCYCGAIBMAgDqBEBDAEAmAQB1AqAhACCTAIA6AdAQAJBJAECdAGgIAMgkAKBOADQEAGQSAFAnABoCADIJAKgTAA0BAJkEANQJgIYAgEwCAOoEQEMAQCYBAHUCoCEAIJMAgDoB0BAAkEkAQJ0AaAgAyCQAoE4ANAQAZBIAUCcAGgIAMgkAqBMADQEAmQQA1AmAhgCATAIA6gRAQwBAJgEAdQKgIQAgkwCAOgHQEACQSQBAnQBoCADIJACgTgA0BABkEgBQJwAaAgAyCQCoEwANAQCZBADUCYCGAIBMAgDqBEBDA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 ClientGE.EIRectanglefalseAnyAnyfalseA representation of Active Directory Federation Services (ADFS) ServerfalseSE.P.TMCore.ADFSCentered on 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GFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlCgDMTQGAPmJYmQIAc1MAoI8YVqYAwNwUAOgjhpUpADA3BQD6iGFlC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ADFSGE.PEllipsefalseAnyAnyfalseAzure Active DirectoryfalseSE.P.TMCore.AzureADCentered on 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 ADGE.PEllipsefalseAnyAnyfalseA representation of Azure Data ExplorerfalseSE.P.TMCore.ADECentered on stenciliVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQ3SURBVGhD3djNa9RAGAbwnvyD9ODRox78BwQVD3oQRD14qAp6EFSoINiDXgQFQURBlFJsVbSVHsQiiq390NrP3e2XLda223a7HfsMeddJ8iaZmUyy2z7w0CWZyeZHdzPZNJ14WhBNzX117Z7L/eLQk0FxpG0os57q/CkuvZsSTWI79UTnhv0w/h+M1AOdKzYIRvJE547lwEge6Lpgo8BIlmhT7OnXI+L+t2lx9u0vdj9XFhsHRrJAm2KBnF3dkOezslEVzd1j7Di1kVg0Doy4RKfBUpLQsVg0CYy4QNt8Z8f+rHln4M/iWkUcbx8OjU/EojpgJA3aBgvQRnXLe3d/sB3fa3W8FhbVBSM2aBss9e6XkvfO/jwemPON08aiJmDEBJ0GSw2inw3P+/YbYVFTMKKDdoGl3vlcFP3zK3JpUrcbY1EbMBKHdomNqhUWtQUjHNoUi6UHV2MsPzprLBrEtn4uyfnF5XX5Wt0XahowoqJtsOo6q3NjwWHLlap3BCFfx6LTghGg02Ipcegg9nZv0YelYBv2qWNrdQFGjj0fZU8yqrjaRqVr8k9oPPed7SkseTPC+Vj6Gxov6wqMHH2hf3N/8+OUNysc3avxg74Zb0Y42MfNcQpGTNDcjYXpOst9UrCNGyvrGozYom1vKlR0LBbNAoyYoHFfjIuYuk0XS235VJDl9vmaFRgxQasNYgHpGF3UAyU1SzBiig5i1XU2cY3VqS14avGlGCy1iOrWurclOrroOCwlDbq5a1xce180B/+YuSde9e2V/TR6xgma+84ulCvebH+W1jfFlZ6J0Pi4Anvw4Yi41T1nBlaxrtAcFqDgf5dSqW6JG9vreHBOVAm7r9UQzGGpQOskiOawVG6NRRKXHqUq1ggch0W7hg57I5ND6DgsNYhOg9UG62BXNwreaL2cbBtjT5Lro++zYmihLP9y+7lyWC1wFljK+U7+ZNM2CpsIzhJLcY2Ow6KRYBfYymb0zzc1rtBJWJQFu8DSMb4Vrnpb4pMWrYNFQ2CXWGrWaF0s6gNngaVmhTbBojVwllgq7r91oos2xaISnAcWx1irRD/HCiYJbYNFJZg7QaorbNIxuEShbbGoBL8ZOGB9ollhKUF0GiwqwUvlQRFENwKWQui0WLR20VLReWGHZ+7I6uRc50RqLFoDI0DjKUYeWCxTNF53ybrQPs0iTOoD68Q1lpoX2gicFZaq+/FOg9YGZ41Fv05e9EYmxxatBc4Dq/tcTI0NOhHcqFiKKToW3OhYigk6ErxTsBRdNAveaViKDjoE3qlYShLaB97pWEocugbeLVhKFFqCdxuWwqElmDtBqg4Wj264udR6YClBtASneQCA4FdWR99+9hj1xFJUtATbPgBQM/e3J4RuBCyF0LWLlukDAC4qupGwFKBrYATo/uJ1Kyzl93Kv/JnXaFjK11JZ/APE8zEB5VpUdAAAAABJRU5ErkJggg==Azure Data ExplorerGE.PEllipsefalseAnyAnyfalsefalseSelectOnly AzureAzure and On PremLinked Service TypesVirtualDynamicafe0080c-37dc-4d53-9edd-d0a163856bdcListAzure Data FactoryfalseSE.P.TMCore.AzureDataFactoryCentered on stenciliVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAABcRgAAXEYBFJRDQQAAHIVJREFUeF7t3S+UXMXW8OErr7wSiUQikUgkFomM+ATiiggEIgIRgUAgIhAxEREIBOIViAhEBCICMQIxIiIiAhEzX3ZYfZl0dqp7prv+nKpHPGYvFumZVM759elTff51dXUFACwmHQIAc0uHAMDc0iEAMLd0CADMLR0CAHNLhwDA3NIhADC3dAgAzC0dAgBzS4cAwNzSIQAwt3QIAMwtHQIAc0uH9Pf08q+r//vjHw9+e3H19c/P/+fuT8+vPv3u4qD/3H129a//97aYZf/tvut/3r1fnr/1euL17b9mALYjHVLPs+ev3pxAH//+8n8n190J94Ov/3jnZL0F//7vP0ERYRI/08OnL9/8nPHz7v8OAOgvHXJ7f70+38WJL06AcSL84sc/35wY4ySZnTxXsYuELx9evvm9iAOAvtIhh12+fHX18zMn+XP45P7F1ecP/nzzu4wrI8IAoL50yNvi8+54R7/73D37XJ3z2l0xiN95/O5FAcB5pcOVxTv7OOHceXT55p1pdnKij+tREFcKXry5DzH/ewSgLB2u5OLFqzd32Mdn0x/d2+ZNeCuLSIsgiI9j4v6L63+3ALxfOpxZvMOPE358br/Vu+55v7hCEPcSPLmwTRGgJB3OJk4G8S7x429d0l9J3KsRV3bi4wJXBwDelg637vq7fDfsEeL+gdhpEOsi1sf+mgFYTTrcorgh7PsnL95cAs5OAHBdrJNYL24kBFaVDrciLuvGO7p4Z5cd5OGQuDIQHxPETYT76wtgZulwdLFNLy7v++IdzunDb/54c69I7AzZX3MAs0mHI4rPbeOBNO7cp4XPfvjTVQFgaulwJHEQjnf72UEaaovvhoiPmewiAGaTDnuLg228249LstlBeTWxfTFuWtsX71Jjz/v77D/CN8Qs+2+vi/9v9uet/JFLXHmK340dBMAs0mEvceK//+uLJS7z706q10/icVf67kQ9+ufQ16Ni9/rD7uea9WuUI4K+enxp9wCweemwtRlP/NefcBeXkONEuepJIx7kEz9/BE78PuL3EpGw5e9oiNceV1N8NABsVTpsZYYTf5zorz/j3iXim4koit9brIO4Az/CY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 Data FactoryGE.PEllipsefalseAnyAnyfalseA high-scale ingestion-only service for collecting telemetry data from concurrent sourcesfalseSE.P.TMCore.AzureEventHubCentered on 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Azure Event HubGE.PEllipsefalseAnyAnyfalsefalseSelectAllow any IP inboundAllow only other Logic AppsAllow specific IP rangesNw Level Access Control Config for TriggersVirtualDynamicd488c23c-1667-45a1-994b-f56f2655727bListfalseSelectNoneSpecific IPNw Level Access Control Config for ContentsVirtualDynamic0b0ab9bc-a582-4509-a6c4-8d56de65661eListfalseSelectYesNoTrigger_action has sensitive inputs_outputsVirtualDynamicb1724997-7ae6-4b30-a001-9c5b42d9d1d1ListfalseSelectYesNoHTTP request based TriggerVirtualDynamic5afb52dc-dffb-4319-aa22-523f78ee3845ListA representation of Azure Logic AppsfalseSE.P.TMCore.ALACentered on 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 Logic AppsGE.PEllipsefalseAnyAnyfalseA representation of Azure Machine Learning ServicefalseSE.P.TMCore.AzureMLCentered on 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Azure MLGE.PEllipsefalseAnyAnyfalseIngests and processes high-volume data stream falseSE.P.TMCore.AzureStreamAnalyticsCentered on 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Azure Stream AnalyticsGE.PEllipsefalseAnyAnyfalseA representation of Azure Traffic Manager ( DNS-based traffic load balancer )falseSE.P.TMCore.AzureTrafficManagerCentered on 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Azure Traffic ManagerGE.PEllipsefalseAnyAnyfalseEnables execution of background processes in AzurefalseSE.P.TMCore.AzureWebJobCentered on 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Azure Web JobGE.PEllipsefalseAnyAnyfalseA representation of Dynamics CRM serverfalseSE.P.TMCore.DynamicsCRMCentered on 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Dynamics CRMGE.PEllipsefalseAnyAnyfalseA representation of Dynamics CRM PortalfalseSE.P.TMCore.DynamicsCRMPortalCentered on stenciliVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAABcRQAAXEUBuS1iLAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMzQDW3oAAGWmSURBVHhe7d13fBRl/gfw7G56T0jZnk3vvUCoIUAo0lEURVAUFT0sWE5U1IueCinbN21TCAmEKiA2VBRPrKd354nnef688zy9s5yn3tlQmN/3mZ0NIQwKmLY7nz/er919sjs7MzuZ72dmnpnx4TgOAAAAJEa0EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2DoQb1j3LVczfBgAAAGeJ1dL+9XWgiDYOBDbiPso6AAAAOEuslvavrwNFtHEgIAAAAAD8PAgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAIGDD/FXd8wAAACPOYNW9/vV1oIg2DoTBmBFsBvf/HgAAgJGA1Six2vVzIAAIEAAAAGCkQgAQIAAAAICUIAAIEAAAAEBKEAAECAAAACAlCAACBAAAAJASBAABAgAAAEgJAoAAAQAAAKQEAUCAAAAAAFKCACBAAAAAAClBABAgAAAAgJQgAAgQAAAAQEoQAAQIAAAAICUIAAIEAAAAkBIEAAECAAAASAkCgAABAAAApAQBQIAAAAAAUoIAIEAAAAAAKUEAECAAAACAlCAACBAAAABAShAABAgAAAAgJQgAAgQAAACQEgQAAQIAAABICQKAAAEAAACkBAFAgAAAAABSggAgQAAAAAApQQAQIAAAAICUIAAIEAAAAEBKEAAECAAAQ+vOmmdiyEJyAVGJvQcABg8CgAABAGBoUdHPumP90zvIY2vvOzDGR1kj94s3MTKx9wPAwEIAECAAAAytMbM3Z5fP3ry7YGrnu6MybZtk8bUbfOONGygAnE/CxD4DAAMHAUCAAAAwtGRqSw7ZJ1OZ6P+llqMAwFEAYDqIUuwzADBwEAAECAAAQ8tHXZtD9vmoajmf+DoKAHWcnCji6zoIAgDAIEMAECAAAAyNNesekpOI5HJHha9uwxM+qg0UAOopADAsCNR2EAQAgEGGACBAAAAYGlT8w8i8ect6zKOybG/5qOrp/4XEGzmfOMbUQRAAAAYZAoAAAQBgaFx23a6YFat33jL7wi3PxeU0fOzD9wFwBwAzsVAAsCAAAAwyBAABAgDA0CirbIsZPbXtluyxzc+FJlo+Zrv/XRAAAIYSAoAAAQBgaCQVNsaRak2O44+BOtN/WAdAFwQAgKGEACBAAAAYGkmlTjVp0RY0fRlssBzhCz/2AAAMOQQAAQIAwNBQ5jZoSVdMpp0L1Js5GTv+jz4AAEMOAUCAAAAwNPz1dVrS5a+r4xSqWgoAta7/GQQAgCGFACBAAAAYXCuve1xG4sbM6JoYaDDulbHiz5/3T/8v6AMAMOQQAAQIAACDi4q/Lyk7Z8nO66LSbYf4/xO+6BP0AQAYcggAAgQAgME14Zwe34mze8blT+q8JSTR8qKr6FPB57EQgAAAMJQQAAQIAACDKyLR5huZZBsXmmC9RaE0vshv+SutxEYQAACGGgKAAAEAYHClj3UGppW3XJVY0vxkiMHyD77gKy0CBACAoYYAIEAAABhchVPbQ/Imt1kzxzu5qDQ7FXwTcR8CQB8AgKGGACBAAAAYPNWmP8gKJ28MV2VZ7bHpFi5Q5y78DAsCCAAAQw0BQIAAADB4rrjloCJrXHt0gLLG4RtXw8n4nv8IAADDCQFAgAAAMHjSx7UHxGU3KBVKYxO777+r8FuERwQAgOGAACBAAAAYPDPP3akbP6tncrDBtv34sX8EAIDhhAAgQAAAGDwXXrZv2XnL9j6eUNDyN584+v/gDwFQ4We9/3kIAABDDQFAgAAAMHhmnrfjnqqF27mEgmYq8LVEKPju4o8AADDkEAAECAAAg0dbYL9Hk2/nQpKowLsLft+tfwQAgCGHACBAAAAYPH662nt8tbWcXM3+N9wBoB8EAIAhhQAgQAAAGDwylfEeQv8XIoXfDQEAYEghAAgQAAAG3vLVj+hIZXRmY5eP0t3pT6T4MwgAAEMKAUCAAAAw8Kj4zyZbUsrbD/so2fF/FgJEij+DAAAwpBAABAgAAANv/OyeCyfM7nlend/8Dx92CEAMAgDAsEAAECAAAAy8mNSm5eQPQXrLxz6qWir49L+BAAAwIiAACBAAAAZeSIL1KvKhn8b0P9f/BRV6BACAEQEBQIAAADDw/HWmNeR7uVoo8ggAACMGAoAAAQBg4JRP2xpHysKT7Ra52vQDOwVQ9mNnADAIAABDCgFAgAAAMHDKp/XkktUxGY0P+SiNR1lxl7ECz276I1b8GQkFgObWZ+SM2N8AhgoCgAABAGDglM/oOYfs0+Q3v+sTX3eMv/Z/LAIAQ4XfjyiJmgSIvQdgKCAACBAAAAbG3bUvyoqndl9WNKXrE01+ExX2Wir+9D8Rw4o8kXgfgNU3PxR2zY17R6+45sEpY2Z2ZsVk2rTqrNo4Xfb6MCIT+wzAYEAAECAAAPx8VPwVJFhX0LwqNrPhk5BEq1DY6X+C3QUwnh4lHgDSytq15JeJxa1b43Iae2IyrQ4KALdS8a8iIWKfARgMCAACBACAn2/FdY/7r7j2scjQROu1CmX9p67j/ibCijwFAP5/Qyj4/Xl5ALiz/iUZCc6b3FUam9G4NSrV8VlEqv1IZJr549j0mufi0tffHJ+xPkrsswCDAQFAgAAA8POlFjYFpBQ2xfqpTTfI4oyf8sf+iYwCgFzJzgToV/T78v4AEECyZl384KXRGdZn/XR13/lp647662u/CTLUfBKUuMFK4sQ+CzAYEAAECAAAP58qx6om04P0ZjsV9C/4ok7Fn+0JUMSbXGcCiBV/xssDwFW3PhlOzpt18a7mUVnWt32UG2iaaziZqobz1dVyfvraTqIS+yzAYEAAECAAAPx8ukJ7JdkdmWb5m1xl/N519z9W+E2cIk44FVCs+DNeHgDOW7knntRNW7ztvfgcx/9krD9ErJGT03T7ao2cn87YSRAAYMggAAgQAAB+vphM2wLydmiyhXNd/Y8VfDMfAOTCoQApdgI8d9V+2dg5W3SjZ3V35U3eyEWl2VzzIpbmS7yZ89OYOX+duZMgAMCQQQAQIAAA/Hy+GssCX63lbbma3faX/R+wAk9FnYq7jPUHYIVemgFAEZ/XbAhLsXcHJ1o5hYZNL80fNl9UJs5Pa0IAgCGHACBAAAA4e5ev3h9NxqWVd9xLAeADV+EXCruShQF6zZ8JQCQWAK68/ilfUj5v6UM3RWc0vOCaN+71BAUACku+OgoBenMnQQCAIYMAIEAAADh7VPzziGn8OVtfpS3c/50YANjzPq+lFwCCyK8vuuKxj5PL2r7pP29kaiMCAAwLBAABAgDA2auct7W8cu7WPdnjOj4OTDAfOV7gzoCXBoCJc7YFj53ZYymZupmLyWo8abr5AKClAKAzdRIEABgyCAACBACAs5dY2FRBXozLtB/11RiP9S9yp8VLAwBNW7BcbbQQ0emWqeqFswAQAGBoIQAIEAAAzlz1/S8EEG1xZfeymPTGP4QYrNypCt1P8sIAMPei3XlV5+64NDKt4fHevhD9ppvdKhl7AGA4IAAIEAAAztyd9xyKWFf93Njxs7bfEWxoeNtHaaFln4pc/+P8P8ZdDL0wAMxe8uDy6eftfFKT1/qej9JK00khoN/0ow8ADBcEAAECAMCZK57YMap4UsdMTV5zrZ/e9q6PmgJAvwL3k7w4AKSPda5JK3f+LTLV8QV/OiQCAIwgCAACBACAMxeuN6qC1XXL/NXGTrnW/A8fDRW5vkX9THhRAMga3+lLAqPSLfdFpJq5AL1Q/MUOAbgDAA4BwBBDABAgAACcGZPz977qvKacYL3Z4a8xvSVXmfqd/neGvCsAaMnEsGTrRn8q7gp2VUR24R9+3XDidLs6ASIAwNBDABAgAACcvsvX7JddcdMTweq85vGBestTfhp2SVuhyLkv+HOmvCgAJJY4RycWO28PNlie5udHfC2pcc2fftONswBguCAACBAAAE5f2hingkSHJ1mnK1TGg/yNbeKoyDH9Ctxp86IAEJVmvoi8Eqg3/tNHyeYJzR8VWy+cPN24DgAMFwQAAQIAwOlTZVmDSVlEkulGubLu973FP44t+1TY+nV0+1HuYugFAYCmR0YUwQnGG4MNxu/9tGx+0HxhxV9s2gk6AcJwQQAQIAAAnD5NtlVF7o1NN7/ur637nBU5ORVxRuIBwI+EKTTGteR7tnvfNT9OPU8QAGC4IAAIEAAATl9MqsVAeiKT2K1s6zgZBQAFLfO9AeBseEEAkMcZDWQ2TU8H+eGE6TuF44cAKADgboAwhBAABAgAAKfPT2kxkB5fpZmTU+FmfQBkyhqea/kXL3Y/yjsCwHxyUBZf/4HoNIo4fiVABAAYWggAAgQAgJ9WNG6TL8k05Dkv9ldbn/GJM1HBpiLG93LfQMu9NAPA+Sv2xZAx6tzG9QpV/X/4TpEiPf7FHD8NEAEAhhYCgAABAOCnUfEPIaszS9ufDku0fcgXMFrWXQGAFX965Jd/8WL3ozw7AJQSY+7E9pf8dHXfnsl8QACA4YIAIEAAAPhphnxneEJeywOa7OYPg/TWr/iizZ/n3odIkTstHhwAiiq7phZWdu3XFTT/y09T/71rHSAyjSJwCACGCwKAAAEA4KeFGKwRxEHF/weF0nzMJ5YVbBLPmFzO9mqAHhwAQhKt88ibgTrLD77x5mNyfj6ITKOI45cCRgCAoYUAIEAAAPhxeRVN+pTRDVXBBuuDvhoLJ2PXtmd9APhi58aKP+lzmttPchdDDwwAJZVt0aQ8Lste7a8z/UNB08OKv4xNy2nOB5wGCMMFAUCAAADw4ygAVGaMa/w1bem+0ntnO3fB70ukyP0ozw4A6eR2fYHjCT9t/eeuSyEzwjSJTW8/CAAwXBAABAgAAD9OX9x4pbaw4VBwooXv/DfgPCgAnHfpwzLir8lvGBebZdsclmz+q6/K+K2M7wdB//+neQYAc7wPAC4FDEMLAUCAAAAgLmtiu4zI43IaHojNdnBBBrbb/2f09j8VDwoAMxZv86s6tycuJst+vp/O+Du5ul64HgKbDpovZxQAcDMgGB4IAAIEAABxVPxDiSo00WIN0ve9te3Jxexn8aAAUFbVoiM3JJc1PBxkMH8sV5k4udLsOvZ/huHo+JUAEQBgaCEACBAAAMSllrcYyNQArXGLTywVN3bDnzM4xv2T3MXQQwLA9Xc+7Td6emtpfkXT/uQyBxecaKWteCr+DN8Pok8AEJveftAHAIYLAoAAAQBAnKHYcS7ZF5ZoeccnjooWv5VLzqbDnxgPCgCs+BPt2NndC5W59ufCUyz81ruPSsAHAGF6EABghEMAECAAAIhT59l/qc61cxQAqEiz4/+C/sXu5/KAADDzwp0hVefvqMip2HhnoMHyR9HpOEPecAggWGsOIRoSKfZ3GJkQAAQIAADiQhJsvyScn4YVfVq23YWa3wsgXtTOigcEAFVeYxy5fVSm4wUq1p+KTscZ8oZOgFT4c8lqMoXIxd4DIw8CgAABAOBEwYnrY0ihQmmyyOMsrh7u7GY/7JE/FHBiIfvZRnAAyJvQLCORmjx7WViSZUtQgvm/CrXxe9HpOEOeHADSR7ePIiXRKfbVgRrTXj+V8dc+sXUVRC/2fhhZEAAECAAAJ6LiP4W0+apr/+ATS8UqrpaKNAsAP/OmP6cysgOAHylLKnZcG6w3PSdXsev91x89aRrOgicfAqDiP4Fsic9q+KOfuv5fsvi6v1Dxf55cKvZ+GFkQAAQIAAAudz5wyJeERKYZLwvQ1/xJoar9/HgAEG75q2JoORfp1HbG3MVwhAaAmcv3yTLGtYVqch2XxGXYtvtrje/2ngYpNj1nyBM7AU6e3T6KjM8qd96ry29+PyrVziloOtheIhktK2Sd2OdgZEEAECAAALhQ8Q8lBlVe422+mvpP5Urj9677/tNyzQcACgJ88R+YAugBAcAvpbwjLiTBWh+oNX+iUNV/4zrXX9IBoJRsyRnX/PfwZOu3vhr63YRrIfjSb+gbZ0EA8AAIAAIEAACXBRfvSl6wdNfFhuKWzbRV9xXf25/v+U/LNb/7nx754i+NADB5bk9p+fTu1bSV+4wvFWs5P67COItNzxnypAAwZtbmCDKhcHLrXdljHW/r8qxcAI2765RQE3+DKEW8mUEA8AAIAAIEAACXyrmbK8n25NKWvyg0pu9dp/sxQtHjC5/b8UJ21tzDHKkBYE7P2gkzN/9TldvwlUxVx1/sR+Y+DVJses6QhwWANNKQNaH1najUuq/8NOs5Nk9650XvsmJEAPAACAACBACQuo4tf/Qj0aXTNi1NKWl5dVS6/XMqTgPS0e20jNAAkFbWdl9KaSsXkWKl8WT9IGg8B/A6CHwAGOGdAGct2RVGpo+bveXetDFtrypzGr8K0Jt+EJseAQKAB0AAECAAgNRR8Q8jGbmTOm7x1xjfl8XXHRuUa/6fyggNAH5qy31E2PXPAoAwrv3H/yx5wmmAVPx1pH38nJ6v47Iav1eoLMd8VA3ETtMgOi8QADwAAoAAAQCkbubibfEzz982VVvQWK9Q13/kOubPluWTVu6DY4QFgPDUhrHkDj+t5SA7tu0ax8EIACN3D8BFNz3lT2bOu+KRmsKpXX9IKGrhQgxW4RCIhdDvhQDgsRAABAgAIHWGogaDobBhRUSKZbNcXffv48syrdD7HLMecO6iMYICQOX8zQoq/reGpTi4AD3b9c/Gk+YFCwDsbAh2ISTWJjY9Z2ik9gGYffF22fnXPh65ZM2TjfOufIQzlLVxsjj6nRh2uh/NC+YUywcCgAdAABAgAIDUBelMJaTVX2N8U66s/6a3MIuv4AeO+ztGSACg4p9HfqHOb9rnr7dwCv4SyO7xpP/t3j0Awvj/TCM4AEyZceG2BwpndL+SMmEjF55mF6Zd+L349Zzw/OTpQgDwAAgAAgQAkKryqk4FCaPiv5C28F5nW3lyfguv30p+sA1zAJi64HEZUYyb1XU+eVFX2PQRf6aD2LgOoN4AMEIOASxZ9WgQiZl+wbb7Ji/a8pmmsOnEMHh6EAA8AAKAAAEApIqKv45cmVTUsi1Qa/tIFs/uay9s9fJ9ABjRlfzAGv4AEETidflt18ZnNf01JNH6FX/BI7FxHUCuToAjKgDMIC1FU7t/q85r+Zbmw4/19j8VBAAPgAAgQAAAqSqc1JZPticXt3warLcfkbHOXSqhc9dQdgQc5gCQNnqzMq1sc0WIodFC3/8lGx/XOe6DO/0j5SyA2RduCydJs5fufmD2xXuOpozZ6Po9+MMd4uP+IxAAPAACgAABAKQqNsNSTB6JTDF966upOeq60Q9b6bMAILpyHxzDHABCE+wTQw32Tn+N+U1ZfP0RFnxkYuM5wEbKdQCo+E8lHYVTOl/XFbZyYSnsFD/xcT4NCAAeAAFAgAAAUjN14TY/otcXNF4QpK9/0VddQ1ujD9Cyu8FV+Ptu+Z3cyWvguL9jmAJAZsXGEJIckeK4MUBjed+Xxonv3c4CAD8P+ozrIBjuToBjZmyMIFnjZm+qHj97038MJS007cJpj+67PoqM909AAPAACAACBACQGir+8WR1QUXnvvAk24fsEreuZVcoxtIJAFnkV/F5Tc/4aSz/5ecDH4Bo65yd7sfGS2y8B8gICABjSVNaefPv4nLsR0KS2G5/4TdxLw8i4/0TEAA8AAKAAAEApKJ96zsyErTwkofyiqd2tqeObv0oJNH2jWurz935j/CBgK38z6oAnL5hCgAXrdobQNT5UzrP15e2HIjOdHyqUJu+7512VgSFc95Fx3uADFcAKJu2OZqU5U3ouDOz3PkXZY7jG4Wm/phox0eR8f4JCAAeAAFAgAAAUkHFX0F0S69+fLYqt+HRYIPpO4XGdNRV8PtjK/+zKgCnz11khj4AxJH5JVWd5ohU6zu+GiM77n/s+NYvGyfhUWy8B8gwBoAysimttP0vUYmOrwM05qP0W1MA6DP9biLj/RMQADwAAoAAAQCk4rq1zwat/uXB2QuX76uPzbS/IXMf5+2/0h9qQxgApszfpaDCn1E0dWN1YmnzbwJ0pv/0nvEwVGc9CIa6E2Dh5I1RZELWuPa7U8va3lFmN3H+KrPrKn8i43eWEAA8AAKAAAEApOL8Sx+OvmDFIzWzzn/wn+q8xq97O3qJr8iHzhAFACr+chIUn9MwPjzFsi/IYPpSrjZ+z2/tD0cAGOLTAKn455CNKWXOf4Qn277xo/AhU9MyoBrQ5QABwAMgAAgQAEAqiqd0xZRM7XLmTtzIRbLLu4qvwIfeEAWAlDHOCDJLmdtQE5hg/rOCtsDFx4f+j4cgDAzVhYDUeU2hZKImr+lOXX7TG3GZDs6fvvfE9Zb4OJ4FBAAPgAAgQAAAqfDV1sX46+udfrp6Ts6O1w7gve1/liEKAIllLYmkQ53f+HlQguUIf6ofX+jd3ONDz4ciALj7AAx+ANATe2ym48MgnflrBf/9tNXPpjGWzfsBXQYQADwAAoAAAQCkQJl9/9hR6fff7KutOeRaTo3HL/t7ckeuoeEuGoMcABYt3R5IJlbM6bpdW+h4NTzVwvlpzMK5/mwc2PzoLWAu7gAgNt4DZLA7AUYn1wWSqqjk+l+HJ1t+G5Jo/c5XbTzq6uAoTB8fgsjALQcIAB4AAUCAAADejoq/nNwVm3n/vwL1tV/xxV9l4omswIdOb7Gl54MbACLJA1ULut9X5lr/56PawN/wyHVve2EcTkVsvAfIEASAaNIYkVj3vb+mnp3tccyFTZd7GmlcBjYEIgB4AAQAAQIAeLMFl+8Onbl0hzY6xWIJ1Ru/8lXXfT8Uu7fPyCAGgMyihrD0ksaMtNHNTkNx45chSZYj7DvZ1v+P7gEYAjIqmAPdB6Bp05vR9vY30tNHOy8I1tXVBunqXgvQ1XFydo5/39McBw8CgAdAABAgAIA3m37hDs2UxdvGhSc0bVbE2oUr3NUQd89vRnRFPnQGKQCsuP5xeWpBQ4IqwzrdT1u/x3WhG9rqj2ffRY/8vDj+fys6boNoIM8CuGHdozLi+2vTK5n3Gl9ZlFrW8mCQloavZt9F08am001kXAYQAoAHQAAQIACAN9MWNk/XFjTbg/W238mpyMr4IsACAFtWRVfgQ28QAsB1dx4MuXrtAaUyq2FlaIJlp6/a+M4JRZCd+85f7Y/Nh+GZFwN5HQAq/nGkuKxq45qkkuaHIlKs79A0c3L2Pfw003diDwAIEAAECADgjXIn9shJQHS64/qoNPvfAnTmz3uLH3/+P1tZs13g5OTjuEPDXTQGIQBMPXebvnLhtopRaY4tQVozp2D9HfiCz254xLB5wV4L48CIjeMgGog+AHOW7pQTv/Mu31VIrk4sadwXSFv+rlMcTVT83QGAvRaIjMsAQgDwAAgAAgQA8EZU/KNJVmiSvdZfZ/6SCsJ3vYWuF62wvTQAxKRYzhuVYtkbpLe8o1BbXB0e+e9z/5+650EfYuM4iAYoAISRJENp61UxWU1PhSRa/6ZQu/oXuH5f9/S5X7u+exAhAHgABAABAgB4I0Nhe5ahsO2SoATrgycUuZFoAANA6YyNUSQtMslsDNKwY+Cs8NOw+VMeRb57GPUGAB0FAN2ZBYC4XLuCBKeWOzMyx7cuCk91tMtUlq9HwHQiAHgABAABAgB4o1Ep9kXRyfanA3Xmvx9fNkVX2MNvYANAFelQ5jS8rqBiKKdh89e6H5rj32fk+FkAZxUAIkhOaLL5qsAE0z5fjen/ZPHm74/fz3/YIAB4AAQAAQIAeJOFy58II4nxmQ13h+rNX/lrqLj2LpuiK+zhNwABoGhGeyjRZ05wrs0Y7/woJtPxHSuGrPjL42ja+b4PIt89jI5fCvj0A0BoutOPRIWlNhSFp9pXBuhNm+Wqus96r2vA5qXIdw0hBAAPgAAgQAAAb0LFP5usTipt2+unrvvu+B3/GNEV9vAbmACQQa5QFzTsCE2y/C9AZzqq6O0AJxD77mF0lgEgkpQHJzXeGJhgf9JPY3lfHl9/xBUAaLjDv6cDAcADIAAIEADAmxRN2VZJtqhyW96SK2t/OH6+v+jKemT4GQGgsHKDH4k0jHbM1pU2doanWt+gQvg9K/xymm4Zm/YRGwBO/xDAVdc/FkKKp527Y8mo7Oa7/HTW3X4a88fs7IbjPf3ZNA77dCIAeAAEAAECAHiTYIP93JBE+xsBOstXcvdlX/nl8qQV9cjx8wJAJMmLzjTe6m8wv6VQm/7nE1N/jN8SZr3hadplccKNb8S+exidSSdAKv4GYp6/dNebyrzmv8pU9Z/I4jYc8Ylj13Sg4fEBgJ4P/2+NAOABEAAECADgDTJKTaPImLAk46/lKuPHMqVwqVtWHNgV8Ni13088XWv4uYvGWQSAW+/7jT+JLZnWOi42o+6mQH3dHpm6/gt+WOwOd+xRuAoev3XMvkdsHIbR8QsBnToAzDp/ZwApm37u9uunLtj6csnUTi4ynd3KmaYpbgNhRd81na7rO7DfWvz7hggCgAdAABAgAIA3oOJfSGrjMowvKjT1X7HCL+MLISt8bietrIfXzwsAEaS0tGrTLcH6+lfl8bVf0P/eD73DdJ/v3vua9P/+YXaaAWAUuX/SnJ6/6fIb/xukN3IKNVvP/MihHZHvGkIIAB4AAUCAAACebPqc7b4kUp9nnxuXbn40LNH4oVxdf4Qv/DG0QmanwIkViZHkLAJAxvjWRHKjMrfhET+N6d+u3eD9hjvCufoAiN8LIKW0QUaKU8uars4c13YgeXTrkbBk69ERdKz/VBAAPAACgAABADwZFf8QkqrMbLrGX2N+S64ysq3gY3zhZwEglq2U3cvmCSvqkeMsAoC/rq6M7KcC+q1MZT7quskPG1a/YY9grrMA6ikAGCkAGPsHAD9yi6HI8VZ4qvU/Cq3pGP22x1yHdQh/VT/x4Q4zBAAPgAAgQAAAT5ZUZEtMKrTeEJNufshPY/yUP/bPrnzHigQr/iP0HPgTnEEACDPUjCLnBelqG3zV9e9SURSmlwUAD5jWPtgeAD+tifPXmTpJbwBIKW0cn1zSsC4+y/5EZIrtPwE667fsaoau0/yEDo0jN+ggAHgABAABAgB4MnWOsVyVbXw2Oo22JLW1fFGRq6xULFhBpWLB94AXVs6uY7Qjh7tonGYAUOc6ZFT8s0ITanYH62s5BRsGf7Ef1wV/XD3i2bHxETitIuRqtvvfTAHA3Bmgt/QGgOSSxnUUALjIFDv9jvRbxtk4WayVpo/WL/yNjEb0dCIAeAAEAAECAHiiWeduDSAJySXNSyNSLK8GJpiooLgKgkxFxZTfJU7LY98txZNX1sPLPV6nEQCo+IeRxTEZVmdQQv3bvpo6Puzwu8LZ5/npdP8PjsBpFeHqBGg+qRNgQlHjOn1hAxeWTEWf/x3dezjYNLLCL0zjyJxOBAAPgAAgQAAATzR+xqYIUplU7LwnQGf7s+uGN7QCdhcGT/ITAUCT1x6kymnKUGbbN8dk2LgAPRVDseF4mFOdBaAuaFynzm/gQpItop8b4RAAPAACgAABADxRZLJVT6pDDJaXFSrzZ3wRFV8hj3w/EgCo+CvIYmVOa2d4sv3PgQlm4V73IsPxMKe6EiALACoWAJIQAGBwIAAIEADAk4RprTIS7q8yjlco6x+T00q39xrwfXf3e5JTBICscZuj0sZ0ZahyWltjM1uOBultxzx2L4eIU90LAAEABhsCgAABADwJFf9gMj1Ibbpfoax5Q8Y6hcWyzn5s2RNdIY98pw4A52aUd++ISW/6c6DOesxXbT0mV7Ki6CWHAH5kDwB/CAABAAYJAoAAAQA8xTU3Pxk0emq3ITzBenuAyvicPH7DRz5x6ykA1BwPACd2yBrZ3EXjFAEgc+ymOzPKO7noNAe9p46Tx5uJ0DFObHge5lR9ADR9+wCIfG6EQwDwAAgAAgQA8ARU/OUkec6FD86JSrFvlcfXfyKLr/3GdaofK6JCMRVfKY9MPxEA0sudd6aNcXJR6VbaWmZ39qP3sR7x7FFseB4GAQCGCwKAAAEAPMHkeZt9K+ZunlE6dWNtRLL1970XveGP/dOKlz82fsKKeOT7iQCQWt58Z8qYJgoAFj4A9L4XAWAkQwDwAAgAAgQA8ASaHEuAPt92hybH+m5wgunL4wGAEQopI75SHpl+IgCklDvvTB7TwkWm2Wjr3/1e4VFseB4GAQCGCwKAAAEARrpr73g+c+WNB89PKml5KDyJCoaWFUJa1vpyF0hPdMoA0EoBwEkBgN3+VuRzHg6dAGG4IAAIEABgpKMAsPrqW597O7ei+zOF2uTaGvb0ot8XAsBJAQCnAcJgQgAQIADASLX2gYNBJHbGBXtrJi98kNMVtbmKJX/cny1rJ618PRMCAAIADCkEAAECAIxUVPzjSbE2v6U5SGvlfFXC9eARALwCLgUMwwUBQIAAACNV9oTmsdnjm6vDk23P+sRS8Y8Ttv7FVrzHO2F5Dve4n00AEBueh0EnQBguCAACBAAYqUal1q8gbwfpTZ/7xFMx6L0jnAjxlfHI5h53BAAEABhSCAACBAAYaTQZ5iiSFWow3xukN3/qpzF+6yp87mWsXzH0dOgDgD4AMKQQAAQIADDSqNLMKcpU04WBWstmmdJ6hF0BT6bcQMtWDel3P3hvINkAgJsBwfBAABAgAMBIsfr2/TLiF6ozzwxQGrf6qoxv0VbiUf7Kd72X+2XL2AkrXM+HPQAIADCkEAAECAAwUuRWOEPyKpy6YK35ZnmM8WP+Nr9qWqZYgYxlBZLdBY+ee8mlcHuLBvoAoA8ADCkEAAECAIwUyhxLkTLbsiE00fS8PL7+G9cWP61U2WPvHgB6jQAgPjwPgwAAwwUBQIAAAMNt9JxNASROnWdbMSrd/BcKAPzxYb4w9vb8F479i690PZO7mCMAIADAkEIAECAAwHCj4p9ALkssa9kclmj9xE9DxZCtTN1b+15W+Hq5pwkBAAEAhhQCgAABAIZL/qR2GfHLmNhaRlrVBU1vBWitX8vYVn//wu/NziYAeIFTBQBcCRAGGwKAAAEAhgsVf18SHZtpnxOWbDkQlGD+Uq4y/cAXRPGVq3eSagCgLeZTBQCcBQCDCQFAgAAAw0Vf5IgiU6PSLPf7aerfkbHlhx3v54/5SwgCAAIADCkEAAECAAwXVZ4tjTRFZ1j+5q+t+1oWX8vJYus4GevxL75y9U44BIBDADCkEAAECAAw1C68fHcwKZ84u+sWVa7ttdAkKgT8+f4UAKj4y/hDAOTEzlXex100ziYAiA3Pw6ATIAwXBAABAgAMNSr+amKecd7WD9R5jq/lqlq++Ltu8ctWoqb+K1Xv5C7mCAAIADCkEAAECAAwVCbM3SwjEWNmdpWUVm3alT2hnYtIoZW8u/j3vdBP/4LnzdAHAH0AYEghAAgQAGCoUPFXkOSM8W0LQ1Js+311ZuGCP2y5EVag7k6AUuoIKNkAgJsBwfBAABAgAMBQic1yBMRmNSyJTnd0++usf/FRUtFjxe+Ego89AO75hT0ACAAwOBAABAgAMFRCEq2hxBaUYOX81FZOFs92/wuX+uUDADsubCboA8CgDwAtHyKfG+EQADwAAoAAAQCGQtH0rul5Uzrro9MbXvXXmDk52/XPLy99CxtbgUqk+DPu6UYAEAkAjRQArKKfG+EQADwAAoAAAQAGU+aEFjnxp+J/f87kTi42s5GT01a/TFlDy8oDhN3kp19xkxqpHgI4nQAg8rkRDgHAAyAACBAAYDBR8deQ8crcpo2jMhq5YL2VAgAVPL7jn5voilQ60AdAPACgDwAMEgQAAQIADAZ7x5v+JCK/smOSvrjhl0EJ1gM+cbTlH2d0XemPDwHC8X/xFal0/EgASBrtzQFA/CyA3j4ACAAwSBAABAgAMBio+CeRBaNn9dQG6EwvKVT1H/Bb/XF1/OV+fVgI4IPACStPaZLsHgAEABgeCAACBAAYDL9Ye3D8NbceNOVWbHqJivwx18V+aqjI0SMLALH0yJ73vQaAVOEQAAIADCkEAAECAAyG1NLWxSklrb8dlWb/VEZb+exGP64AQCvJWFbw6Hn8BmGZOWklKi1SDQA/dRogAgAMEgQAAQIADKTyqp4YUhaf0bAhRGf53F9touLPAgAtG3wIYMWOHfun50ohAJx4GpV0uIvG2fQBEBueh8F1AGC4IAAIEABgIFHxn0y2Gwpb3/FXW47IlFTsTyhetJLsvdIfW168o5idFfc8OZs9AGLD8zAIADBcEAAECAAwEKoW9YSTnIKKzrUZ5R3vK7ObODlbIaKT309DH4ATAgC7FDAOAcBgQgAQIADAQKDin07WZk1o2x+eZv3CT8dWhhuouLEL/py0koS+EABOCgC4FwAMJgQAAQIADIT0MS1l6WOcm5W5jr/66Yzf8suC+za/4itKcDubPgBeAAEAhgsCgAABAAZCgM5YQQ75aYxH5ErjMRnr6BdLK3BW2MRXlOAm1T0Ap+gD0HsIgPUBEPncCIcA4AEQAAQIAHA2Lr/ugJyE5kzsTAlNsi721RptcnX9e+ziLjK2ImRX+WNFjT3yN/mBk7D5wop/bwAwUwAwoxMgOgHCIEMAECAAwNmg4u9HNBQAFlAAeMZPa/qOVuhHffi7/DG0MnQTX1ECHwBYUBLCEgUAGQIAAgAMOgQAAQIAnI20sa3RaeWtK7QFjT3BBtPfFep+BQpOi4zdGZG/JwIVjzhjBz2iEyD6AMAgQwAQIADAmSqsdPomFDemawoatsdl27lAHStk7Mp+7PcXXSnCKciUtCXM7wmg1/H1HdQmoQAgfi8ABAAYbAgAAgQAOBNU/IPJ4sxxza0xmbY/ByeYOV8V/e7suv787y+6UoRTYP0l+BAQb+ZkZ3IIwAtgDwAMFwQAAQIAnK6LV+8Nrlq8JTm/wrkxvbyJi2DHaGNppee+sQ9bAZ54PHT4nbByZq/d+rb3/7tY26na+7b11+/vwjixY9+MXG08ptAYf/DVmI/4axzfBmgaWki8e36nlDuFAGBz7yE4aVieDH0AYLggAAgQAOB0UQCYsejyXfWpY9p+F5li5/w1rPMaK/70uzMjsTC5CyaPvXZzt7mX275/d7eLfUbkvfx9Dtztfd9z4mu2xeunNXOBBisXRvMvMt1xZFRm43+0hW3v5VRs+13htJ13FVXtGuWe364A0MJFplpd85n/HmGY/afTAyEAwHBBABAgAMBPGT2p05+Ezb54+7rpF2z7m7bA+aVPHK2c+fv5C8f+R2phYuN0QnGmNv7UO3e7G3vdV99DGmw4fT7DHoXhydlxbE09F6A3cSFJVi4wwfw/marunzJV/QdytekDX63xA/8E4we0pf+uXGV6KzDB+lZ4quOt2OymtzQFztcNJW2/KZy29cGFK59qWLbm0EUk3D3fU8c470wZ7eSiUtm8ZndS7PPdYtPqYRAAYLggAAgQAOCnUPHXkQmG4uY2VV7jf4MTrUdOKKJ9C6z4SnH4sGWSvxyxu6Cz12y8GfZ34ToFbNx729l72PvZ5/p81v0Z/nP1HDvzISjBxI3KtHPJZU6ubPomLndi++vBCSZrsMGyISazcUNqeceG4umb79cVOa+iADCfAsB8CgDzKQDMpwAwhwLAjMKpWydTABhDxT+R+Lrne8aYtjvTR7dx0ewQQN9xRwAYyRAAPAACgAABAE7l+rue8SXBaWXOioS8xnVBCeZnewu9p2DFnN993icA8O20sman4CnNvN7CzmOfraWt+1rOT1PLRaZbOXV+0/dhybZ36e8vMjJl/Yu+mroXw5LNL2oLm14snrbpxXlLd744Y/FWe2ymbY4qu6GysKKr8oIrHq9ct+HVSUQrNo/76tz6RgwpvP2ep8tmLuouyxjd2mQoaOEiUigAuK+v4A4AXuBUAQBXAoTBhgAgQACAU6HiH0FS4vMa1vrpjIfl6vpPPK4AsfFlhyriqLAz/NY74zr/XhFv5nzjLZwsjnW0s1KhNQnFto4L1Ju4qGQbN+6crdyyXzzx5bTzdtfS5ysYCgAVFAAqKABU6AqbKoqndlZQAKigAJAfm2FTUgCIpQAQSwEglop/DAkSm8d9UfGvIjsoAByYde7mA2llze+GJpo5Py0bX/d0EC8JATgLAIYLAoAAAQBOJWdiZ3bOhM6V4am2PT7sVD/2+3pkABCKP7viHhV/OW15+ulMVODNRwI15n+HJTj+GZfZ/s+odOefFDrLAR+18TEKAY+FGCyPKTMaH5u3dN9jd294dQeZxeaLs+t1+S/vfdb/sjWPR827ZE985sRN8ZrCFqW20KEpqerOmbxw15TSGVurUsd1VsXmNFbRd1Up1KYqChxVND6ktspH6VYntNVXzV+2e8MN6w58umTlHq5sagenyXVw8r7znYq/DAFgpEMA8AAIAAIEADiV0ATbBeS3/hrzJ70rOI8sPrRcsvGmrX85vfbX1nNRaWYuNtv6eWSa7ZWksvb951z88P55lz5aYxjdMZkCQAEFgIKQBEsBBYCC+RfvK6Din0tGUfGXEf9f3nMwhgJAydxL9kylADCVAsAMCgDzKQBUUwA4RAHgNQoAr1EAeI0CwGsUAF6jAPAajQepfY2Kv6BOaKt/LSzJ8jdtfuOR+OwGLizZxgVQSOnbx6L3okHuPgseDocAYLggAAgQAKA/VXqthswM0dc3+qlNX8nZbvG+neV+zIkdos4SG457eWLDZY/sGD57Tn/vHQ/3c+I+fs+PQx1tXTL1XFiqlVMXNh6LyrD/NVBveS4y1XowPsv2hDrf9qCmwOaMybLfmTO56/qVtzxz/dr1L88i4Rdf82w8Ka2Yv7M8odBRnjGubUbOpE2LtQXOxREpjvPDU+wXjcpquDKxzHm3vsRZF5nuqAtJsppDk8yNusLmZ7IndH6TPLqdU+W3cPRezldDwYPmoeuSvzR+fEEXuAs8v4VPj+7TKvn3Ce8VuC4aRG08ajuBu/0siP4Ggw+dAGG4IAAIEACgP1b8yZPhhtoP5aq6o67ibyXsUaSA9CW+UjxDrHj37bm/gTxARZB15qNx4Hfn03fRIyuq8jgqru7d/FQo5fRZBevAR8NhF9KZcsH2H8rnbNmZMa5j1awLdiy/bPXD86cv7imiAKCnAKDMreyKpQAQy4o/kVPxH0dqJs3baaUAYKUA8AQFgHcpALwbnuz4q7/O/FcqXn9XaE0fko/o+UcUNj6mefWJn8b4ZaDefDRAZ+b8NCYaDzaONK7ugNKf+xoK7uP7wmsZK/h9ij8fAHrb2HwQ0e//8GQ0fDEnzf+hgQAAwwUBQIAAAG6FlZ1askiX39AYmWT8MFBX971MWXPMtZXNTkU7jQAwIKjQ9Z56R9/NFz0KBHwhZQGAHt1byTRuMnpPWKKNSyxu4/RFzreDEuo3+aprGv3UtY2ZE9oa51z6YEPVkh2XjJ21pfC6W5/MtjS8kn/rr55buHTVI1ekj2m8Ili34Qp5bM0VPrF1V9A0XqHOb63PmdR9yFDsfCUyxfxKfLb9Q01+IxedZuWC9FTUqXCJjjdfoGkrva/ewk6f6Q0u7L1suthzmg5+q59h0+TCF/o+/1MnYvOG8POEYc+pvfczbPhi3O+h5yMA+gDAcEEAECAAgBsV/0rybEKx87/+OtsPMmX9MZlyPf2mbMXGAoBZeD7Y3MsSK5JUBFy3yqXnVPz5rWZ6Tyz9nR0mULsetQUt3OyLHuKWXPn4tknztmdTAIj0V9dFZk1si5y7YnckBYDg8plb/K5f+5TvzXf9JvWGO57dtPSqRz7LGNP4GQWAzygAfEbD/IwCwGdylfFLhbruW1913XcuNT/4qtdzvsoHON/4B6g4s70T/cZZKLJiAYAPAbE03vxlk+k1w9pZMeYv8LNBwIo5m25hmPyhEDFsmlkIYOPBsM+40fewoMbPK4bNN4Y+N+ICAG4GBMMDAUCAAAAXXbVPRS6YMHdLi6Gk5YOoNAdt5bKVL21d81ua9Luywiu+whsE7iJGj6xwsS1nKqABWgsXmmj7PjzJ9mFYkvUVf71po0xTt0GmqluvK3KuX3DJw+svu+HAyitveaZw7rI9+aOnbxqbMab9fEOB8+bwRNvNVHxv9okz3RyR2vhA0dTu1wunbOJiMyycv6qGL8p8keb3ctCjsBteTtg8kFGhlcVv4IkWUb7AsqLu0lts+S18htqEvQDscMXxPQPu97Liz4o6PXcP86TCL+j3/3bieLB5xvQNAQz7G723r76fGwbYAwDDBQFAgAAAVPzLyFOTF2w9GsXfeY4Vwr5FhIWAB6iNbW2KrvQGGOswZyVsHKjgxtL3xtZy4YlWTpPb/HVSSetLWePbjTkTO8rmX7pDUTClQ0Zbk7LLrj8gW7X2Gf3Vtx2cRQHgSgoAd1EAOEAB4CgFgKMUAI5SADjqozQT+h5WBN273mPZdLI9HMKeBmF3vWtLvf/4ncIJAYDNMxpvfqueYf8bbL7SsBlW+Fng4PdssO+lv/Nb9kyfYYoV/94CzobH5hFDf3MTgkZvGODfw/7W57P859nwhs9p9QEQ+dyIhj4AHgEBQIAAIF2FFd2hZHTepE235Ezc+MeEkhYuIMG15X9iYaHftXfrVPjbiR2ffgRbKdLnGP7YNRsetfMrTDZc92tWGN3t9ZycnsdkOLiscW1cSpnzD6qcxi5VTlMtBYCbk0tbl4+euWXBJTceWLz0+icvShvfuiIyzXJdeLL17uh0hzU+p2lrbFbjI1FpjmcjUxx/i0i2cwFaKrL8MXb2Pazosu9lrwm/JU7t/N9oHNyFk293vYfvgU9tchpPf72VC02xc6OyHJwqv5EzlDq5tLFt3+dO6vg6saTlzQCdabtCbez21Ri7/bTGbn+dsTss2do9KrOhOza7sVuZ29StLWjpTihydhuKW9lz56hMR42mqMmSMamjM3G0szE6w7E+odTpyK7o7O4rY3zHRm1BkyU+p8GYUNLcnljm7E4ocXZrC1u6lXnNNPym7uiMRvo+e3eA3kzfbe721Zq7FRoT0xNksOyl73reUNr6aeLoVk5T0MTF0HREpFi4wAQTJ+cPqbDfoM+84H8XN/pb30Di/p1PeM+Jv2Xve/nXx9/H9gAotBQCdMZOcjwA5DvWqfMcrj0AvcuRx0AA8AAIAAIEAGlavOph39KqLfrcCZuuTyhq3UeF/599V84ubIXNflP26F6pC8RXfiLo8+x4Nd+rn+0+p2HxxZYNl20ls9esI5+ZHXY4RgXrGBXN7xTq2i9Txzi/mL909xeLVzzUsfwX++csuuShTGW6NSxYbwqbu+KRtFV3PHfbeVc/vjtlrPPpiDTLm1RkvwrUmV1b4PwWcN+tefo+/jvped8AwL82UTEycb5qE3/uvZ/G9B21f0HvIbWk7gsaJjF+4auyfBGW7PgiPq/5i5Ty1i8KpnZ+MWFuzxczl+z89IKVe/4++6IdPfE5jReFJNnnR6Y3zY/JapmvynPOL5rWPX/6BTvnz1u+a/6SVQ/NX3XrgQU3/erZBWvveWr+3eufmWJq/m1OU/frY5s3v35BU9cfqhztv89s2fRGZWv34Yt5mw9f3N7zp4s2bn1rfse2P+WbW1/JqK5/ZuodDxyYf8u9z8y/+ran5l/4i8fnz1nx8PzKJQ/Nz6vaPF9d1DA/Lq9hflSmY35IsmN+aGrDeboS55WFVd21left/H3Foh1fFE/r+iJ9bOsX2nzHF5Gp5i98NbVfyFQ03UozTbfpOKXpS4Xa9B39Nj8otPXH5FrXFjwr4mzenXiNAvb70iM/f0lvABTmNx+02Dw/VQCwUwCwUwCg3+mEZckjIAB4AAQAAQKA9FDxDyBlFefuuEad79wVkmh/V6Ex/+94wWfY875o5daX+MrvZHyRX88XA1bkXcWYhscKsPB97I56fmozZyhq/2HOsoe+m3nh7mdjsuy3pI1xrpp/8e5Vi1fsqzr/8oczUoubLqMAYA/Sm+yBCZYObXHrIX2J853wVPP7Abr6f/trTUcUKvYdDG09sg6E9J2uUwTpu/gQIEwLX4QsnExr5wKTGrmY7GYuc2InN2XxTq58ztZngxJta+i9qygAkLpVFACIcRUFgFUUAFZRAFiVMrZ1FQWAVRPm9ayiAHAFBYAVsy/aOTMuuzGdAkAyBYBkCgDJyjxnMgWAZAoAyRQAki+6Zl/K9Xc+nX7bfb/JuO3eAynrrYdmmJpfrt1gf35rdd3BR+7e8MyuOx84uPFXNc/uuKfuN49V1z372L31z+6rb/yts6HzzVuaNr1ZTAEgigKAjgJAMgWAZAoAyRQAkikAJFMASKYAkEwBIJkCQDIFgGQKAMmhKQ2pFAByCqZ1jacAcBEFgFUUAFZl0HRQAFhFAWAVBYBVFABWUQCg6Tb1ikxz/LL8nO5HJi3c8kFmZfvXqpImLjTVxvnpaB6yec7mJz9vaR6zYs8f/mC/u3D4gw8ELIwJvw+FMPY5Wu44X62501dr6Q0A2oKmdZp8Gn4yuzQzfc6zIAB4AAQAAQKAtFy/7vnApav3a2YsffDq0eds2R2Z1vie6xg0K4hsBc621Bn2fADwheB+wnah2+mRFYHaoxQEvpUpTf/105v+E5hg+jhYZ/nH6Kqe9+41vvqerf2NhitveSI/eXSzTh5fr/PTmPWhiba0uDRrW2yqhQvkr5DHhs2+g+2eryEsaNAKmBX8eCunUNmO+mpsP/iqrd/6qcxfBWktX4UkWP7rpzF+RJ95jwrQez5q+3vyhJb3wrPa30sa2/le1YUPvrfmnufeW1f30oZ7LL+NvXbdwcD5l+4OyqlsDxqVYw1etGJ79KXX7lHNWfagZvz87bqcio26hJIWXUxWky4kyaZTqOt1svhanSyOqaNxN+poOl3Yc6VLUIJFbyhuSkkqaU4JSbImXH7jY5fe8cDBP9967wFu9W2Pcr+49VFu9dr95HF6TdY+xl1722Pf3lx98I9r73uxY+k1++fI42n49D19se+mwCWoc30ffa8s3uSiNOkUGpMu0GDRRWU267RF7ToKPbqxc7bq5i5/SDf1/F2xkZnW4IBEU1BEZkNQ2aztQUuvPhB0yz0v+m9wvKi+33rolpvuPbB/5qU738iZ3vlebF7je4EG23sylZWWIROpe0+urvvAV1/3ka9mw398VQ98JYvf8BUFr6/l8ebvFUrrUXmc5Ygs3vKNXGX5yk9r+yo4seGr0KQGZ2hyo9K9jGoLnOsIBQDWH6XPsuQZEAA8AAKAAAFAOqj4y0j+stVPLU8b17ElOsPxV3+t5b+urXJWPGkF5t5tK75yO3P8FiAFAH4rkLYW2XH0+LpvfZXGv4QZ7M9kTujsKZmxpUaT23Ll6KotV/1i7YF7LrnuEfuU87ZsShnT3K1Q1ndT8dosU1q20hb+W0E6I+dLW1quDoKE/x4WAtgeBiO/JyEkwcZFpTq+VeU0fk7eUec0vjBmZs8Lc5fve7pgSte99P4lFACWUABYQgFgCQWAJRQAlkxb8uASCgBLfmV+ZXp9y+sF1915sIgCQFn25PYydZFj/Lkrtq++ZPUeGwWAtvHztnVTAOjWl7R0UwDopgDQTQGAxrW2mwIAqSP13TRfXeKJstdmucrYw7DnMVmOZ3IrOj7Pr+zgsie2CtpIO2Ft7VzWhPYfMsdv/Hfy6I4/R6baH6N52E1F/wTsu6n4C+pc30lo/rko+X4A3RQAuqMymrspAHTT/O+mANA9Z9ne7imLd66NzLBOCEwyl1EAKBs9a3sZBYDSX977Yrp94+tJFALG3PzrAzMpAJxLAWAJBYAlFACWUABYQgGA1C1RFTT9Im/qpntTRrds0eY5XghLNL2oUNb+jsLXJ+FJ9m9DEuz/CNbZ3ghLsL6izWt+oWzGthcmzHvwrvHzdo1yL6fa/JZ1mvwWLjSJnXrab3ka+RAAPAACgAABQDrOWfqQYu7yh8+dunj3xtjsxj/xPdbdxd+9W57fqh5IrOPfes5XU/9tgN7yub/G9J6fqv7VQLVpizqref3cpQ+tXbnmwKVUoMerch2VicUNV+ZMat1cXNXxpa6okaMA4Cr0/PF8Gl9avqhwcv5aM3+Z3Yg0Ow3X/E9fjeldP435z8F6y+GoFNvrmtyGl9LLmw9kjXN2501sr1l541M1lvY3q+uaX59xw10HddPO26PLq9hsKJq2KSOvcmN28pi2nPjc5tygRFsuBZKp8y7dd/nkRTtWF0zpXKMubFoTmW5dO2l+16NzL972r0kLtn5dOK2bSylv41T5TVxkegMXZGB7HdheDvofiKul+eoKJMfDVZ/QwuYxf0iCTZsbfe4krN39mePY78afnsh/Ty0nZ9/Ffx/bC+J28ufZMXp2ESOaX1x4aiMXn+vkksrauPwpXdykhTu4khmbXwhOMt/upzetCUqyrUks61gzeua26yfO37l88qKdczLGbiyPSLbnaguaclPGOLPTxnakZ0/cmFw0pSNhwaW7dXfVv6KpaXw9w9hyuGzO0r0riio31Siz7HX+6hp7VKr18bjMhpdGpTY8GJ1sd8alWk1FFRtrlv3iyZrVtx9aQsLdyykV/3WavGYKAOzqkzQNngUBwAMgAAgQAKQjNM3uOyq7cW1UZsO7VARYxzYqGmx3OhUIvlCz891FV2pnT+gBHp1hfz+tvO05fVHz/dGptnPjMxqmppY4ZxVObrudinRrfJZjV2ii5clAnenlkETL36LSbUeCDWyPAX2+t5C5AoC/3sjFZNu50bO2cFMX73w/d9LGTm1+022G4paVuoLm82MzHOdo8hqqMsqbK2nY5RQACi6/8akCo/OPZXfXv7j0+rueubVq8Z5bKQDcQwGgI2/yxt0UAPZRAHg4ONFGrE9FpNpeCkuy/jY4wfKqn9b8Km05/z4q3fqhKs/xTWy24/uodAcXmmzjAhMsHP2dCqurI5xrXN3jy+YtO7TCTmukAty34AsBgAWG44Wb/n96P9+fq4gfJ/Ye+jzr58D3dWD/i33a6ZH/vamNXZ6YjXOg3kJF1sJFptm4uJxGFqY+kauNf5CpjK/KVaZX/fXmV4MTLa+GGKwvkIMhCdb9FAAepgDwMAWAXRQAOigAGCkArFt46Z6b1tW+fN19tt9Nq29+I3bu0r1JFAAKKAAUUgAooQBQQQGgigLABAoAZRQAiigAFCxf/WQBFf8E4uteTlkAUOdhDwAMHgQAAQKANNCWop62TCdTMe45fkoWcQcAvqe+KwD09uY+3rHJxd3O9xcQnvMFhj2y18IwafjBtPWmzGviItIdf/dRmQ5Sgd07c8mO9vIZm2/Q5zrPic9qnBGTYV0al2FuGZVmfjU82fo5K0iurWY2zHrOX2fmwlKoyOrNf6XXBxmZqv5goMF4UFvccHDOst0HV974ZNfCS/Ysr1q0teSaW5/Qr177TOrFq54YM27G1gnRBsuEIHXNBHncr8kDE6LTrdOnnb+jZvbFu5/Kr9z8lKGk/aXU8rZ/JY1u/U5T0HI0KqOBC0igLXkNK+a0LJ8wbQxbvllQYo+ucez9e+97+nIV/1MGAHrkAwDff8H9fYzw+d7XQlt/fb+r9300nL4BQPifPHH4wvt4wne7fzuee7jsuetzbJnw05g5CgJcbJaDnT74jbaw5V8Jxc43k8qanx09s/vxRSsf2Tftgj13+modk2SxdRPkMfdPiEs1Tcgb3zLh4qv3Tli3/tliEi22fPalLWhZp2WHAChgnbQMjnwIAB4AAUCAACANFAAuoQDwPK3wPzhxhU8rLUbYUj+xrR++mLl71xO2a5u/gh61M3zhoYKiruUSy5zc3KV7uOmLH+xS6CzjFl22e+nq256oLpzUtS3K0PhyoM78kq+m7rUAbd17AVrj574ayxG5ig2T9RKnYVHRicl0cDkVG7nU8tYWel3OUAAopwBQri1qKJ+zfHc5BYCCBcv3aCgARFAACFp29ROzll71xG4KAIdGJVoOUQA4RAGAPHBIoax9kbbq/y86veGTkCTbJ4EG638oqHxLjgYkWI75UeCQsy15flr7zQueu62vvn//KWKfFyP2/r7DEdP3vT+X2DApwNB8YeHIX2+moGT+gebZt4EJlv8GGsz/Dk2xfTwqq/FfoSkNf5ap7M9TADhEAeAQBYBD+RNaDlEAOETFfxMZK7Z89pVY1LzOUNTMhVP4O2kZHPkQADwAAoAAAcA7lVV1y4l/VJojNSzJPkuhqt3kut583y0+WmGdsJL/Kawws2PxAn43Njv+bOYUSvO3AVrTxwG6+jdkmtrHMie0P3HRlY++dM6S3eZAnWVe8bSum6ecu71dn+98I0Rn4/zU7Hh0HRdsoK38ZNu3IcmOjwMT7IflSuvjFAD20LD3qPMa95TP3rxn8qJtK1ff+pRqwrwtquQxTn3FvO1jJ8zeNic+s3GOPL5+DgUXF3qeOW5j7YQ52z7OHNvOhSVQsWJ7NeIeIBsITTu/i5xNt7DCFp1OOHts74mVXzZksRu4iEQjZyhq4CYv6OEWXrrnb0VTu35Fv8Ec+k3mRKda5uRN7p6TX9k1J6mscU50mmWOLLaWHq1d8dkOLjiRAqHod4xoCAAeAAFAgADgnaj4B5BoCgBXUgB41V9b95GrNz7rlU8rqt5dyCetwE6td/cxe81+ayqoKtYpz8wFJdg+VeU6ntcXOh4ITzVNSCx1Ti2e0nW1Mqux1V9jfiNQb303ONH+L3+d+Ss5FX85FWYKC1xcdhNnKG3/d8r4jheSxnXURGU2TaIAkEkFJFOd35hJASBz6dWPjF79y6eqJs7bUpVc7lxEAWDj+HO2HVZmNh6mAHCYir8LPffTGt8PSzYdCTawgFHLyWk83dfe53fBu3ePn830w6m5lwt+XrO9QTRv6bWr06GJi0hxcFFpTd/466zv0W9wWBa3/jAFgMP5k7sPUwA4nDS66TAFgMMUAA4rVPUf+eloGVH3Gb7nQADwAAgAAgQA7zQqrTGNrAhNtG4L1Ju+82UrU/7Oc2yLmH4nvoifRQDgj12z49Z1RwISTB+HJFneCEywssvu9qSVNe1IG91opRX5VUEJpjX0vfV+GuNztEI/xu6PH5Jo/SE0yfp+RKr11dhM23Oa/IbHDSWt29LGddpyp3X9cuyCbcsWXfbY1IoFOys1hU0zotPtCyOTbUsTilpuzRjbbonPabSEp9icKaPb/5Q2poOLSLK5Cjs/LcL48cV9A72maeWvPsfaWDESppX/uzD97jb4+fj5yQgBoDdguecxaxPa6X1sj0yIwcTpi1p5cbTFH2owC3dKFPpF8OsTYfieAwHAAyAACBAAvFN4omMR+R0V4S9k6g3H+CIZa6EVLFtBuw8DnGEBZCtvtmVHRddXbfxfXGbDb1PLWhtSy9pm54x1nlMwvsWRVOh4LjzZ/H+0df8vharuU1qRf8UuAUxtnDav8bvUMucTo6u67ztvxZ7rrvnl/nMXXronjwKAMmda16jzLn987LKrn6qmANCpKWzePSrD/hIFgPeDE8wfUZD4t0Jl+rdcafrMX2v+lgUKdjogGxc5myZ2Yx2+uNB09XZsY6/ZeAvjz/dxYH93E9phYPDzms3z/gGAYe9hv4nwPiry7BRPdjonu8ujv9rM+bKrA8aa+NMaFfHs4k7C+z0LAoAHQAAQIAB4jzttf50+d+UzC6Mym6/w11o6AnXW//hpaGXMrsPPr3TZsXsqlnxxFFZYfBGk16w4sr0EvZ0Bhd+Tf82e1/Lnj4ck278J0FmeCjVYmgsmde4fO33zk/rCxtrwZFNdfIb1megUy9/ZHgcq3lx6uZPTFjS8SgHAGplqtiQUNhmzx7VfOWPR9gWXX7Nv3SVX7TFnjXGulcfX/kIeX/OL2EzHhsxxGw8kFLe+EZ5q+7/gRMu/g/TmY74aoYC4i4u7oPDTxI41C7v3+QLE0Pj2FiLCb5EKn+t9D2HD6J1elxOuZ8+ohM/R39wd4Nipf+wc9cg0Ozcqs4GLz23kVHmNnKbAwSWWtXCZkzZy2ZM7udwpzCYuf2oXVz67h5u8aPtpq+Dt4CrO3clNWrSTm7BgJztPn8tjw63cxGVN6uSSxjg5XXETR2GJP+OC3ZwoOtPBsbMZwlIdXJDBxi6zy487P0/ce374aXdPZx/839h72O/NuOZJrxM+654v/fDzXSDaTp9jj+7DMvTcdYaEGztjgt0Miu0FoO86sYOdJ0AA8AAIAAIEAO9BAWAjBYD9UVnNH8rVpm/kKtNRvkd7b4Gj5zzhNVuZs6LA9giwu8Bp6TUfAtjvyHajs2P87DU7PXADF5Fu4zQlzn+ri1uuqZyzNXPhhbu3TZm39Uh8tu1rH2XN13Jl/RG50vgDfcexlNGt3HmX7uaWrNxrpOIfGpFiDqYAEJwzvt1/yfKdhotX7Oqcc17PN7ocx1cUAP5HAYD5WqGqOyJX1f9AK1JSf5QfF3782Xiz4nG8IPcWpL56p5O9l3VUZB3SbK5H4d4Arr8TftrY8AkVPb7w8AVJ+Cy7aRC7zj29l22NsgAUlmLnYqjAanKbuZSyNi6Xin1JFRX4WZu4CXM6uHMu2sYtu+4x7rKbnuBW3vokd+XaA9w1tz/DVde/yFmdr502i/N3nLntD5y5/Y+csfUNrqbxj9wv73mOW3XTfu7KW57ill+/n5u7fCc35bwt3KQFW7mymZu5nIoOLmNCB5c2vpPTl7RxsdktXLCBTT9NXyz9ljGEPfJBgKbfXYzd3MsCO0zU/7oELGDxZ3yw1+w3oPnS9/Puecq/1zX83mtMsM/yZ3ewszyE34Bes7+7AoDwGf59ruG5lluPhADgARAABAgA3mPl7S/0TDxv78Gw1IbPWcc8duta1xYtrVhF0e/Fr3iF385dDPnz0ms5tuUdnGjjcmirc+Fle7lzlu/mplyw86vM8Z27w3SOupTSttfTRrd9G51q/yAq1f4nan81fWznXio6tRnj2i0LL9ndM+/SvY4pF+69I2Vc2x3+uto75KraO4ITTDWppS2/T6et5YgkVgjcBcddnITxYePIioO7uLhf8+h1XzStbJr9tBZ+yzcs2c5FpTVwESkNX4YlNnwQkmD7vxC99XBMuv2wvrDpcPbEzsO5FV3Pq/Kb2gINpvUUOu6lQlRNAaCaClM1FalqH6Wl2kdFlNSmrKsOTDBXh6fYqykAVGvzmqvTxrRV51V0VpfN6KoeP7urumLexuq5y7ZXr7hxf/WVtz5Vver2p6p/se6Z6uvverb6fsvL1c2dfzgtTaSRNGz6Y7Wj681q+6Y/VZvb3qy+4/7nq1ff+mT1Nbc9XX3ZTU9WL1ixq7rq/J7qyYu2VY85Z0t1XuXG6qxJG6szJnZWJ5S2V8dlt1TTb1FNBb2aCn81BQDXY1wdTZ+RsOlkjy4RKXZLQpGzJ7nM+XTamNbDymzH4dAE4+FAbf3hQJ3x7ahU2+exFH4iUlkPfTvnr7PwF0ByFX6GhQJ65Au5e+ue/Vb0W/KHjui9vXtjXMsme4/rbwJ+OORHl9sRDQHAAyAACBAAvMc5l+7qyZu66WCQwf45u/Oei9iKtM/vJays+a2+uBp6fw1tBddyCloBh1Ahjctu5i68+nGua/dfuPscv+WuWPsklzep6wdFrOUHhcr8vZ/W/O/wBPvLuWO7d1172/PNGxxvXHbrfS8px8zZmjJu/vb5FYsf3DT5gj1Hk8e2UsGo5Xv/n7Bl6S787jb3+PS+ZluJrLizMwfqj8mUtaw/ww9UJASmH6iY/CBXWWhcbEdCEh1HRmU0HdHktxxJGe08klTi/Lu+oPlFbY7jEV22dUvJZOeWeUu2brl+7cEtv6773QN1ttfGbNn2ShhRiM1TKVlvez2RzLn29oNrL1n92JaJszZtScg2bYlLNW6JTTPvSRvtfDdrfMeRhGLnkbjsxiPhydYjATrz9/Tb0O9gJlbh0fgD/UZH5fH1x+TxdcfkFChdQaAP914p/vdmwcC9d8YdKIT3nbTsjngIAB4AAUCAAOA9Zl+6mwJANwWAhs/5lSm/cqXfhN+i7r+iEray+ELLCjC18VtjdZwyp5EbP2crN2PJLm7ust3cvEse4haseJibfO4OrrCq61ttQfPz/ipzG21hm1PGtNdPmr21adbiBzuqzt/bVTJ9S2tsltUUlmxuCU9xPBif23g4oaT5WGS6lT/v33WFPYZ9N9sadL9m338iOY2fL23VhyVauLgM2zF9QdOnyaWtfx6V5ng0QGveGJXm2KjMbWrTFjkdyryW9VT8byVrKACsoQCwhgLAmqRS55UUAC6iALCIAsDs0snO2XOXbJ19w20HZ1MAmEgBQEXF35/IxOaplFDxDyfJFABGUwCYTQFgNgWA2RQAZlMAmJ82xrmSAsAaCgBrKACsoQCwJibTsS6ptNWcXNrWnFDk7IjJaNjoT7+NrrDlNzkTOz+g+f9fZU4DF55k4/w1bK8U+23p93avL3qXBbb3QCj+/HsEJyyzHgEBwAMgAAgQALzH7Ev39uRP20IBoPFz/phrTI3rmC+/wu23ouJXuGyLi/7O307XxPlqrFxooo0rqNzEXXHTE9yNdz/N3firp7mpi3cciUhp+F9QgvU/vhrje8GJ5kZNUcPFY2dvnXHZ9U/OuXHd03dcsHJfW/Lojr0RqbY/hCbWf8XO8ecPQVC4kMfdz+9dcK3o3ePAVvZmTqGi71Ubv1eoTf+Vq02f+aiMn1AR+Jihto8DteaPlZm2j9NLGz4qn97125nnP7i9sKLrJmVGw9xx53TPXbJq74xb7z84rqbp5TQSJDZfYPC0bvpjNCm+v+65yutu2Td72sLuufHZjrlV5++6f/EVjzwzcd62t7LHd3ysymn+ODjB9rGvqv5jCpw8maruU4Wm/nNfrelrCg1Hffn7KfRZRj0TAoAHQAAQIAB4DxYA8qZuFvYAsN2qrOiyAi+youK3vlkRpgKtruUCE8xcWnkbd+Gqh7glV+3mxs1u54qr2rmiqk1c6YzuP5XP2rI9eXTrvSFJ1lVF07c0jZ+/4wlDSeveUWkN+/TFHS9qCtvepL/91V9r/MSPL+j1nEzFDilsoADArsLHjgmz0MG28Gg5UdWzy8lyqoIWLqW84/3UsRs364pb7w40WFdR8V/BUABYQQFgBQWAFRQALqUAcB4FgBkUAAooABgoABgoAOgpAKio+EcSye/GH2pU/ANILAUADQUAAwUAQ1yWw0ABYAwFgPkUAC6kALCCAsAKCgArKACsoGWSNyq7YU1WZXddduXGJ9MntvwvPtfGKdTu0//67A3wLAgAHgABQIAA4D3cASCQBQB+BUoBgN/CF1ZO7uOu/K5/V6e5IIOZi0izcLTS5ibM2cLdYzzEXb/ucS53koPTFlg5TUEzVzi164Xlqx/dMHPJzkXxeY3FExbu2jJu3g5OmdPkOnVLye7axnrZ1/Gnb/mpLGyr/ohMvf6//traL0P1pi8D1JYPZfHWtykAvE3j9LaPqvbtkBTz21kVnW9XnLtr39Jrn1x+Z91rmQRb8RKxYdM7sWT8hTc8uq7i/K7fpoxreNtPs/5tCgC0jJiJiZYT4zv+evNHFAy/VGhNX8rUxq8UGtP3cv70VlqOe5fpfsv3CcTaRJzYm/9sIQB4AAQAAQKA9zgeABxCAGC7/xm2AmS/DQsE9EivZUoLF5LYwOVUbOLGze3hSqZ2c2Nn9nCzL9rNLb3mEe6aW5+kIHCAW3PX09zilfs+zq/s+qMyt/GAXF23JyrD/n/s9rHBtAUvp2EpaMueYcd3A3UmLjqtgYtKsf0rSFf3kqGw8dC4GVsOZZVvXE8BYCEFgIU0XgspACwMTjEvzJq8aSEFgCkUAJKp+EcQbMVLBBX/QBK/5IZH8ykAzKYAsJACwEIKALSMmIlpYUiSbSkte03F0zYfistpOESB9Q8R6fbPw1LtHAUCKrjuZZsIAUBOoVROAbe3Eyx/CIweGX4PFMMOf7kJexvEC/qZQgDwAAgAAgQA7+EKAN39AgD9Jvyu/jpOptrAKVS0ha5hN+BpoK37dir+27l5l+zlFizby81YvIsrm76FO+eiPdwt9xziz13/tfEFbuGKvZwqr5kLSaKtfBoOOz0wMMH0Q4jB/N9Qg+XjEJ31b4Eay59oq/+10ETLy5rc5pdV2Y27Iwym2tLKTfdfvnr//SuvfaJCbJwBfsyVNx4IJedecMUj96eXt94fkWqxx+c17R+V3fiyn970slxT/3s/rfHtQIPpH6Epls+CDeZvAmn59mOnwcYLt5fu7WjYh7v484elhADA7yn42RAAPAACgAABwHuIBgB+xWal4s92+ddxQQkWLjq9kUufsIkrPWcrl1/ZzU2ct51bfdsBvtPfosv3cBULe7jCaRu53MkdXPakjeze71yQwch26/OdBdn59QlFrV9nju84XDCl86HMCV3mhNKN14en2OeFJFoqKQBUUgAopwCQSwEgh4o/Eys2zgA/hoq/L9FQAMhJK2/NCU+1FCjzmsaPym6opABQGZ1hv8BQ7FybO6mtrWxGx29Sy5v+Hpdt5UIMrPizIs+KMq2X+MJP/xNsbxi/B8x1jQI565vCXwfjhCL+cyAAeAAEAAECgPc4VQBgt2cNTLByEWlWblS6g9PktfCn9C1cuY/Lm9zF5U7s5Hf7X37j49yMC3dQ0W/jQpPqubBkM3+cPzLV9q5cVbOfVpz75UrL/vjslv1Z4zftHTenxzxr6a7rZyx7eO70S57II6Fi4wUwWGactyuWlM25aPtFC5Zvu7tkelubtti2PyzFQsuraT8V5P0KrfE3kakN/2KHpgK07NAAu+oj/V+wQwWx9BwBQHIQAAQIAN5DPACwc+9NXEyOg8uoaOUSS5q55KIW7sKrHuZuuPsZbuyszZyairyusJXT5LdyozKauLBEGxegruOS6H3TF+3mKubuaKMAUEQBoIgCQBEFgKKscZsKxs3uSacAoKcAEMuKP8HxexhSVPz9SPjci7YrKQAkFU9vy9KV2IsoANDyaiqiglykL2qZO+GcbfvLpm7mYtIsrhsNsb0D7OJDsfR/wq5AKF7MzwYCgAdAABAgAHiPucsf6imYsvlgcG8AqOP8dSbakrdxhrJmrmhGB5cx1smllLZws5bs5Jas2vd9fsXGf8ekO/4Rl9n8fnRa8x/91faH5XGm7X5xtdszR7dtv2DFY9uXXfnEhWLfB+AJzl32cDxZM3X+ju2qLOt2CgDbfeIt2wN1jqdi0hr/Ep5k+4evxvihQmP8kt3wib8PAX/orK/+hb5vO1vv9f4NAcADIAAIEAC8x8Klj/QUT+45GEoBQK4088c5I1LtnKG0lcue1M6VTu/gsia2cYllTmpr4bSFjf+LSrX+Pj7L8fj4WT2P0pZUbfa4TRMpACRTAEimAJBMASCZAkC02PcBeAIq/r5ESQEgmQJAMgWAZFm8Jbm0snvRjAXbNuZPaH88LMn0dJDe/H/BCbZjvhrWd4CKO99ngGHPad3mxl9hk7UJ7ezsGna2Dd+OAOAJEAAECADeY9HF+3qKKzcfDDHYPmc3xQlJsnMxWY1cQrGTy6/s5CbN33K0dEbX2xkT2ver8ht7QpPMtkCd8TZllv3qmYt3XHXpNY/NIqPEhg3gbZau2JtEloyt2nR1ZIrp2hCD+R7632kJTbLtDE+1PaPKb3lfV9TKhSfbOF8Vu5AVK/C0juuLP82WcbchAHgCBAABAoD3WLhsT0/RlE0Hg5LMnwclWTllnpM0c3FZDVzhlE3c3It3f3/ORQ9umbJ450WjZ20pDE00R1MAiIjPsofNOG9HKBX/ICIXGzaAt6Hi70tCxs/oCgtPNoZRAIgMNdhHlc3oGj9pQc+qmRc/eGDakl1ccqmTC9aaOF+2N4C/HTIr+Gyrf4PwnO0J4Lf+EQA8BAKAAAHAe6y6YV/Puct3Hiyf2f157qTOw4ay9gZVXktNbKajhgJAzbzle9eTC+Ys35tFosSGASB1cy7eqZyzbFfxgpUPrTxn2e6a1NGtNSE6Uw0FgJpwg6VHn2/7QJll4fw19ZyC1nf+6nrOT1X/CoWAejJVbJgwsiAACBAAvMd99z3Wc8dd+w9ef8uTn6++6amuK67br1PnOxUUABQZ49oV85fvVcxdvldGxV/yd74D+DEUAmQLVz4kX3TlwwoKAIrwBLPCT2lSzFjYUXnOeRtfKJ3s5MISbFyAysiF62q5CF2tMVhTG0QBAP9bHgABQIAA4D3uv//x+evu3n/xDbc+ddN1txyYR8LE3gcAZ2fO4k49uaS0svV2CgC3ByiNt1MAuD1SXzuN4DRYD4EAIEAAAAAAKUEAECAAAACAlCAACBAAAABAShAABAgAAAAgJQgAAgQAAACQEgQAAQIAAABICQKAAAEAAACkBAFAgAAAAABSggAgQAAAAAApQQAQIAAAAICUIAAIEAAAAEBKEAAECAAAACAlCAACBAAAAJASBAABAgAAAEgJAoAAAQAAAKQEAUCAAAAAAFKCACBAAAAAAClBABAgAAAAgJQgAAgQAAAAQEoQAAQIAAAAICUIAAIEAAAAkBIEAAECAAAASAkCgAABAAAApAQBQIAAAAAAUoIAIEAAAAAAKUEAECAAAACAlCAACBAAAABAShAABAgAAAAgJQgAAgQAAACQEgQAAQIAAABICQKAAAEAAACkBAFAgAAAAABSggAgQAAAAAApQQAQIAAAAICUIAAIEAAAAEBKEAAEgxEALl29nzvw/N8BAABGHFajxGrXz4EAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBCAAAAAAShAAAAAAgQQgAAAAAEoQAAAAAIEEIAAAAABKEAAAAACBBHhkAAAAAYOQSbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8G6ijQAAAODdRBsBAADAu4k2AgAAgHcTbQQAAADvJtoIAAAA3k20EQAAALybaCMAAAB4N9FGAAAA8Gacz/8DA6+zSJMsMSQAAAAASUVORK5CYII=Dynamics CRM PortalGE.PEllipsefalseAnyAnyfalsefalseSelectAzure IaaSGenericHost TechnologiesVirtualDynamic97da4742-4e59-441a-994c-a1490d70dd28ListA representation of a machine e.g., on-prem or azure server that hosts an applicationfalseSE.P.TMCore.HostCentered on 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HostGE.PEllipsefalseAnyAnyfalseA representation of Identity Server falseSE.P.TMCore.IdSrvCentered on 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Identity ServerGE.PEllipsefalseAnyAnyfalsefalseSelectGenericNodeJsCSharpIoT Cloud Gateway TechnologiesVirtualDynamic9c1cc117-8938-40ca-bb0a-23d6002ddcf0ListfalseSelectAzure IoT HubAzure Event HubsAzure IoT protocol gatewayCustom cloud gatewayGateway choiceVirtualDynamic1e48cf4e-8ae0-4455-9a2b-c158693877f3ListA high-scale service enabling secure bidirectional communication from variety of devices.falseSE.GP.TMCore.IoTCloudGatewayCentered on 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 Cloud GatewayGE.PEllipsefalseAnyAnyfalseA specialized device that acts as a communication enabler between an IoT device and a cloud backendfalseSE.GP.TMCore.IoTFieldGatewayCentered on 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IoT Field GatewayGE.PEllipsefalseAnyAnyfalsefalseSelectGenericNET Framework 3WCF TechnologiesVirtualDynamicb28a8275-e02f-48b5-888c-87d03d5b01beListfalseSelectTransportMessageSecurity ModeVirtualDynamic6644d5f0-e070-4350-a13b-4d36dcb86531ListfalseSelectNonewindows username certificateClient Credential TypeVirtualDynamic18aa87e2-8648-48e7-a197-46f0b65a81d1ListfalseSelectNoneEncryptAndSign SignProtection LevelVirtualDynamicb81b55b0-ca7b-41df-8cfa-d644e1df1c92ListfalseSelectBasicHttpBindingWSHttpBinding NetTcpBinding WSFederationHttpBinding BindingVirtualDynamiccdaf2be7-2522-458a-8401-64055c7bdec3ListWindows Communication Foundation WCF is Microsoft s unified programming model for building service oriented applications. falseSE.P.TMCore.WCFCentered on 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WCFGE.PEllipsefalseAnyAnyfalsefalseSelectGenericMVC 5MVC 6Web API TechnologiesVirtualDynamic1e972c93-2bd6-4915-8f5f-f46fd9f9399dListfalseSelectOn PremAzureHosting environmentVirtualDynamic6c5d51b0-91b1-45ca-aebd-3238f93db3b8ListfalseSelectADFSAzure ADIdentity ProviderVirtualDynamic3175328a-d229-4546-887b-39b914a75dd8ListWeb APIfalseSE.P.TMCore.WebAPICentered on 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Web APIGE.PEllipsefalseAnyAnyfalsefalseSelectWeb AppWeb App for ContainersTypeVirtualDynamice8c6c66c-d75f-4ddf-bc22-3dad2a5934dbListfalseSelectTrueFalseAzure Web App Processes XMLVirtualDynamic049c845a-28c2-46f8-bda2-971ff7df9bd4ListfalseSelectTrueFalseAzure Web App Processes JSONVirtualDynamicd69db950-2372-4bd3-8328-f751f0b04c03ListfalseSelectAllow access from all networksAllow access from selected networksAzure Web App Firewall SettingsVirtualDynamic327ab565-9b38-4f6a-8171-6ab7deb2246bListfalseSelectTrueFalseAzure Web App CORS UsedVirtualDynamicf6b0309d-2020-4c3f-838f-5ab8ea0d2194ListWeb application built and hosted on Azure App ServicefalseSE.P.TMCore.AzureAppServiceWebAppCentered on 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Azure App Service Web AppGE.PEllipsefalseAnyAnyfalsefalseSelectTrueFalseAzure API App Processes XMLVirtualDynamic0eb10857-97b7-4c8c-8fdd-c289b7921a7eListfalseSelectTrueFalseAzure API App Processes JSONVirtualDynamic0945adcf-1cfd-432f-8032-05391ab62336ListfalseSelectAllow access from all networksAllow access from selected networksAzure API App Firewall SettingsVirtualDynamiccb0fca77-c600-4622-b9a5-118107fcd9ddListfalseSelectTrueFalseAzure API App CORS UsedVirtualDynamic3f4a2250-9087-44c1-9fb7-61e9eb1e4df7ListWeb API built and hosted on Azure App ServicefalseSE.P.TMCore.AzureAppServiceApiAppCentered on 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Azure App Service API AppGE.PEllipsefalseAnyAnyfalsefalseSelectTrueFalseAzure Mobile App Processes XMLVirtualDynamic6c7ab607-e310-4d74-aa5b-397d87f02ee9ListfalseSelectTrueFalseAzure Mobile App Processes JSONVirtualDynamic015d94e3-d54e-4c09-9ce2-2731a0dc86f0ListfalseSelectAllow access from all networksAllow access from selected networksAzure Mobile App Firewall SettingsVirtualDynamic9b54ed83-3970-475b-97a0-be7641051497ListfalseSelectTrueFalseAzure Mobile App CORS UsedVirtualDynamic6ddbac5e-2e11-4b88-b917-587749ea4721ListMobile app backend service built and hosted on Azure App ServicefalseSE.P.TMCore.AzureAppServiceMobileAppCentered on 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Azure App Service Mobile AppGE.PEllipsefalseAnyAnyfalsefalseSelectGenericWeb FormsMVC5MVC6Web Application TechnologiesVirtualDynamicf9960f99-8659-4776-90d7-e454ef832db7ListfalseSelectOnPremAzureEnvironmentTypeVirtualDynamic80fe9520-5f00-4480-ad47-f2fd75dede82ListfalseSelectYesNoProcesses XMLVirtualDynamicdf53c172-b70c-412c-9e99-a6fbc10748eeListWeb ApplicationfalseSE.P.TMCore.WebAppCentered on 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DEIAIgQANZhixECAO7kjieMQQBAhACwDluMEABwJ3c8YQwCACIEgHXYYoQAgDu54wljEAAQIQCswxYjBADcyR1PGIMAgAgBYB22GCEA4E7ueMIYBABECADrsMUIAQB3cscTxiAAIEIAWIctRggAuJM7njAGAQARAsA6bDFCAMCd3PGEMQgAiBAA1mGLEQIA7uSOJ4xBAECEALAOW4wQAHAndzxhDAIAIgSAddhihACAO7njCWMQABAhAKzDFiMEANzJHU8YgwCACAFgHbYYIQDgTu54whgEAEQIAOuwxQgBAHdyxxPGIAAgQgBYhy1GCAC4kzueMAYBABECwDpsMUIAwJ3c8YQxCACIEADWYYsRAgDu5I4njEEAQIQAsA5bjBAAcCd3PGEMAgAiBIB12GKEAIA7ueMJYxAAECEArMMWIwQA3MkdTxiDAIAIAWAdthghAOBO7njCGAQARAgA67DFCAEAd3LHE8YgACBCAFiHLUYIALiTO54wBgEAEQLAOmwxQgDAndzxhDEIAIgQANZhixECAO7kjieMQQBAhACwDluMEABwJ3c8YQwCACIEgHXYYoQAgDu54wljEAAQIQCswxYjBADcyR1PGIMAgAgBYB22GCEA4E7ueMIYBABECADrsMUIAQB3cscTxiAAIEIAWIctRggAuJM7njAGAQARAsA6bDFCAMCd3PGEMQgAiBAA1mGLEQIA7uSOJ4xBAECEALAOW4wQAHAndzxhDAIAIgSAddhihACAO7njCWMQABAhAKzDFiMEANzJHU8YgwCACAFgHbYYIQDgTu54whgEAEQIAOuwxQgBAHdyxxPGIAAgQgBYhy1GCAC4kzueMAYBABECwDpsMUIAwJ3c8YQxCACIEADWYYsRAgDu5I4njEEAQOTf//73+08++cQePw4BYBxbjBAAcCd3PGEMAgAe9csvv7z/17/+9f7rr79+//HHH9vjSQgA49hihACAO7njCWMQAJD1008/vf/nP//5/vPPP//gmCIAjGOLEQIA7uSOJ4xBAEAL6h3QsaShAgLAOLYYIQDgTu54whgEALT2888/v/w//n9DX7YYIQDgTu54whgEAGAfthghAOBO7njCGAQAYB+2GCEA4E7ueMIYBABgH7YYIQDgTu54whgEAGAfthghAOBO7njCGASAMX788cf37969+/9++OGHP36LyH/+8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 ApplicationGE.PEllipsefalseAnyAnyfalseA representation of Azure IaaS VM Trust BoundaryfalseSE.TB.TMCore.AzureIaaSVMTrustBoundaryBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCAzure IaaS VM Trust BoundaryGE.TB.BBorderBoundaryfalseAnyAnyfalseA border representation of Azure Trust Boundary, also referred to as Azure Services ZonefalseSE.TB.TMCore.AzureTrustBoundaryBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCAzure Trust BoundaryGE.TB.BBorderBoundaryfalseAnyAnyfalseA border representation of a Cloud Gateway Zone, also referred to as Cloud Gateway Trust BoundaryfalseSE.TB.TMCore.IoTCloudGatewayZoneBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCIoT Cloud Gateway ZoneGE.TB.BBorderBoundaryfalseAnyAnyfalseA border representation of a Device Zone, also referred to as Device Trust BoundaryfalseSE.TB.TMCore.IoTDeviceZoneBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCIoT Device ZoneGE.TB.BBorderBoundaryfalseAnyAnyfalseA border representation of a Field Gateway Zone, also referred to as Field Gateway Trust BoundaryfalseSE.TB.TMCore.IoTFieldGatewayZoneBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCIoT Field Gateway ZoneGE.TB.BBorderBoundaryfalseAnyAnyfalseA border representation of a Local User Zone, also referred to as Local User Trust BoundaryfalseSE.TB.TMCore.LocalUserTrustBoundaryBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCLocal User ZoneGE.TB.BBorderBoundaryfalseAnyAnyfalseA representation of an end-users machine trust boundaryfalseSE.TB.TMCore.MachineTrustBoundaryBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCMachine Trust BoundaryGE.TB.BBorderBoundaryfalseAnyAnyfalseA border representation of a Remote User Zone, also referred to as Remote User Trust BoundaryfalseSE.TB.TMCore.RemoteUserTrustBoundaryBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCRemote User ZoneGE.TB.BBorderBoundaryfalseAnyAnyfalsefalseSelectAzureStand aloneOther cloudsEnvironmentVirtualDynamic1e5ffbf5-f5bc-4fe5-a73b-dc516d274c82ListA representation of Service Fabric Cluster for stand-alone or cloud environmentsfalseSE.TB.TMCore.ServiceFabricBefore labeliVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABGSURBVDhPY/hPIWBQ9Ev6z2jqDccPnr0ESxArzoDMAeEDZy+DFRIrDjeAVDCcDIDyyQajgTioAhGEQekdHx+bGIUGeP8HAJ4fIfJijo6MAAAAAElFTkSuQmCCService Fabric Trust BoundaryGE.TB.BBorderBoundaryfalseAnyAnyfalseDDenial of ServiceDenial of Service happens when the process or a datastore is not able to service incoming requests or perform up to specfalseEElevation of PrivilegesA user subject gains increased capability or privilege by taking advantage of an implementation bugfalseIInformation DisclosureInformation disclosure happens when the information can be read by an unauthorized partyfalseRRepudiationRepudiation threats involve an adversary denying that something happenedfalseSSpoofingSpoofing is when a process or entity is something other than its claimed identity. Examples include substituting a process, a file, website or a network addressfalseTTamperingTampering is the act of altering the bits. Tampering with a process involves changing bits in the running process. Similarly, Tampering with a data flow involves changing bits on the wire or between two running processestruetrueTitlefalse22222222-2222-2222-2222-2222222222220UserThreatCategoryfalse22222222-2222-2222-2222-2222222222220UserThreatShortDescriptiontrue22222222-2222-2222-2222-2222222222220UserThreatDescriptionfalse22222222-2222-2222-2222-2222222222220StateInformationfalse22222222-2222-2222-2222-2222222222220InteractionStringfalse22222222-2222-2222-2222-2222222222220PossibleMitigationsfalse22222222-2222-2222-2222-2222222222222PriorityfalseHighMediumLow22222222-2222-2222-2222-2222222222221SDLPhasefalseDesignImplementation22222222-2222-2222-2222-2222222222221falseDThe default cache that Identity Server uses is an in-memory cache that relies on a static store, available process-wide. While this works for native applications, it does not scale for mid tier and backend applications. This can cause availability issues and result in denial of service either by the influence of an adversary or by the large scale of application's users. target is 'SE.P.TMCore.IdSrv'TH112UserThreatDescriptionfalseThe default cache that Identity Server uses is an in-memory cache that relies on a static store, available process-wide. While this works for native applications, it does not scale for mid tier and backend applications. This can cause availability issues and result in denial of service either by the influence of an adversary or by the large scale of application's users. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseOverride the default Identity Server token cache with a scalable alternative. Refer: <a href="https://aka.ms/tmtauthn#override-token">https://aka.ms/tmtauthn#override-token</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can leverage the weak scalability of Identity Server's token cache and cause DoSfalseDAn Adversary can launch DoS attack on WCF if Throttling in not enabledtarget is 'SE.P.TMCore.WCF'TH130UserThreatDescriptionfalseAn Adversary can launch DoS attack on WCF if Throttling in not enabled22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable WCF's service throttling feature. Refer: <a href="https://aka.ms/tmtconfigmgmt#throttling">https://aka.ms/tmtconfigmgmt#throttling</a>22222222-2222-2222-2222-2222222222222PriorityfalseLow22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An Adversary can launch DoS attack on WCF if Throttling in not enabledfalseDFailure to restrict requests originating from third party domains may result in unauthorized actions or access of datasource is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp'TH26UserThreatDescriptionfalseFailure to restrict requests originating from third party domains may result in unauthorized actions or access of data22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that authenticated ASP.NET pages incorporate UI Redressing or clickjacking defences. Refer: <a href="https://aka.ms/tmtconfigmgmt#ui-defenses">https://aka.ms/tmtconfigmgmt#ui-defenses</a> Ensure that only trusted origins are allowed if CORS is enabled on ASP.NET Web Applications. Refer: <a href="https://aka.ms/tmtconfigmgmt#cors-aspnet">https://aka.ms/tmtconfigmgmt#cors-aspnet</a> Mitigate against Cross-Site Request Forgery (CSRF) attacks on ASP.NET web pages. Refer: <a href="https://aka.ms/tmtsmgmt#csrf-asp">https://aka.ms/tmtsmgmt#csrf-asp</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can perform action on behalf of other user due to lack of controls against cross domain requestsfalseDThe default cache that ADAL (Active Directory Authentication Library) uses is an in-memory cache that relies on a static store, available process-wide. While this works for native applications, it does not scale for mid tier and backend applications. This can cause availability issues and result in denial of service either by the influence of an adversary or by the large scale of application's users.target is 'SE.P.TMCore.AzureAD'TH91UserThreatDescriptionfalseThe default cache that ADAL (Active Directory Authentication Library) uses is an in-memory cache that relies on a static store, available process-wide. While this works for native applications, it does not scale for mid tier and backend applications. This can cause availability issues and result in denial of service either by the influence of an adversary or by the large scale of application's users.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseOverride the default ADAL token cache with a scalable alternative. Refer: <a href="https://aka.ms/tmtauthn#adal-scalable">https://aka.ms/tmtauthn#adal-scalable</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can leverage the weak scalability of token cache and cause DoSfalseEIf there is no restriction at network or host firewall level, to access the database then anyone can attempt to connect to the database from an unauthorized locationtarget is 'SE.DS.TMCore.SQL'TH1UserThreatDescriptionfalseIf there is no restriction at network or host firewall level, to access the database then anyone can attempt to connect to the database from an unauthorized location22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseConfigure a Windows Firewall for Database Engine Access. Refer: <a href="https://aka.ms/tmtconfigmgmt#firewall-db">https://aka.ms/tmtconfigmgmt#firewall-db</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to database due to lack of network access protectionfalseEDue to poorly configured account policies, adversary can launch brute force attacks on {target.Name} target is 'SE.DS.TMCore.AzureSQLDB'TH10UserThreatDescriptionfalseDue to poorly configured account policies, adversary can launch brute force attacks on {target.Name} 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseWhen possible use Azure Active Directory Authentication for connecting to SQL Database. Refer: <a href="https://aka.ms/tmt-th10a">https://aka.ms/tmt-th10a</a> Ensure that least-privileged accounts are used to connect to Database server. Refer: <a href="https://aka.ms/tmt-th10b">https://aka.ms/tmt-th10b</a> and <a href="https://aka.ms/tmt-th10c">https://aka.ms/tmt-th10c</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to Azure SQL database due to weak account policyfalseEAn adversary may jail break into a mobile device and gain elevated privilegessource is 'SE.EI.TMCore.Mobile'TH104UserThreatDescriptionfalseAn adversary may jail break into a mobile device and gain elevated privileges22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement implicit jailbreak or rooting detection. Refer: <a href="https://aka.ms/tmtauthz#rooting-detection">https://aka.ms/tmtauthz#rooting-detection</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may jail break into a mobile device and gain elevated privilegesfalseEAn adversary may gain unauthorized access to Web API due to poor access control checkstarget is 'SE.P.TMCore.WebAPI'TH110UserThreatDescriptionfalseAn adversary may gain unauthorized access to Web API due to poor access control checks22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement proper authorization mechanism in ASP.NET Web API. Refer: <a href="https://aka.ms/tmtauthz#authz-aspnet">https://aka.ms/tmtauthz#authz-aspnet</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to Web API due to poor access control checksfalseEAn adversary can gain unauthorized access to resources in Azure subscription. The adversary can be either a disgruntled internal user, or someone who has stolen the credentials of an Azure subscription.flow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.AzureTrustBoundary'TH116UserThreatDescriptionfalseAn adversary can gain unauthorized access to resources in Azure subscription. The adversary can be either a disgruntled internal user, or someone who has stolen the credentials of an Azure subscription.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable fine-grained access management to Azure Subscription using RBAC. Refer: <a href="https://aka.ms/tmtauthz#grained-rbac">https://aka.ms/tmtauthz#grained-rbac</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to resources in an Azure subscriptionfalseEAn adversary can bypass built in security through Custom Services or ASP.NET Pages which authenticate as a service accounttarget is 'SE.P.TMCore.DynamicsCRM'TH120UserThreatDescriptionfalseAn adversary can bypass built in security through Custom Services or ASP.NET Pages which authenticate as a service account22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseCheck service account privileges and check that the custom Services or ASP.NET Pages respect CRM's security. Refer: <a href="https://aka.ms/tmtcommsec#priv-aspnet">https://aka.ms/tmtcommsec#priv-aspnet</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can bypass built in security through Custom Services or ASP.NET Pages which authenticate as a service accountfalseEMisconfiguration of Security Roles, Business Unit or Teamstarget is 'SE.P.TMCore.DynamicsCRM'TH124UserThreatDescriptionfalseMisconfiguration of Security Roles, Business Unit or Teams22222222-2222-2222-2222-2222222222220PossibleMitigationsfalsePerform security modelling and use Field Level Security where required. Refer: <a href="https://aka.ms/tmtauthz#modeling-field">https://aka.ms/tmtauthz#modeling-field</a> Perform security modelling and use Business Units/Teams where required. Refer: <a href="https://aka.ms/tmtdata#modeling-teams">https://aka.ms/tmtdata#modeling-teams</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221Misconfiguration of Security Roles, Business Unit or TeamsfalseEMisuse of the Share featuretarget is 'SE.P.TMCore.DynamicsCRM'TH125UserThreatDescriptionfalseMisuse of the Share feature22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseMinimize access to share feature on critical entities. Refer: <a href="https://aka.ms/tmtdata#entities">https://aka.ms/tmtdata#entities</a> Train users on the risks associated with the Dynamics CRM Share feature and good security practices. Refer: <a href="https://aka.ms/tmtdata#good-practices">https://aka.ms/tmtdata#good-practices</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221Misuse of the Share featurefalseEUsers with CRM Portal access are inadvertently given access to sensitive records and datatarget is 'SE.P.TMCore.DynamicsCRMPortal'TH128UserThreatDescriptionfalseUsers with CRM Portal access are inadvertently given access to sensitive records and data22222222-2222-2222-2222-2222222222220PossibleMitigationsfalsePerform security modelling of portal accounts keeping in mind that the security model for the portal differs from the rest of CRM. Refer: <a href="https://aka.ms/tmtauthz#portal-security">https://aka.ms/tmtauthz#portal-security</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221Users with CRM Portal access are inadvertently given access to sensitive records and datafalseEAn adversary may gain unauthorized access to data on host machinesflow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No' flow crosses 'SE.TB.TMCore.MachineTrustBoundary'TH135UserThreatDescriptionfalseAn adversary may gain unauthorized access to data on host machines22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that proper ACLs are configured to restrict unauthorized access to data on the device. Refer: <a href="https://aka.ms/tmtauthz#acl-restricted-access">https://aka.ms/tmtauthz#acl-restricted-access</a> Ensure that sensitive user-specific application content is stored in user-profile directory. Refer: <a href="https://aka.ms/tmtauthz#sensitive-directory">https://aka.ms/tmtauthz#sensitive-directory</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to data on host machinesfalseEIf an application runs under a high-privileged account, it may provide an opportunity for an adversary to gain elevated privileges and execute malicious code on host machines. E.g., If the developed executable runs under the logged-in user's identity and the user has admin rights on the machine, the executable will be running with administrator privileges. Any unnoticed vulnerability in the application could be used by adversaries to execute malicious code on the host machines that run the application.flow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.MachineTrustBoundary'TH136UserThreatDescriptionfalseIf an application runs under a high-privileged account, it may provide an opportunity for an adversary to gain elevated privileges and execute malicious code on host machines. E.g., If the developed executable runs under the logged-in user's identity and the user has admin rights on the machine, the executable will be running with administrator privileges. Any unnoticed vulnerability in the application could be used by adversaries to execute malicious code on the host machines that run the application.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that the deployed applications are run with least privileges. . Refer: <a href="https://aka.ms/tmtauthz#deployed-privileges">https://aka.ms/tmtauthz#deployed-privileges</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain elevated privileges and execute malicious code on host machinesfalseEAn adversary can gain unauthorized access to {target.Name} due to weak access control restrictionstarget is 'SE.DS.TMCore.AzureStorage'TH17UserThreatDescriptionfalseAn adversary can gain unauthorized access to {target.Name} due to weak access control restrictions22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseGrant limited access to objects in Azure Storage using SAS or SAP. It is recommended to scope SAS and SAP to permit only the necessary permissions over a short period of time. Refer: <a href="https://aka.ms/tmt-th17a">https://aka.ms/tmt-th17a</a> and <a href="https://aka.ms/tmt-th17b">https://aka.ms/tmt-th17b</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to {target.Name} due to weak access control restrictionsfalseEDue to poorly configured account policies, adversary can launch brute force attacks on {target.Name}target is 'SE.DS.TMCore.SQL' and target.6047e74b-a4e1-4e5b-873e-3f7d8658d6b3 is 'OnPrem'TH2UserThreatDescriptionfalseDue to poorly configured account policies, adversary can launch brute force attacks on {target.Name}22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseWhen possible, use Windows Authentication for connecting to SQL Server. Refer: <a href="https://aka.ms/tmtauthn#win-authn-sql">https://aka.ms/tmtauthn#win-authn-sql</a> When SQL authentication mode is used, ensure that account and password policy are enforced on SQL server. Refer: <a href="https://aka.ms/tmtauthn#authn-account-pword">https://aka.ms/tmtauthn#authn-account-pword</a> Do not use SQL Authentication in contained databases. Refer: <a href="https://aka.ms/tmtauthn#autn-contained-db">https://aka.ms/tmtauthn#autn-contained-db</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to SQL database due to weak account policyfalseEFailure to restrict the privileges and access rights to the application to individuals who require the privileges or access rights may result into unauthorized use of data due to inappropriate rights settings and validation.source is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp'TH27UserThreatDescriptionfalseFailure to restrict the privileges and access rights to the application to individuals who require the privileges or access rights may result into unauthorized use of data due to inappropriate rights settings and validation.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that administrative interfaces are appropriately locked down. Refer: <a href="https://aka.ms/tmtauthn#admin-interface-lockdown">https://aka.ms/tmtauthn#admin-interface-lockdown</a> Enforce sequential step order when processing business logic flows. Refer: <a href="https://aka.ms/tmtauthz#sequential-logic">https://aka.ms/tmtauthz#sequential-logic</a> Ensure that proper authorization is in place and principle of least privileges is followed. Refer: <a href="https://aka.ms/tmtauthz#principle-least-privilege">https://aka.ms/tmtauthz#principle-least-privilege</a> Business logic and resource access authorization decisions should not be based on incoming request parameters. Refer: <a href="https://aka.ms/tmtauthz#logic-request-parameters">https://aka.ms/tmtauthz#logic-request-parameters</a> Ensure that content and resources are not enumerable or accessible via forceful browsing. Refer: <a href="https://aka.ms/tmtauthz#enumerable-browsing">https://aka.ms/tmtauthz#enumerable-browsing</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may bypass critical steps or perform actions on behalf of other users (victims) due to improper validation logicfalseEAn adversary may gain elevated privileges on the functionality of cloud gateway if SAS tokens with over-privileged permissions are used to connect(source is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway') and target is 'SE.GP.TMCore.IoTCloudGateway'TH37UserThreatDescriptionfalseAn adversary may gain elevated privileges on the functionality of cloud gateway if SAS tokens with over-privileged permissions are used to connect22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseConnect to Cloud Gateway using least-privileged tokens. Refer: <a href="https://aka.ms/tmtauthz#cloud-least-privileged">https://aka.ms/tmtauthz#cloud-least-privileged</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain elevated privileges on Cloud GatewayfalseEDatabase access should be configured with roles and privilege based on least privilege and need to know principle. target is 'SE.DS.TMCore.SQL' TH4UserThreatDescriptionfalseDatabase access should be configured with roles and privilege based on least privilege and need to know principle. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that least-privileged accounts are used to connect to Database server. Refer: <a href="https://aka.ms/tmtauthz#privileged-server">https://aka.ms/tmtauthz#privileged-server</a> Implement Row Level Security RLS to prevent tenants from accessing each others data. Refer: <a href="https://aka.ms/tmtauthz#rls-tenants">https://aka.ms/tmtauthz#rls-tenants</a> Sysadmin role should only have valid necessary users . Refer: <a href="https://aka.ms/tmtauthz#sysadmin-users">https://aka.ms/tmtauthz#sysadmin-users</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to database due to loose authorization rulesfalseEAn adversary may get access to admin interface or privileged services like WiFi, SSH, File shares, FTP etc., on a devicesource is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway'TH41UserThreatDescriptionfalseAn adversary may get access to admin interface or privileged services like WiFi, SSH, File shares, FTP etc., on a device22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that all admin interfaces are secured with strong credentials. Refer: <a href="https://aka.ms/tmtconfigmgmt#admin-strong">https://aka.ms/tmtconfigmgmt#admin-strong</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to privileged features on {source.Name}falseEAn adversary may leverage insufficient authorization checks on the device and execute unauthorized and sensitive commands remotely.(source is 'SE.GP.TMCore.IoTFieldGateway' or source is 'SE.GP.TMCore.IoTCloudGateway') and target is 'SE.EI.TMCore.IoTdevice'TH42UserThreatDescriptionfalseAn adversary may leverage insufficient authorization checks on the device and execute unauthorized and sensitive commands remotely.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalsePerform authorization checks in the device if it supports various actions that require different permission levels. Refer: <a href="https://aka.ms/tmtauthz#device-permission">https://aka.ms/tmtauthz#device-permission</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may trigger unauthorized commands on the devicefalseEAn adversary may use unused features or services on {target.Name} such as UI, USB port etc. Unused features increase the attack surface and serve as additional entry points for the adversarysource is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway'TH48UserThreatDescriptionfalseAn adversary may use unused features or services on {target.Name} such as UI, USB port etc. Unused features increase the attack surface and serve as additional entry points for the adversary22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that only the minimum services/features are enabled on devices. Refer: <a href="https://aka.ms/tmtconfigmgmt#min-enable">https://aka.ms/tmtconfigmgmt#min-enable</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may exploit unused services or features in {target.Name}falseEAn adversary may leverage insufficient authorization checks on the field gateway and execute unauthorized and sensitive commands remotely(source is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTCloudGateway') and target is 'SE.GP.TMCore.IoTFieldGateway'TH51UserThreatDescriptionfalseAn adversary may leverage insufficient authorization checks on the field gateway and execute unauthorized and sensitive commands remotely22222222-2222-2222-2222-2222222222220PossibleMitigationsfalsePerform authorization checks in the Field Gateway if it supports various actions that require different permission levels. Refer: <a href="https://aka.ms/tmtauthz#field-permission">https://aka.ms/tmtauthz#field-permission</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may trigger unauthorized commands on the field gatewayfalseEA compromised access key may permit an adversary to have over-privileged access to an {target.Name} instance target is 'SE.P.TMCore.AzureDocumentDB'TH54UserThreatDescriptionfalseA compromised access key may permit an adversary to have over-privileged access to an {target.Name} instance22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse resource (SAS like) tokens (derived using master keys) to connect to Cosmos DB instances whenever possible. Scope the resource tokens to permit only the privileges necessary (e.g. read-only). Store secrets in a secret storage solution (e.g. Azure Key Vault). Refer: <a href="https://aka.ms/tmt-th54">https://aka.ms/tmt-th54</a> 22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221A compromised access key may permit an adversary to have more access than intended to an {target.Name} instance falseIAn adversary may read content stored in {target.Name} instances through SQL injection based attackstarget is 'SE.P.TMCore.AzureDocumentDB' and target.d456e645-5642-41ad-857f-951af1a3d968 is 'SQL'TH56UserThreatDescriptionfalseAn adversary may read content stored in {target.Name} instances through SQL injection based attacks22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse parametrized SQL queries to query Cosmos DB instances. Refer: <a href="https://aka.ms/tmt-th56">https://aka.ms/tmt-th56</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may read content stored in {target.Name} instances through SQL injection based attacksfalseEAn adversary can gain unauthorized access to Azure Cosmos DB instances due to weak network security configurationtarget is 'SE.P.TMCore.AzureDocumentDB' and not target.b646c6da-6894-432a-8925-646ae6d1d0ea is 'Allow access from selected networks (excluding Azure)'TH57UserThreatDescriptionfalseAn adversary can gain unauthorized access to Azure Cosmos DB instances due to weak network security configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict access to Azure Cosmos DB instances by configuring account-level firewall rules to only permit connections from selected IP addresses where possible. Refer: <a href="https://aka.ms/tmt-th57">https://aka.ms/tmt-th57</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to Azure Cosmos DB instances due to weak network security configurationfalseEAn adversary may leverage insufficient authorization checks on the Event Hub (SAS token) and be able to listen (Read) to the Events and manage (change) configurations of the Event Hubtarget is 'SE.P.TMCore.AzureEventHub'TH59UserThreatDescriptionfalseAn adversary may leverage insufficient authorization checks on the Event Hub (SAS token) and be able to listen (Read) to the Events and manage (change) configurations of the Event Hub22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse a send-only permissions SAS Key for generating device tokens. Refer: <a href="https://aka.ms/tmtauthz#sendonly-sas">https://aka.ms/tmtauthz#sendonly-sas</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may exploit the permissions provisioned to the device token to gain elevated privilegesfalseEIf a token that grants direct access to the event hub is given to the device, it would be able to send messages directly to the eventhub without being subjected to throttling. It further exempts such a device from being able to be blacklisted.target is 'SE.P.TMCore.AzureEventHub'TH60UserThreatDescriptionfalseIf a token that grants direct access to the event hub is given to the device, it would be able to send messages directly to the eventhub without being subjected to throttling. It further exempts such a device from being able to be blacklisted.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseDo not use access tokens that provide direct access to the Event Hub. Refer: <a href="https://aka.ms/tmtauthz#access-tokens-hub">https://aka.ms/tmtauthz#access-tokens-hub</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary bypass the secure functionalities of the Event Hub if devices authenticate with tokens that give direct access to Event HubfalseEAn adversary may gain elevated privileges on the functionality of Event Hub if SAS keys with over-privileged permissions are used to connecttarget is 'SE.P.TMCore.AzureEventHub'TH62UserThreatDescriptionfalseAn adversary may gain elevated privileges on the functionality of Event Hub if SAS keys with over-privileged permissions are used to connect22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseConnect to Event Hub using SAS keys that have the minimum permissions required. Refer: <a href="https://aka.ms/tmtauthz#sas-minimum-permissions">https://aka.ms/tmtauthz#sas-minimum-permissions</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain elevated privileges on Event HubfalseEAn adversary can gain unauthorized access to all entities in {target.Name} tablestarget is 'SE.DS.TMCore.AzureStorage' and target.b3ece90f-c578-4a48-b4d4-89d97614e0d2 is 'Table'TH64UserThreatDescriptionfalseAn adversary can gain unauthorized access to all entities in {target.Name} tables22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseGrant fine-grained permission on a range of entities in Azure Table Storage. Refer: <a href="https://aka.ms/tmt-th64">https://aka.ms/tmt-th64</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to all entities in {target.Name}'s tablesfalseEAn adversary can gain unauthorized access to {target.Name} instances due to weak network configurationtarget is 'SE.DS.TMCore.AzureStorage' and target.eb012c7c-9201-40d2-989f-2aad423895a5 is 'Allow access from selective networks'target is 'SE.DS.TMCore.AzureStorage'TH140UserThreatDescriptionfalseAn adversary can gain unauthorized access to {target.Name} instances due to weak network configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseIt is recommended to restrict access to Azure Storage instances to selected networks where possible. <a href="https://aka.ms/tmt-th140">https://aka.ms/tmt-th140</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to {target.Name} instances due to weak network configurationfalseEAn adversary may gain unauthorized access to {target.Name} account in a subscriptiontarget is 'SE.DS.TMCore.AzureStorage'TH67UserThreatDescriptionfalseAn adversary may gain unauthorized access to {target.Name} account in a subscription22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseAssign the appropriate Role-Based Access Control (RBAC) role to users, groups and applications at the right scope for the Azure Storage instance. Refer: <a href="https://aka.ms/tmt-th67">https://aka.ms/tmt-th67</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to {target.Name} account in a subscriptionfalseEIf RBAC is not implemented on Service Fabric, clients may have over-privileged access on the fabric's cluster operationsflow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.ServiceFabric'TH71UserThreatDescriptionfalseIf RBAC is not implemented on Service Fabric, clients may have over-privileged access on the fabric's cluster operations22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict client's access to cluster operations using RBAC. Refer: <a href="https://aka.ms/tmtauthz#cluster-rbac">https://aka.ms/tmtauthz#cluster-rbac</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to Service Fabric cluster operationsfalseEAn adversary may gain unauthorized access to {target.Name} if connection is insecure(source is 'SE.P.TMCore.AzureDataFactory') and source.afe0080c-37dc-4d53-9edd-d0a163856bdc is 'Only Azure'(source is 'SE.P.TMCore.AzureDataFactory')TH90UserThreatDescriptionfalseAn adversary may gain unauthorized access to {target.Name} if connection is insecure22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse Data management gateway while connecting On Prem SQL Server to Azure Data Factory. Refer: <a href="https://aka.ms/tmtcommsec#sqlserver-factory">https://aka.ms/tmtcommsec#sqlserver-factory</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to {target.Name} if connection is insecurefalseIAn adversary can reverse weakly encrypted or hashed contenttarget is 'SE.P.TMCore.WebApp'TH101UserThreatDescriptionfalseAn adversary can reverse weakly encrypted or hashed content22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseDo not expose security details in error messages. Refer: <a href="https://aka.ms/tmtxmgmt#messages">https://aka.ms/tmtxmgmt#messages</a> Implement Default error handling page. Refer: <a href="https://aka.ms/tmtxmgmt#default">https://aka.ms/tmtxmgmt#default</a> Set Deployment Method to Retail in IIS. Refer: <a href="https://aka.ms/tmtxmgmt#deployment">https://aka.ms/tmtxmgmt#deployment</a> Use only approved symmetric block ciphers and key lengths. Refer: <a href="https://aka.ms/tmtcrypto#cipher-length">https://aka.ms/tmtcrypto#cipher-length</a> Use approved block cipher modes and initialization vectors for symmetric ciphers. Refer: <a href="https://aka.ms/tmtcrypto#vector-ciphers">https://aka.ms/tmtcrypto#vector-ciphers</a> Use approved asymmetric algorithms, key lengths, and padding. Refer: <a href="https://aka.ms/tmtcrypto#padding">https://aka.ms/tmtcrypto#padding</a> Use approved random number generators. Refer: <a href="https://aka.ms/tmtcrypto#numgen">https://aka.ms/tmtcrypto#numgen</a> Do not use symmetric stream ciphers. Refer: <a href="https://aka.ms/tmtcrypto#stream-ciphers">https://aka.ms/tmtcrypto#stream-ciphers</a> Use approved MAC/HMAC/keyed hash algorithms. Refer: <a href="https://aka.ms/tmtcrypto#mac-hash">https://aka.ms/tmtcrypto#mac-hash</a> Use only approved cryptographic hash functions. Refer: <a href="https://aka.ms/tmtcrypto#hash-functions">https://aka.ms/tmtcrypto#hash-functions</a> Verify X.509 certificates used to authenticate SSL, TLS, and DTLS connections. Refer: <a href="https://aka.ms/tmtcommsec#x509-ssltls">https://aka.ms/tmtcommsec#x509-ssltls</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can reverse weakly encrypted or hashed contentfalseIAn adversary may gain access to sensitive data from log filestarget is 'SE.P.TMCore.WebApp' TH102UserThreatDescriptionfalseAn adversary may gain access to sensitive data from log files22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that the application does not log sensitive user data. Refer: <a href="https://aka.ms/tmtauditlog#log-sensitive-data">https://aka.ms/tmtauditlog#log-sensitive-data</a> Ensure that Audit and Log Files have Restricted Access. Refer: <a href="https://aka.ms/tmtauditlog#log-restricted-access">https://aka.ms/tmtauditlog#log-restricted-access</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain access to sensitive data from log filesfalseIAn adversary may gain access to unmasked sensitive data such as credit card numberssource is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp'TH103UserThreatDescriptionfalseAn adversary may gain access to unmasked sensitive data such as credit card numbers22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that sensitive data displayed on the user screen is masked. Refer: <a href="https://aka.ms/tmtdata#data-mask">https://aka.ms/tmtdata#data-mask</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain access to unmasked sensitive data such as credit card numbersfalseIAn adversary can gain access to sensitive data such as the following, through verbose error messages - Server names - Connection strings - Usernames - Passwords - SQL procedures - Details of dynamic SQL failures - Stack trace and lines of code - Variables stored in memory - Drive and folder locations - Application install points - Host configuration settings - Other internal application details target is 'SE.P.TMCore.WebAPI'TH106UserThreatDescriptionfalseAn adversary can gain access to sensitive data such as the following, through verbose error messages - Server names - Connection strings - Usernames - Passwords - SQL procedures - Details of dynamic SQL failures - Stack trace and lines of code - Variables stored in memory - Drive and folder locations - Application install points - Host configuration settings - Other internal application details 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that proper exception handling is done in ASP.NET Web API. Refer: <a href="https://aka.ms/tmtxmgmt#exception">https://aka.ms/tmtxmgmt#exception</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive information from an API through error messagesfalseIAn adversary may retrieve sensitive data (e.g, auth tokens) persisted in browser storagesource is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebAPI' TH107UserThreatDescriptionfalseAn adversary may retrieve sensitive data (e.g, auth tokens) persisted in browser storage22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that sensitive data relevant to Web API is not stored in browser's storage. Refer: <a href="https://aka.ms/tmtdata#api-browser">https://aka.ms/tmtdata#api-browser</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may retrieve sensitive data (e.g, auth tokens) persisted in browser storagefalseIAn adversary may sniff the data sent from Identity Server. This can lead to a compromise of the tokens issued by the Identity Servertarget is 'SE.P.TMCore.IdSrv'TH115UserThreatDescriptionfalseAn adversary may sniff the data sent from Identity Server. This can lead to a compromise of the tokens issued by the Identity Server22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that all traffic to Identity Server is over HTTPS connection. Refer: <a href="https://aka.ms/tmtcommsec#identity-https">https://aka.ms/tmtcommsec#identity-https</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may sniff the data sent from Identity ServerfalseISensitive attributes or fields on an Entity can be inadvertently disclosedtarget is 'SE.P.TMCore.DynamicsCRM'TH119UserThreatDescriptionfalseSensitive attributes or fields on an Entity can be inadvertently disclosed22222222-2222-2222-2222-2222222222220PossibleMitigationsfalsePerform security modelling and use Field Level Security where required. Refer: <a href="https://aka.ms/tmtauthz#modeling-field">https://aka.ms/tmtauthz#modeling-field</a> Perform security modelling and use Business Units/Teams where required. Refer: <a href="https://aka.ms/tmtdata#modeling-teams">https://aka.ms/tmtdata#modeling-teams</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221Sensitive attributes or fields on an Entity can be inadvertently disclosedfalseISensitive Entity records (containing PII, HBI information) can be inadvertently disclosed to users who should not have accesstarget is 'SE.P.TMCore.DynamicsCRM'TH121UserThreatDescriptionfalseSensitive Entity records (containing PII, HBI information) can be inadvertently disclosed to users who should not have access22222222-2222-2222-2222-2222222222220PossibleMitigationsfalsePerform security modelling and use Field Level Security where required. Refer: <a href="https://aka.ms/tmtauthz#modeling-field">https://aka.ms/tmtauthz#modeling-field</a> Perform security modelling and use Business Units/Teams where required. Refer: <a href="https://aka.ms/tmtdata#modeling-teams">https://aka.ms/tmtdata#modeling-teams</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221Sensitive Entity records (containing PII, HBI information) can be inadvertently disclosed to users who should not have accessfalseIIf a mobile device containing cached customer data in the CRM Mobile Client is lost the data could be disclosed if the device is not securedtarget is 'SE.EI.TMCore.DynamicsCRMMobileClient'TH122UserThreatDescriptionfalseIf a mobile device containing cached customer data in the CRM Mobile Client is lost the data could be disclosed if the device is not secured22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure a device management policy is in place that requires a use PIN and allows remote wiping. Refer: <a href="https://aka.ms/tmtcrypto#pin-remote">https://aka.ms/tmtcrypto#pin-remote</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221If a mobile device containing cached customer data in the CRM Mobile Client is lost the data could be disclosed if the device is not securedfalseIIf a laptop with the Dynamics CRM Outlook Client and offline data is lost the data could be disclosed if the device is not securedtarget is 'SE.EI.TMCore.DynamicsCRMOutlookClient'TH123UserThreatDescriptionfalseIf a laptop with the Dynamics CRM Outlook Client and offline data is lost the data could be disclosed if the device is not secured22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure a device management policy is in place that requires a PIN/password/auto lock and encrypts all data (e.g. Bitlocker). Refer: <a href="https://aka.ms/tmtcrypto#bitlocker">https://aka.ms/tmtcrypto#bitlocker</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221If a laptop with the Dynamics CRM Outlook Client and offline data is lost the data could be disclosed if the device is not securedfalseISecure system configuration information exposed via JScripttarget is 'SE.P.TMCore.DynamicsCRM'TH126UserThreatDescriptionfalseSecure system configuration information exposed via JScript22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseInclude a development standards rule proscribing showing config details in exception management outside development. Refer: <a href="https://aka.ms/tmtdata#exception-mgmt">https://aka.ms/tmtdata#exception-mgmt</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221Secure system configuration information exposed via JScriptfalseISecure system configuration information exposed when exception is thrown.target is 'SE.P.TMCore.DynamicsCRM'TH127UserThreatDescriptionfalseSecure system configuration information exposed when exception is thrown.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseInclude a development standards rule proscribing showing config details in exception management outside development. Refer: <a href="https://aka.ms/tmtdata#exception-mgmt">https://aka.ms/tmtdata#exception-mgmt</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221Secure system configuration information exposed when a DotNET exception is thrownfalseIAn Adversary can sniff communication channel and steal the secrets.target is 'SE.P.TMCore.WCF'TH131UserThreatDescriptionfalseAn Adversary can sniff communication channel and steal the secrets.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable HTTPS - Secure Transport channel. Refer: <a href="https://aka.ms/tmtcommsec#https-transport">https://aka.ms/tmtcommsec#https-transport</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An Adversary can sniff communication channel and steal the secrets falseIAn adversary may gain access to sensitive data stored on host machinesflow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No' flow crosses 'SE.TB.TMCore.MachineTrustBoundary'TH139UserThreatDescriptionfalseAn adversary may gain access to sensitive data stored on host machines22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseConsider using Encrypted File System (EFS) is used to protect confidential user-specific data. Refer: <a href="https://aka.ms/tmtdata#efs-user">https://aka.ms/tmtdata#efs-user</a> Ensure that sensitive data stored by the application on the file system is encrypted. Refer: <a href="https://aka.ms/tmtdata#filesystem">https://aka.ms/tmtdata#filesystem</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain access to sensitive data stored on host machinesfalseIAn adversary can read sensitive data by sniffing traffic to {target.Name}target is 'SE.P.TMCore.AzureRedis' and not target.866e2e37-a089-45bc-9576-20fc95304b82 is 'True'TH14UserThreatDescriptionfalseAn adversary can read sensitive data by sniffing traffic to {target.Name}22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that communication to {target.Name} is over SSL/TLS. Configure {target.Name} such that only connections over SSL/TLS are permitted. Also ensure that connection string(s) used by clients have the ssl flag set to true (I.e. ssl=true). Refer: <a href="https://aka.ms/tmt-th14">https://aka.ms/tmt-th14</a>.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can read sensitive data by sniffing traffic to {target.Name}falseIAn adversary can gain access to sensitive data by sniffing traffic from Mobile clientsource is 'SE.EI.TMCore.Mobile'TH15UserThreatDescriptionfalseAn adversary can gain access to sensitive data by sniffing traffic from Mobile client22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement Certificate Pinning. Refer: <a href="https://aka.ms/tmtcommsec#cert-pinning">https://aka.ms/tmtcommsec#cert-pinning</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data by sniffing traffic from Mobile clientfalseIAn adversary can gain access to sensitive data by sniffing traffic to Web APItarget is 'SE.P.TMCore.WebAPI'TH16UserThreatDescriptionfalseAn adversary can gain access to sensitive data by sniffing traffic to Web API22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseForce all traffic to Web APIs over HTTPS connection. Refer: <a href="https://aka.ms/tmtcommsec#webapi-https">https://aka.ms/tmtcommsec#webapi-https</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data by sniffing traffic to Web APIfalseIAn adversary can read sensitive data by sniffing unencrypted SMB traffic to {target.Name}target is 'SE.DS.TMCore.AzureStorage' and target.b3ece90f-c578-4a48-b4d4-89d97614e0d2 is 'File'TH19UserThreatDescriptionfalseAn adversary can read sensitive data by sniffing unencrypted SMB traffic to {target.Name}22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse SMB 3.0 compatible client to ensure in-transit data encryption to Azure File Shares. Refer: <a href="https://aka.ms/tmt-th19a">https://aka.ms/tmt-th19a</a> and <a href="https://aka.ms/tmt-th19b">https://aka.ms/tmt-th19b</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can read sensitive data by sniffing unencrypted SMB traffic to {target.Name}falseIIf application saves sensitive PII or HBI data on phone SD card or local storage, then it ay get stolen.source is 'SE.EI.TMCore.Mobile'TH31UserThreatDescriptionfalseIf application saves sensitive PII or HBI data on phone SD card or local storage, then it ay get stolen.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEncrypt sensitive or PII data written to phones local storage. Refer: <a href="https://aka.ms/tmtdata#pii-phones">https://aka.ms/tmtdata#pii-phones</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain sensitive data from mobile devicefalseIAn adversary may eavesdrop and interfere with the communication between {source.Name} and {target.Name} and possibly tamper the data that is transmitted.(source is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway') and target is 'SE.GP.TMCore.IoTCloudGateway'TH38UserThreatDescriptionfalseAn adversary may eavesdrop and interfere with the communication between {source.Name} and {target.Name} and possibly tamper the data that is transmitted.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseSecure Device to Cloud Gateway communication using SSL/TLS. Refer: <a href="https://aka.ms/tmtcommsec#device-cloud">https://aka.ms/tmtcommsec#device-cloud</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may eavesdrop the traffic to cloud gatewayfalseIAn adversary can eaves drop on communication between application server and {target.Name} server, due to clear text communication protocol usage.(target is 'SE.DS.TMCore.SQL' and source is 'SE.P.TMCore.WebApp')TH5UserThreatDescriptionfalseAn adversary can eaves drop on communication between application server and {target.Name} server, due to clear text communication protocol usage.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure SQL server connection encryption and certificate validation. Refer: <a href="https://aka.ms/tmtcommsec#sqlserver-validation">https://aka.ms/tmtcommsec#sqlserver-validation</a> Force Encrypted communication to SQL server. Refer: <a href="https://aka.ms/tmtcommsec#encrypted-sqlserver">https://aka.ms/tmtcommsec#encrypted-sqlserver</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data by sniffing traffic to databasefalseIAn adversary may eavesdrop and interfere with the communication between the device and the field gateway and possibly tamper the data that is transmittedsource is 'SE.EI.TMCore.IoTdevice' and target is 'SE.GP.TMCore.IoTFieldGateway'TH52UserThreatDescriptionfalseAn adversary may eavesdrop and interfere with the communication between the device and the field gateway and possibly tamper the data that is transmitted22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseSecure Device to Field Gateway communication. Refer: <a href="https://aka.ms/tmtcommsec#device-field">https://aka.ms/tmtcommsec#device-field</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may eavesdrop the communication between the device and the field gatewayfalseIAn adversary having access to {target.Name} may read sensitive clear-text datatarget is 'SE.P.TMCore.AzureDocumentDB'TH53UserThreatDescriptionfalseAn adversary having access to {target.Name} may read sensitive clear-text data22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEncrypt sensitive data before storing it in Azure Document DB.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary having access to {target.Name} may read sensitive clear-text datafalseIAdditional controls like Transparent Data Encryption, Column Level Encryption, EKM etc. provide additional protection mechanism to high value PII or HBI data. target is 'SE.DS.TMCore.SQL'TH6UserThreatDescriptionfalseAdditional controls like Transparent Data Encryption, Column Level Encryption, EKM etc. provide additional protection mechanism to high value PII or HBI data. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse strong encryption algorithms to encrypt data in the database. Refer: <a href="https://aka.ms/tmtcrypto#strong-db">https://aka.ms/tmtcrypto#strong-db</a> Ensure that sensitive data in database columns is encrypted. Refer: <a href="https://aka.ms/tmtdata#db-encrypted">https://aka.ms/tmtdata#db-encrypted</a> Ensure that database-level encryption (TDE) is enabled. Refer: <a href="https://aka.ms/tmtdata#tde-enabled">https://aka.ms/tmtdata#tde-enabled</a> Ensure that database backups are encrypted. Refer: <a href="https://aka.ms/tmtdata#backup">https://aka.ms/tmtdata#backup</a> Use SQL server EKM to protect encryption keys. Refer: <a href="https://aka.ms/tmtcrypto#ekm-keys">https://aka.ms/tmtcrypto#ekm-keys</a> Use AlwaysEncrypted feature if encryption keys should not be revealed to Database engine. Refer: <a href="https://aka.ms/tmtcrypto#keys-engine">https://aka.ms/tmtcrypto#keys-engine</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive PII or HBI data in databasefalseEAn adversary can abuse poorly managed {target.Name} account access keys and gain unauthorized access to storage.target is 'SE.DS.TMCore.AzureStorage'TH63UserThreatDescriptionfalseAn adversary can abuse poorly managed {target.Name} account access keys and gain unauthorized access to storage.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure secure management and storage of Azure storage access keys. It is recommended to rotate storage access keys regularly, in accordance with organizational policies. Refer: <a href="https://aka.ms/tmt-th63">https://aka.ms/tmt-th63</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can abuse poorly managed {target.Name} account access keysfalseIAn adversary can abuse an insecure communication channel between a client and {target.Name}target is 'SE.DS.TMCore.AzureStorage' and target.229f2e53-bc3f-476c-8ac9-57da37efd00f is 'True'target is 'SE.DS.TMCore.AzureStorage'TH65UserThreatDescriptionfalseAn adversary can abuse an insecure communication channel between a client and {target.Name}22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that communication to Azure Storage is over HTTPS. It is recommended to enable the secure transfer required option to force communication with Azure Storage to be over HTTPS. Use Client-Side Encryption to store sensitive data in Azure Storage. Refer: <a href="https://aka.ms/tmt-th65">https://aka.ms/tmt-th65</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can abuse an insecure communication channel between a client and {target.Name}falseISecrets can be any sensitive information, such as storage connection strings, passwords, or other values that should not be handled in plain text. If secrets are not encrypted, an adversary who can gain access to them can abuse them.flow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No' flow crosses 'SE.TB.TMCore.ServiceFabric'TH73UserThreatDescriptionfalseSecrets can be any sensitive information, such as storage connection strings, passwords, or other values that should not be handled in plain text. If secrets are not encrypted, an adversary who can gain access to them can abuse them.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEncrypt secrets in Service Fabric applications. Refer: <a href="https://aka.ms/tmtdata#fabric-apps">https://aka.ms/tmtdata#fabric-apps</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to unencrypted secrets in Service Fabric applicationsfalseIAn adversary may conduct man in the middle attack and downgrade TLS connection to clear text protocol, or forcing browser communication to pass through a proxy server that he controls. This may happen because the application may use mixed content or HTTP Strict Transport Security policy is not ensured. source is 'GE.EI' and target is 'SE.P.TMCore.WebApp' and target.80fe9520-5f00-4480-ad47-f2fd75dede82 is 'Azure' TH78UserThreatDescriptionfalseAn adversary may conduct man in the middle attack and downgrade TLS connection to clear text protocol, or forcing browser communication to pass through a proxy server that he controls. This may happen because the application may use mixed content or HTTP Strict Transport Security policy is not ensured. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseConfigure SSL certificate for custom domain in Azure App Service. Refer: <a href="https://aka.ms/tmtcommsec#ssl-appservice">https://aka.ms/tmtcommsec#ssl-appservice</a> Force all traffic to Azure App Service over HTTPS connection . Refer: <a href="https://aka.ms/tmtcommsec#appservice-https">https://aka.ms/tmtcommsec#appservice-https</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data by sniffing traffic to Azure Web AppfalseI An adversary can fingerprint web application by leveraging server header information source is 'GE.EI' and target is 'SE.P.TMCore.WebApp' and target.80fe9520-5f00-4480-ad47-f2fd75dede82 is 'Azure' TH79UserThreatDescriptionfalse An adversary can fingerprint web application by leveraging server header information 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRemove standard server headers on Windows Azure Web Sites to avoid fingerprinting. Refer: <a href="https://aka.ms/tmtconfigmgmt#standard-finger">https://aka.ms/tmtconfigmgmt#standard-finger</a>22222222-2222-2222-2222-2222222222222PriorityfalseLow22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can fingerprint an Azure web application by leveraging server header informationfalseIRobots.txt is often found in your site's root directory and exists to regulate the bots that crawl your site. This is where you can grant or deny permission to all or some specific search engine robots to access certain pages or your site as a whole. The standard for this file was developed in 1994 and is known as the Robots Exclusion Standard or Robots Exclusion Protocol. Detailed info about the robots.txt protocol can be found at robotstxt.org.(source is 'SE.EI.TMCore.Browser') and (target is 'SE.P.TMCore.WebApp')TH80UserThreatDescriptionfalseRobots.txt is often found in your site's root directory and exists to regulate the bots that crawl your site. This is where you can grant or deny permission to all or some specific search engine robots to access certain pages or your site as a whole. The standard for this file was developed in 1994 and is known as the Robots Exclusion Standard or Robots Exclusion Protocol. Detailed info about the robots.txt protocol can be found at robotstxt.org.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that administrative interfaces are appropriately locked down. Refer: <a href="https://aka.ms/tmtauthn#admin-interface-lockdown">https://aka.ms/tmtauthn#admin-interface-lockdown</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to certain pages or the site as a whole.falseISQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed. target is 'SE.DS.TMCore.SQL'TH82UserThreatDescriptionfalseSQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that login auditing is enabled on SQL Server. Refer: <a href="https://aka.ms/tmtauditlog#identify-sensitive-entities">https://aka.ms/tmtauditlog#identify-sensitive-entities</a> Ensure that least-privileged accounts are used to connect to Database server. Refer: <a href="https://aka.ms/tmtauthz#privileged-server">https://aka.ms/tmtauthz#privileged-server</a> Enable Threat detection on Azure SQL database. Refer: <a href="https://aka.ms/tmtauditlog#threat-detection">https://aka.ms/tmtauditlog#threat-detection</a> Do not use dynamic queries in stored procedures. Refer: <a href="https://aka.ms/tmtinputval#stored-proc">https://aka.ms/tmtinputval#stored-proc</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data by performing SQL injectionfalseIAn adversary can gain access to the config files. and if sensitive data is stored in it, it would be compromised.target is 'SE.P.TMCore.WebAPI'TH83UserThreatDescriptionfalseAn adversary can gain access to the config files. and if sensitive data is stored in it, it would be compromised.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEncrypt sections of Web API's configuration files that contain sensitive data. Refer: <a href="https://aka.ms/tmtconfigmgmt#config-sensitive">https://aka.ms/tmtconfigmgmt#config-sensitive</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data stored in Web API's config filesfalseIAn adversary may conduct man in the middle attack and downgrade TLS connection to clear text protocol, or forcing browser communication to pass through a proxy server that he controls. This may happen because the application may use mixed content or HTTP Strict Transport Security policy is not ensured.(source is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp')TH9UserThreatDescriptionfalseAn adversary may conduct man in the middle attack and downgrade TLS connection to clear text protocol, or forcing browser communication to pass through a proxy server that he controls. This may happen because the application may use mixed content or HTTP Strict Transport Security policy is not ensured.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseApplications available over HTTPS must use secure cookies. Refer: <a href="https://aka.ms/tmtsmgmt#https-secure-cookies">https://aka.ms/tmtsmgmt#https-secure-cookies</a> Enable HTTP Strict Transport Security (HSTS). Refer: <a href="https://aka.ms/tmtcommsec#http-hsts">https://aka.ms/tmtcommsec#http-hsts</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data by sniffing traffic to Web ApplicationfalseIIf an adversary can gain access to Azure VMs, sensitive data in the VM can be disclosed if the OS in the VM is not encryptedflow crosses 'SE.TB.TMCore.AzureIaaSVMTrustBoundary'TH93UserThreatDescriptionfalseIf an adversary can gain access to Azure VMs, sensitive data in the VM can be disclosed if the OS in the VM is not encrypted22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse Azure Disk Encryption to encrypt disks used by Virtual Machines. Refer: <a href="https://aka.ms/tmtdata#disk-vm">https://aka.ms/tmtdata#disk-vm</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain access to sensitive data stored in Azure Virtual MachinesfalseIAn adversary can gain access to sensitive data such as the following, through verbose error messages - Server names - Connection strings - Usernames - Passwords - SQL procedures - Details of dynamic SQL failures - Stack trace and lines of code - Variables stored in memory - Drive and folder locations - Application install points - Host configuration settings - Other internal application details target is 'SE.P.TMCore.WebApp'TH94UserThreatDescriptionfalseAn adversary can gain access to sensitive data such as the following, through verbose error messages - Server names - Connection strings - Usernames - Passwords - SQL procedures - Details of dynamic SQL failures - Stack trace and lines of code - Variables stored in memory - Drive and folder locations - Application install points - Host configuration settings - Other internal application details 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseDo not expose security details in error messages. Refer: <a href="https://aka.ms/tmtxmgmt#messages">https://aka.ms/tmtxmgmt#messages</a> Implement Default error handling page. Refer: <a href="https://aka.ms/tmtxmgmt#default">https://aka.ms/tmtxmgmt#default</a> Set Deployment Method to Retail in IIS. Refer: <a href="https://aka.ms/tmtxmgmt#deployment">https://aka.ms/tmtxmgmt#deployment</a> Exceptions should fail safely. Refer: <a href="https://aka.ms/tmtxmgmt#fail">https://aka.ms/tmtxmgmt#fail</a> ASP.NET applications must disable tracing and debugging prior to deployment. Refer: <a href="https://aka.ms/tmtconfigmgmt#trace-deploy">https://aka.ms/tmtconfigmgmt#trace-deploy</a> Implement controls to prevent username enumeration. Refer: <a href="https://aka.ms/tmtauthn#controls-username-enum">https://aka.ms/tmtauthn#controls-username-enum</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive information through error messagesfalseIAn adversary may gain access to sensitive data from uncleared browser cachesource is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp'TH99UserThreatDescriptionfalseAn adversary may gain access to sensitive data from uncleared browser cache22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that sensitive content is not cached on the browser. Refer: <a href="https://aka.ms/tmtdata#cache-browser">https://aka.ms/tmtdata#cache-browser</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain access to sensitive data from uncleared browser cachefalseRAttacker can deny a malicious act on an API leading to repudiation issuestarget is 'SE.P.TMCore.WebAPI'TH109UserThreatDescriptionfalseAttacker can deny a malicious act on an API leading to repudiation issues22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that auditing and logging is enforced on Web API. Refer: <a href="https://aka.ms/tmtauditlog#logging-web-api">https://aka.ms/tmtauditlog#logging-web-api</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221Attacker can deny a malicious act on an API leading to repudiation issuesfalseRThis is due to the Last Modified By field being overwritten on each save(target is 'SE.P.TMCore.DynamicsCRM')TH118UserThreatDescriptionfalseThis is due to the Last Modified By field being overwritten on each save22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseIdentify sensitive entities in your solution and implement change auditing. Refer: <a href="https://aka.ms/tmtauditlog#sensitive-entities">https://aka.ms/tmtauditlog#sensitive-entities</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221A malicious user can deny they made a change to {target.Name}falseRProper logging of all security events and user actions builds traceability in a system and denies any possible repudiation issues. In the absence of proper auditing and logging controls, it would become impossible to implement any accountability in a system.target is 'SE.DS.TMCore.AzureStorage'TH20UserThreatDescriptionfalseProper logging of all security events and user actions builds traceability in a system and denies any possible repudiation issues. In the absence of proper auditing and logging controls, it would become impossible to implement any accountability in a system.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse Azure Storage Analytics to audit access of Azure Storage. If possible, audit the calls to the Azure Storage instance at the source of the call. Refer: <a href="https://aka.ms/tmt-th20">https://aka.ms/tmt-th20</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can deny actions on {target.Name} due to lack of auditing falseRProper logging of all security events and user actions builds traceability in a system and denies any possible repudiation issues. In the absence of proper auditing and logging controls, it would become impossible to implement any accountability in a system.target is 'SE.DS.TMCore.SQL' TH3UserThreatDescriptionfalseProper logging of all security events and user actions builds traceability in a system and denies any possible repudiation issues. In the absence of proper auditing and logging controls, it would become impossible to implement any accountability in a system.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that login auditing is enabled on SQL Server. Refer: <a href="https://aka.ms/tmtauditlog#identify-sensitive-entities">https://aka.ms/tmtauditlog#identify-sensitive-entities</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can deny actions on database due to lack of auditingfalseRProper logging of all security events and user actions builds traceability in a system and denies any possible repudiation issues. In the absence of proper auditing and logging controls, it would become impossible to implement any accountability in a systemtarget is 'SE.P.TMCore.WebApp'TH30UserThreatDescriptionfalseProper logging of all security events and user actions builds traceability in a system and denies any possible repudiation issues. In the absence of proper auditing and logging controls, it would become impossible to implement any accountability in a system22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that auditing and logging is enforced on the application. Refer: <a href="https://aka.ms/tmtauditlog#auditing">https://aka.ms/tmtauditlog#auditing</a> Ensure that log rotation and separation are in place. Refer: <a href="https://aka.ms/tmtauditlog#log-rotation">https://aka.ms/tmtauditlog#log-rotation</a> Ensure that Audit and Log Files have Restricted Access. Refer: <a href="https://aka.ms/tmtauditlog#log-restricted-access">https://aka.ms/tmtauditlog#log-restricted-access</a> Ensure that User Management Events are Logged. Refer: <a href="https://aka.ms/tmtauditlog#user-management">https://aka.ms/tmtauditlog#user-management</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221Attacker can deny the malicious act and remove the attack foot prints leading to repudiation issuesfalseRAn adversary may perform actions such as spoofing attempts, unauthorized access etc. on Cloud gateway. It is important to monitor these attempts so that adversary cannot deny these actionstarget is 'SE.GP.TMCore.IoTCloudGateway'TH34UserThreatDescriptionfalseAn adversary may perform actions such as spoofing attempts, unauthorized access etc. on Cloud gateway. It is important to monitor these attempts so that adversary cannot deny these actions22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that appropriate auditing and logging is enforced on Cloud Gateway. Refer: <a href="https://aka.ms/tmtauditlog#logging-cloud-gateway">https://aka.ms/tmtauditlog#logging-cloud-gateway</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can deny actions on Cloud Gateway due to lack of auditingfalseRAn adversary may perform actions such as spoofing attempts, unauthorized access etc. on Field gateway. It is important to monitor these attempts so that adversary cannot deny these actionstarget is 'SE.GP.TMCore.IoTFieldGateway'TH49UserThreatDescriptionfalseAn adversary may perform actions such as spoofing attempts, unauthorized access etc. on Field gateway. It is important to monitor these attempts so that adversary cannot deny these actions22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that appropriate auditing and logging is enforced on Field Gateway. Refer: <a href="https://aka.ms/tmtauditlog#logging-field-gateway">https://aka.ms/tmtauditlog#logging-field-gateway</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can deny actions on Field Gateway due to lack of auditingfalseRProper logging of all security events and user actions builds traceability in a system and denies any possible repudiation issues. In the absence of proper auditing and logging controls, it would become impossible to implement any accountability in a system. source is 'GE.EI' and target is 'SE.P.TMCore.WebApp' and target.80fe9520-5f00-4480-ad47-f2fd75dede82 is 'Azure'TH77UserThreatDescriptionfalseProper logging of all security events and user actions builds traceability in a system and denies any possible repudiation issues. In the absence of proper auditing and logging controls, it would become impossible to implement any accountability in a system. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable diagnostics logging for web apps in Azure App Service. Refer: <a href="https://aka.ms/tmtauditlog#diagnostics-logging">https://aka.ms/tmtauditlog#diagnostics-logging</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can deny actions on Azure App Service due to lack of auditingfalseSAn adversary can bypass authentication due to non-standard Azure AD authentication schemestarget is 'SE.P.TMCore.AzureAD'TH11UserThreatDescriptionfalseAn adversary can bypass authentication due to non-standard Azure AD authentication schemes22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse standard authentication scenarios supported by Azure Active Directory. Refer: <a href="https://aka.ms/tmtauthn#authn-aad">https://aka.ms/tmtauthn#authn-aad</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can bypass authentication due to non-standard Azure AD authentication schemesfalseSAn adversary can bypass authentication due to non-standard Identity Server authentication schemestarget is 'SE.P.TMCore.IdSrv'TH111UserThreatDescriptionfalseAn adversary can bypass authentication due to non-standard Identity Server authentication schemes22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse standard authentication scenarios supported by Identity Server. Refer: <a href="https://aka.ms/tmtauthn#standard-authn-id">https://aka.ms/tmtauthn#standard-authn-id</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can bypass authentication due to non-standard Identity Server authentication schemesfalseSAn adversary can get access to a user's session due to improper logout from Identity Servertarget is 'SE.P.TMCore.IdSrv'TH113UserThreatDescriptionfalseAn adversary can get access to a user's session due to improper logout from Identity Server22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement proper logout when using Identity Server. Refer: <a href="https://aka.ms/tmtsmgmt#proper-logout">https://aka.ms/tmtsmgmt#proper-logout</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can get access to a user's session due to improper logout from Identity ServerfalseSAn adversary can abuse poorly managed signing keys of Identity Server. In case of key compromise, an adversary will be able to create valid auth tokens using the stolen keys and gain access to the resources protected by Identity server.target is 'SE.P.TMCore.IdSrv'TH114UserThreatDescriptionfalseAn adversary can abuse poorly managed signing keys of Identity Server. In case of key compromise, an adversary will be able to create valid auth tokens using the stolen keys and gain access to the resources protected by Identity server.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that signing keys are rolled over when using Identity Server. Refer: <a href="https://aka.ms/tmtcrypto#rolled-server">https://aka.ms/tmtcrypto#rolled-server</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may issue valid tokens if Identity server's signing keys are compromisedfalseSAn adversary may spoof an Azure administrator and gain access to Azure subscription portal if the administrator's credentials are compromised.flow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.AzureTrustBoundary' TH117UserThreatDescriptionfalseAn adversary may spoof an Azure administrator and gain access to Azure subscription portal if the administrator's credentials are compromised.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable fine-grained access management to Azure Subscription using RBAC. Refer: <a href="https://aka.ms/tmtauthz#grained-rbac">https://aka.ms/tmtauthz#grained-rbac</a> Enable Azure Multi-Factor Authentication for Azure Administrators. Refer: <a href="https://aka.ms/tmtauthn#multi-factor-azure-admin">https://aka.ms/tmtauthn#multi-factor-azure-admin</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may spoof an Azure administrator and gain access to Azure subscription portalfalseSAn adversary can get access to a user's session by replaying authentication tokens (source is 'GE.P' or source is 'GE.EI') and target is 'SE.P.TMCore.AzureAD'TH12UserThreatDescriptionfalseAn adversary can get access to a user's session by replaying authentication tokens 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that TokenReplayCache is used to prevent the replay of ADAL authentication tokens. Refer: <a href="https://aka.ms/tmtauthn#tokenreplaycache-adal">https://aka.ms/tmtauthn#tokenreplaycache-adal</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can get access to a user's session by replaying authentication tokens falseSAn adversary may gain access to the field gateway by leveraging default login credentials. target is 'SE.GP.TMCore.IoTFieldGateway'TH129UserThreatDescriptionfalseAn adversary may gain access to the field gateway by leveraging default login credentials. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that the default login credentials of the field gateway are changed during installation. Refer: <a href="https://aka.ms/tmtconfigmgmt#default-change">https://aka.ms/tmtconfigmgmt#default-change</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain access to the field gateway by leveraging default login credentials. falseSAn adversary can gain unauthorized access to API end points due to weak CORS configurationsource is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebAPI'TH13UserThreatDescriptionfalseAn adversary can gain unauthorized access to API end points due to weak CORS configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that only trusted origins are allowed if CORS is enabled on ASP.NET Web API. Refer: <a href="https://aka.ms/tmtconfigmgmt#cors-api">https://aka.ms/tmtconfigmgmt#cors-api</a> Mitigate against Cross-Site Request Forgery (CSRF) attacks on ASP.NET Web APIs. Refer: <a href="https://aka.ms/tmtsmgmt#csrf-api">https://aka.ms/tmtsmgmt#csrf-api</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to API end points due to unrestricted cross domain requestsfalseSAn adversary may guess the client id and secrets of registered applications and impersonate them target is 'SE.P.TMCore.IdSrv'TH133UserThreatDescriptionfalseAn adversary may guess the client id and secrets of registered applications and impersonate them 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that cryptographically strong client id, client secret are used in Identity Server. Refer: <a href="https://aka.ms/tmtcrypto#client-server">https://aka.ms/tmtcrypto#client-server</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may guess the client id and secrets of registered applications and impersonate themfalseEAn adversary can gain unauthorized access to {target.Name} due to weak CORS configurationtarget is 'SE.DS.TMCore.AzureStorage' and target.c63455d0-ad77-4b08-aa02-9f8026bb056f is 'False'target is 'SE.DS.TMCore.AzureStorage'TH21UserThreatDescriptionfalseAn adversary can gain unauthorized access to {target.Name} due to weak CORS configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that only specific, trusted origins are allowed. Refer: <a href="https://aka.ms/tmt-th21">https://aka.ms/tmt-th21</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to {target.Name} due to weak CORS configurationfalseSThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user.source is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp'TH22UserThreatDescriptionfalseThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseSet up session for inactivity lifetime. Refer: <a href="https://aka.ms/tmtsmgmt#inactivity-lifetime">https://aka.ms/tmtsmgmt#inactivity-lifetime</a> Implement proper logout from the application. Refer: <a href="https://aka.ms/tmtsmgmt#proper-app-logout">https://aka.ms/tmtsmgmt#proper-app-logout</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can get access to a user's session due to improper logout and timeoutfalseSThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user.source is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp'TH23UserThreatDescriptionfalseThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable ValidateRequest attribute on ASP.NET Pages. Refer: <a href="https://aka.ms/tmtconfigmgmt#validate-aspnet">https://aka.ms/tmtconfigmgmt#validate-aspnet</a> Encode untrusted web output prior to rendering. Refer: <a href="https://aka.ms/tmtinputval#rendering">https://aka.ms/tmtinputval#rendering</a> Avoid using Html.Raw in Razor views. Refer: <a href="https://aka.ms/tmtinputval#html-razor">https://aka.ms/tmtinputval#html-razor</a> Sanitization should be applied on form fields that accept all characters e.g, rich text editor . Refer: <a href="https://aka.ms/tmtinputval#richtext">https://aka.ms/tmtinputval#richtext</a> Do not assign DOM elements to sinks that do not have inbuilt encoding . Refer: <a href="https://aka.ms/tmtinputval#inbuilt-encode">https://aka.ms/tmtinputval#inbuilt-encode</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can get access to a user's session due to insecure coding practicesfalseSEnsure that TLS certificate parameters are configured with correct valuestarget is 'SE.P.TMCore.WebApp'TH32UserThreatDescriptionfalseEnsure that TLS certificate parameters are configured with correct values22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseVerify X.509 certificates used to authenticate SSL, TLS, and DTLS connections. Refer: <a href="https://aka.ms/tmtcommsec#x509-ssltls">https://aka.ms/tmtcommsec#x509-ssltls</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can spoof the target web application due to insecure TLS certificate configurationfalseSAn adversary may replacing the {source.Name} or part of the {source.Name} with some other {source.Name}. (source is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway') and (target is 'SE.GP.TMCore.IoTFieldGateway' or target is 'SE.GP.TMCore.IoTCloudGateway')TH35UserThreatDescriptionfalseAn adversary may replacing the {source.Name} or part of the {source.Name} with some other {source.Name}. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that devices connecting to Field or Cloud gateway are authenticated. Refer: <a href="https://aka.ms/tmtauthn#authn-devices-cloud">https://aka.ms/tmtauthn#authn-devices-cloud</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may spoof {source.Name} with a fake onefalseSAn attacker may extract cryptographic key material from {source.Name}, either at the software or hardware level, and subsequently access the system with a different physical or virtual {source.Name} under the identity of the {source.Name} the key material has been taken from. A good illustration is remote controls that can turn any TV and that are popular prankster tools.(source is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway') and (target is 'SE.GP.TMCore.IoTFieldGateway' or target is 'SE.GP.TMCore.IoTCloudGateway')TH36UserThreatDescriptionfalseAn attacker may extract cryptographic key material from {source.Name}, either at the software or hardware level, and subsequently access the system with a different physical or virtual {source.Name} under the identity of the {source.Name} the key material has been taken from. A good illustration is remote controls that can turn any TV and that are popular prankster tools.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse per-device authentication credentials. Refer: <a href="https://aka.ms/tmtauthn#authn-cred">https://aka.ms/tmtauthn#authn-cred</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may reuse the authentication tokens of {source.Name} in anotherfalseSAn adversary may predict and generate valid security tokens to authenticate to IoT Hub, by leveraging weak encryption keys(source is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway') and target is 'SE.GP.TMCore.IoTCloudGateway'TH40UserThreatDescriptionfalseAn adversary may predict and generate valid security tokens to authenticate to IoT Hub, by leveraging weak encryption keys22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseGenerate a random symmetric key of sufficient length for authentication to IoT Hub. Refer: <a href="https://aka.ms/tmtcrypto#random-hub">https://aka.ms/tmtcrypto#random-hub</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may auto-generate valid authentication tokens for IoT HubfalseSAn adversary may get access to SaS tokens used to authenticate to IoT Hub. If the lifetime of these tokens is not finite, the adversary may replay the stolen tokens indefinitely(source is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway') and target is 'SE.GP.TMCore.IoTCloudGateway'TH44UserThreatDescriptionfalseAn adversary may get access to SaS tokens used to authenticate to IoT Hub. If the lifetime of these tokens is not finite, the adversary may replay the stolen tokens indefinitely22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse finite lifetimes for generated SaS tokens. Refer: <a href="https://aka.ms/tmtsmgmt#finite-tokens">https://aka.ms/tmtsmgmt#finite-tokens</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may replay stolen long-lived SaS tokens of IoT HubfalseSAn adversary may spoof a device and connect to field gateway. This may be achieved even when the device is registered in Cloud gateway since the field gateway may not be in sync with the device identities in cloud gatewaysource is 'SE.EI.TMCore.IoTdevice' and target is 'SE.GP.TMCore.IoTFieldGateway'TH50UserThreatDescriptionfalseAn adversary may spoof a device and connect to field gateway. This may be achieved even when the device is registered in Cloud gateway since the field gateway may not be in sync with the device identities in cloud gateway22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseAuthenticate devices connecting to the Field Gateway. Refer: <a href="https://aka.ms/tmtauthn#authn-devices-field">https://aka.ms/tmtauthn#authn-devices-field</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may spoof a device and connect to field gatewayfalseEAn adversary may reuse a stolen long-lived resource token, access key or connection string to access an {target.Name} instancetarget is 'SE.P.TMCore.AzureDocumentDB'TH55UserThreatDescriptionfalseAn adversary may reuse a stolen long-lived resource token, access key or connection string to access an {target.Name} instance22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse minimum token lifetimes for generated resource tokens. Rotate secrets (e.g. resource tokens, access keys and passwords in connection strings) frequently, in accordance with your organization's policies. Refer: <a href="https://aka.ms/tmt-th55">https://aka.ms/tmt-th55</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may reuse a stolen long-lived resource token, access key or connection string to access an {target.Name} instancefalseSIf multiple devices use the same SaS token, then an adversary can spoof any device using a token that he or she has access totarget is 'SE.P.TMCore.AzureEventHub'TH58UserThreatDescriptionfalseIf multiple devices use the same SaS token, then an adversary can spoof any device using a token that he or she has access to22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse per device authentication credentials using SaS tokens. Refer: <a href="https://aka.ms/tmtauthn#authn-sas-tokens">https://aka.ms/tmtauthn#authn-sas-tokens</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may spoof a device by reusing the authentication tokens of one device in anotherfalseSIf a service fabric cluster is not secured, it allow any anonymous user to connect to it if it exposes management endpoints to the public Internet.flow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.ServiceFabric'TH68UserThreatDescriptionfalseIf a service fabric cluster is not secured, it allow any anonymous user to connect to it if it exposes management endpoints to the public Internet.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict anonymous access to Service Fabric Cluster. Refer: <a href="https://aka.ms/tmtauthn#anon-access-cluster">https://aka.ms/tmtauthn#anon-access-cluster</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to resources in Service FabricfalseSIf the same certificate that is used for node-to-node security is used for client-to-node security, it will be easy for an adversary to spoof and join a new node, in case the client-to-node certificate (which is often stored locally) is compromisedflow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.ServiceFabric'TH69UserThreatDescriptionfalseIf the same certificate that is used for node-to-node security is used for client-to-node security, it will be easy for an adversary to spoof and join a new node, in case the client-to-node certificate (which is often stored locally) is compromised22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that Service Fabric client-to-node certificate is different from node-to-node certificate. Refer: <a href="https://aka.ms/tmtauthn#fabric-cn-nn">https://aka.ms/tmtauthn#fabric-cn-nn</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can spoof a node and access Service Fabric clusterfalseSAttackers can exploit weaknesses in system to steal user credentials. Downstream and upstream components are often accessed by using credentials stored in configuration stores. Attackers may steal the upstream or downstream component credentials. Attackers may steal credentials if, Credentials are stored and sent in clear text, Weak input validation coupled with dynamic sql queries, Password retrieval mechanism are poor, (target is 'SE.P.TMCore.WebApp')TH7UserThreatDescriptionfalseAttackers can exploit weaknesses in system to steal user credentials. Downstream and upstream components are often accessed by using credentials stored in configuration stores. Attackers may steal the upstream or downstream component credentials. Attackers may steal credentials if, Credentials are stored and sent in clear text, Weak input validation coupled with dynamic sql queries, Password retrieval mechanism are poor, 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseExplicitly disable the autocomplete HTML attribute in sensitive forms and inputs. Refer: <a href="https://aka.ms/tmtdata#autocomplete-input">https://aka.ms/tmtdata#autocomplete-input</a> Perform input validation and filtering on all string type Model properties. Refer: <a href="https://aka.ms/tmtinputval#typemodel">https://aka.ms/tmtinputval#typemodel</a> Validate all redirects within the application are closed or done safely. Refer: <a href="https://aka.ms/tmtinputval#redirect-safe">https://aka.ms/tmtinputval#redirect-safe</a> Enable step up or adaptive authentication. Refer: <a href="https://aka.ms/tmtauthn#step-up-adaptive-authn">https://aka.ms/tmtauthn#step-up-adaptive-authn</a> Implement forgot password functionalities securely. Refer: <a href="https://aka.ms/tmtauthn#forgot-pword-fxn">https://aka.ms/tmtauthn#forgot-pword-fxn</a> Ensure that password and account policy are implemented. Refer: <a href="https://aka.ms/tmtauthn#pword-account-policy">https://aka.ms/tmtauthn#pword-account-policy</a> Implement input validation on all string type parameters accepted by Controller methods. Refer: <a href="https://aka.ms/tmtinputval#string-method">https://aka.ms/tmtinputval#string-method</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can steal sensitive data like user credentialsfalseSAzure AD authentication provides better control on identity management and hence it is a better alternative to authenticate clients to Service Fabricflow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.ServiceFabric'TH70UserThreatDescriptionfalseAzure AD authentication provides better control on identity management and hence it is a better alternative to authenticate clients to Service Fabric22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse AAD to authenticate clients to service fabric clusters. Refer: <a href="https://aka.ms/tmtauthn#aad-client-fabric">https://aka.ms/tmtauthn#aad-client-fabric</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can potentially spoof a client if weaker client authentication channels are usedfalseSIf self-signed or test certificates are stolen, it would be difficult to revoke them. An adversary can use stolen certificates and continue to get access to Service Fabric cluster.flow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.ServiceFabric'TH72UserThreatDescriptionfalseIf self-signed or test certificates are stolen, it would be difficult to revoke them. An adversary can use stolen certificates and continue to get access to Service Fabric cluster.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that service fabric certificates are obtained from an approved Certificate Authority (CA). Refer: <a href="https://aka.ms/tmtauthn#fabric-cert-ca">https://aka.ms/tmtauthn#fabric-cert-ca</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can spoof a node in Service Fabric cluster by using stolen certificatesfalseSOn a public client (e.g. a mobile device), refresh tokens may be stolen and used by an attacker to obtain access to the API. Depending on the client type, there are different ways that tokens may be revealed to an attacker and therefore different ways to protect them, some involving how the software using the tokens requests, stores and refreshes them.source is 'SE.EI.TMCore.Mobile' and target is 'SE.P.TMCore.WebAPI'TH74UserThreatDescriptionfalseOn a public client (e.g. a mobile device), refresh tokens may be stolen and used by an attacker to obtain access to the API. Depending on the client type, there are different ways that tokens may be revealed to an attacker and therefore different ways to protect them, some involving how the software using the tokens requests, stores and refreshes them.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse ADAL libraries to manage token requests from OAuth2 clients to AAD (or on-premises AD). Refer: <a href="https://aka.ms/tmtauthn#adal-oauth2">https://aka.ms/tmtauthn#adal-oauth2</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary obtains refresh or access tokens from {source.Name} and uses them to obtain access to the {target.Name} APIfalseSThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user. source is 'SE.P.TMCore.WebApp' and target is 'SE.P.TMCore.AzureAD'TH75UserThreatDescriptionfalseThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement proper logout using ADAL methods when using Azure AD. Refer: <a href="https://aka.ms/tmtsmgmt#logout-adal">https://aka.ms/tmtsmgmt#logout-adal</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can get access to a user's session due to improper logout from Azure ADfalseSThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user. source is 'SE.P.TMCore.WebApp' and target is 'SE.P.TMCore.ADFS'TH76UserThreatDescriptionfalseThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement proper logout using WsFederation methods when using ADFS. Refer: <a href="https://aka.ms/tmtsmgmt#wsfederation-logout">https://aka.ms/tmtsmgmt#wsfederation-logout</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can get access to a user's session due to improper logout from ADFSfalseSThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user. (source is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp')TH8UserThreatDescriptionfalseThe session cookies is the identifier by which the server knows the identity of current user for each incoming request. If the attacker is able to steal the user token he would be able to access all user data and perform all actions on behalf of user. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseApplications available over HTTPS must use secure cookies. Refer: <a href="https://aka.ms/tmtsmgmt#https-secure-cookies">https://aka.ms/tmtsmgmt#https-secure-cookies</a> All http based application should specify http only for cookie definition. Refer: <a href="https://aka.ms/tmtsmgmt#cookie-definition">https://aka.ms/tmtsmgmt#cookie-definition</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221Attackers can steal user session cookies due to insecure cookie attributesfalseSPhishing is attempted to obtain sensitive information such as usernames, passwords, and credit card details (and sometimes, indirectly, money), often for malicious reasons, by masquerading as a Web Server which is a trustworthy entity in electronic communicationtarget is 'SE.P.TMCore.WebApp'TH81UserThreatDescriptionfalsePhishing is attempted to obtain sensitive information such as usernames, passwords, and credit card details (and sometimes, indirectly, money), often for malicious reasons, by masquerading as a Web Server which is a trustworthy entity in electronic communication22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseVerify X.509 certificates used to authenticate SSL, TLS, and DTLS connections. Refer: <a href="https://aka.ms/tmtcommsec#x509-ssltls">https://aka.ms/tmtcommsec#x509-ssltls</a> Ensure that authenticated ASP.NET pages incorporate UI Redressing or clickjacking defences. Refer: <a href="https://aka.ms/tmtconfigmgmt#ui-defenses">https://aka.ms/tmtconfigmgmt#ui-defenses</a> Validate all redirects within the application are closed or done safely. Refer: <a href="https://aka.ms/tmtinputval#redirect-safe">https://aka.ms/tmtinputval#redirect-safe</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can create a fake website and launch phishing attacksfalseSAn adversary can gain access to Azure storage containers and blobs if anonymous access is provided to potentially sensitive data accidentally. target is 'SE.DS.TMCore.AzureStorage' and target.b3ece90f-c578-4a48-b4d4-89d97614e0d2 is 'Blob'TH85UserThreatDescriptionfalseAn adversary can gain access to Azure storage containers and blobs if anonymous access is provided to potentially sensitive data accidentally.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that only the required containers and blobs are given anonymous read access. Refer: <a href="https://aka.ms/tmt-th85">https://aka.ms/tmt-th85</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can access Azure storage blobs and containers anonymouslyfalseSIf proper authentication is not in place, an adversary can spoof a source process or external entity and gain unauthorized access to the Web Applicationtarget is 'SE.P.TMCore.WebApp'TH86UserThreatDescriptionfalseIf proper authentication is not in place, an adversary can spoof a source process or external entity and gain unauthorized access to the Web Application22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseConsider using a standard authentication mechanism to authenticate to Web Application. Refer: <a href="https://aka.ms/tmtauthn#standard-authn-web-app">https://aka.ms/tmtauthn#standard-authn-web-app</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may spoof {source.Name} and gain access to Web ApplicationfalseSIf proper authentication is not in place, an adversary can spoof a source process or external entity and gain unauthorized access to the Web Application target is 'SE.P.TMCore.WebAPI'TH87UserThreatDescriptionfalseIf proper authentication is not in place, an adversary can spoof a source process or external entity and gain unauthorized access to the Web Application 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that standard authentication techniques are used to secure Web APIs. Refer: <a href="https://aka.ms/tmtauthn#authn-secure-api">https://aka.ms/tmtauthn#authn-secure-api</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may spoof {source.Name} and gain access to Web APIfalseTAn adversary can execute remote code on the server through XSLT scriptingtarget is 'SE.P.TMCore.WebApp' and target.df53c172-b70c-412c-9e99-a6fbc10748ee is 'Yes'TH100UserThreatDescriptionfalseAn adversary can execute remote code on the server through XSLT scripting22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseDisable XSLT scripting for all transforms using untrusted style sheets. Refer: <a href="https://aka.ms/tmtinputval#disable-xslt">https://aka.ms/tmtinputval#disable-xslt</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can execute remote code on the server through XSLT scriptingfalseTAn adversary can tamper critical database securables and deny the actiontarget is 'SE.DS.TMCore.SQL'TH105UserThreatDescriptionfalseAn adversary can tamper critical database securables and deny the action22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseAdd digital signature to critical database securables. Refer: <a href="https://aka.ms/tmtcrypto#securables-db">https://aka.ms/tmtcrypto#securables-db</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can tamper critical database securables and deny the actionfalseTAn adversary may inject malicious inputs into an API and affect downstream processestarget is 'SE.P.TMCore.WebAPI'TH108UserThreatDescriptionfalseAn adversary may inject malicious inputs into an API and affect downstream processes22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that model validation is done on Web API methods. Refer: <a href="https://aka.ms/tmtinputval#validation-api">https://aka.ms/tmtinputval#validation-api</a> Implement input validation on all string type parameters accepted by Web API methods. Refer: <a href="https://aka.ms/tmtinputval#string-api">https://aka.ms/tmtinputval#string-api</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may inject malicious inputs into an API and affect downstream processesfalseTAn Adversary can view the message and may tamper the message target is 'SE.P.TMCore.WCF'TH132UserThreatDescriptionfalseAn Adversary can view the message and may tamper the message 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseWCF: Set Message security Protection level to EncryptAndSign. Refer: <a href="https://aka.ms/tmtcommsec#message-protection">https://aka.ms/tmtcommsec#message-protection</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An Adversary can view the message and may tamper the message falseTAn adversary may spread malware, steal or tamper data due to lack of endpoint protection on devices. Scenarios such as stealing a user's laptop and extracting data from hard disk, luring users to install malware, exploit unpatched OS etc. flow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No' flow crosses 'SE.TB.TMCore.MachineTrustBoundary'TH134UserThreatDescriptionfalseAn adversary may spread malware, steal or tamper data due to lack of endpoint protection on devices. Scenarios such as stealing a user's laptop and extracting data from hard disk, luring users to install malware, exploit unpatched OS etc. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that devices have end point security controls configured as per organizational policies. Refer: <a href="https://aka.ms/tmtconfigmgmt#controls-policies">https://aka.ms/tmtconfigmgmt#controls-policies</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may spread malware, steal or tamper data due to lack of endpoint protection on devicesfalseTAn adversary may reverse engineer deployed binariesflow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.MachineTrustBoundary'TH137UserThreatDescriptionfalseAn adversary may reverse engineer deployed binaries22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that binaries are obfuscated if they contain sensitive information. Refer: <a href="https://aka.ms/tmtdata#binaries-info">https://aka.ms/tmtdata#binaries-info</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may reverse engineer deployed binariesfalseTAn adversary may tamper deployed binariesflow.23e2b6f4-fcd8-4e76-a04a-c9ff9aff4f59 is 'No'flow crosses 'SE.TB.TMCore.MachineTrustBoundary'TH138UserThreatDescriptionfalseAn adversary may tamper deployed binaries22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that deployed application's binaries are digitally signed. Refer: <a href="https://aka.ms/tmtauthn#binaries-signed">https://aka.ms/tmtauthn#binaries-signed</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may tamper deployed binariesfalseTWebsite defacement is an attack on a website where the attacker changes the visual appearance of the site or a webpage. source is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp'TH24UserThreatDescriptionfalseWebsite defacement is an attack on a website where the attacker changes the visual appearance of the site or a webpage. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement Content Security Policy (CSP), and disable inline javascript. Refer: <a href="https://aka.ms/tmtconfigmgmt#csp-js">https://aka.ms/tmtconfigmgmt#csp-js</a> Enable browser's XSS filter. Refer: <a href="https://aka.ms/tmtconfigmgmt#xss-filter">https://aka.ms/tmtconfigmgmt#xss-filter</a> Access third party javascripts from trusted sources only. Refer: <a href="https://aka.ms/tmtconfigmgmt#js-trusted">https://aka.ms/tmtconfigmgmt#js-trusted</a> Enable ValidateRequest attribute on ASP.NET Pages. Refer: <a href="https://aka.ms/tmtconfigmgmt#validate-aspnet">https://aka.ms/tmtconfigmgmt#validate-aspnet</a> Ensure that each page that could contain user controllable content opts out of automatic MIME sniffing . Refer: <a href="https://aka.ms/tmtinputval#out-sniffing">https://aka.ms/tmtinputval#out-sniffing</a> Use locally-hosted latest versions of JavaScript libraries . Refer: <a href="https://aka.ms/tmtconfigmgmt#local-js">https://aka.ms/tmtconfigmgmt#local-js</a> Ensure appropriate controls are in place when accepting files from users. Refer: <a href="https://aka.ms/tmtinputval#controls-users">https://aka.ms/tmtinputval#controls-users</a> Disable automatic MIME sniffing. Refer: <a href="https://aka.ms/tmtconfigmgmt#mime-sniff">https://aka.ms/tmtconfigmgmt#mime-sniff</a> Encode untrusted web output prior to rendering. Refer: <a href="https://aka.ms/tmtinputval#rendering">https://aka.ms/tmtinputval#rendering</a> Perform input validation and filtering on all string type Model properties. Refer: <a href="https://aka.ms/tmtinputval#typemodel">https://aka.ms/tmtinputval#typemodel</a> Ensure that the system has inbuilt defences against misuse. Refer: <a href="https://aka.ms/tmtauditlog#inbuilt-defenses">https://aka.ms/tmtauditlog#inbuilt-defenses</a> Enable HTTP Strict Transport Security (HSTS). Refer: <a href="https://aka.ms/tmtcommsec#http-hsts">https://aka.ms/tmtcommsec#http-hsts</a> Implement input validation on all string type parameters accepted by Controller methods. Refer: <a href="https://aka.ms/tmtinputval#string-method">https://aka.ms/tmtinputval#string-method</a> Avoid using Html.Raw in Razor views. Refer: <a href="https://aka.ms/tmtinputval#html-razor">https://aka.ms/tmtinputval#html-razor</a> Sanitization should be applied on form fields that accept all characters e.g, rich text editor . Refer: <a href="https://aka.ms/tmtinputval#richtext">https://aka.ms/tmtinputval#richtext</a> Do not assign DOM elements to sinks that do not have inbuilt encoding . Refer: <a href="https://aka.ms/tmtinputval#inbuilt-encode">https://aka.ms/tmtinputval#inbuilt-encode</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can deface the target web application by injecting malicious code or uploading dangerous filesfalseTAn attacker steals messages off the network and replays them in order to steal a user's session(source is 'SE.EI.TMCore.Browser' and target is 'SE.P.TMCore.WebApp')TH33UserThreatDescriptionfalseAn attacker steals messages off the network and replays them in order to steal a user's session22222222-2222-2222-2222-2222222222220PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An attacker steals messages off the network and replays them in order to steal a user's sessionfalseTAn adversary may leverage known vulnerabilities and exploit a device if the firmware of the device is not updatedsource is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway'TH39UserThreatDescriptionfalseAn adversary may leverage known vulnerabilities and exploit a device if the firmware of the device is not updated22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that the Cloud Gateway implements a process to keep the connected devices firmware up to date. Refer: <a href="https://aka.ms/tmtconfigmgmt#cloud-firmware">https://aka.ms/tmtconfigmgmt#cloud-firmware</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may exploit known vulnerabilities in unpatched devicesfalseTAn adversary may partially or wholly replace the software running on {target.Name}, potentially allowing the replaced software to leverage the genuine identity of the device if the key material or the cryptographic facilities holding key materials were available to the illicit program. For example an attacker may leverage extracted key material to intercept and suppress data from the device on the communication path and replace it with false data that is authenticated with the stolen key material.source is 'SE.EI.TMCore.IoTdevice' or source is 'SE.GP.TMCore.IoTFieldGateway'TH43UserThreatDescriptionfalseAn adversary may partially or wholly replace the software running on {target.Name}, potentially allowing the replaced software to leverage the genuine identity of the device if the key material or the cryptographic facilities holding key materials were available to the illicit program. For example an attacker may leverage extracted key material to intercept and suppress data from the device on the communication path and replace it with false data that is authenticated with the stolen key material.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseStore Cryptographic Keys securely on IoT Device. Refer: <a href="https://aka.ms/tmtcrypto#keys-iot">https://aka.ms/tmtcrypto#keys-iot</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may tamper {source.Name} and extract cryptographic key material from itfalseTAn adversary may perform a Man-In-The-Middle attack on the encrypted traffic sent to {target.Name}(source is 'SE.GP.TMCore.IoTFieldGateway' or source is 'SE.GP.TMCore.IoTCloudGateway') and (target is 'SE.EI.TMCore.IoTdevice' or target is 'SE.GP.TMCore.IoTFieldGateway')TH45UserThreatDescriptionfalseAn adversary may perform a Man-In-The-Middle attack on the encrypted traffic sent to {target.Name}22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseVerify X.509 certificates used to authenticate SSL, TLS, and DTLS connections. Refer: <a href="https://aka.ms/tmtcommsec#x509-ssltls">https://aka.ms/tmtcommsec#x509-ssltls</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may attempt to intercept encrypted traffic sent to {target.Name}falseTAn adversary may launch malicious code into {target.Name} and execute ittarget is 'SE.EI.TMCore.IoTdevice' or target is 'SE.GP.TMCore.IoTFieldGateway'TH46UserThreatDescriptionfalseAn adversary may launch malicious code into {target.Name} and execute it22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that unknown code cannot execute on devices. Refer: <a href="https://aka.ms/tmtconfigmgmt#unknown-exe">https://aka.ms/tmtconfigmgmt#unknown-exe</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may execute unknown code on {target.Name}falseTAn adversary may launch offline attacks made by disabling or circumventing the installed operating system, or made by physically separating the storage media from the device in order to attack the data separately.source is 'SE.EI.TMCore.IoTdevice'TH47UserThreatDescriptionfalseAn adversary may launch offline attacks made by disabling or circumventing the installed operating system, or made by physically separating the storage media from the device in order to attack the data separately.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEncrypt OS and additional partitions of IoT Device with Bitlocker. Refer: <a href="https://aka.ms/tmtconfigmgmt#partition-iot">https://aka.ms/tmtconfigmgmt#partition-iot</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may tamper the OS of a device and launch offline attacksfalseTAn adversary may eavesdrop and interfere with the communication between a client and Event Hub and possibly tamper the data that is transmittedtarget is 'SE.P.TMCore.AzureEventHub'TH61UserThreatDescriptionfalseAn adversary may eavesdrop and interfere with the communication between a client and Event Hub and possibly tamper the data that is transmitted22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseSecure communication to Event Hub using SSL/TLS. Refer: <a href="https://aka.ms/tmtcommsec#comm-ssltls">https://aka.ms/tmtcommsec#comm-ssltls</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may eavesdrop the communication between the a client and Event HubfalseTAn adversary can tamper the data uploaded to {target.Name} storage when HTTPS cannot be enabled.target is 'SE.DS.TMCore.AzureStorage' and target.b3ece90f-c578-4a48-b4d4-89d97614e0d2 is 'Blob' and target.229f2e53-bc3f-476c-8ac9-57da37efd00f is 'True'target is 'SE.DS.TMCore.AzureStorage' and target.b3ece90f-c578-4a48-b4d4-89d97614e0d2 is 'Blob'TH66UserThreatDescriptionfalseAn adversary can tamper the data uploaded to {target.Name} storage when HTTPS cannot be enabled.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseValidate the hash (which should be generated using a cryptographically strong hashing algorithm) after downloading the blob if HTTPS cannot be enabled.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can tamper the data uploaded to {target.Name} when HTTPS cannot be enabledfalseTThe source of a package is the individual or organization that created the package. Running a package from an unknown or untrusted source might be risky.target is 'SE.DS.TMCore.SQL' and target.649208cc-3b55-40ff-94b9-015c0fb0c9e8 is 'Yes'TH88UserThreatDescriptionfalseThe source of a package is the individual or organization that created the package. Running a package from an unknown or untrusted source might be risky.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseSSIS packages should be encrypted and digitally signed . Refer: <a href="https://aka.ms/tmtcrypto#ssis-signed">https://aka.ms/tmtcrypto#ssis-signed</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can tamper SSIS packages and cause undesirable consequencesfalseTAn adversary may leverage the lack of intrusion detection and prevention of anomalous database activities and trigger anomalous traffic to databasetarget is 'SE.DS.TMCore.SQL'TH89UserThreatDescriptionfalseAn adversary may leverage the lack of intrusion detection and prevention of anomalous database activities and trigger anomalous traffic to database22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable Threat detection on Azure SQL database. Refer: <a href="https://aka.ms/tmtauditlog#threat-detection">https://aka.ms/tmtauditlog#threat-detection</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may leverage the lack of monitoring systems and trigger anomalous traffic to databasefalseTAn adversary may gain unauthorized access to {source.Name}, tamper its OS and get access to confidential information in the field gatewaysource is 'SE.GP.TMCore.IoTFieldGateway'TH92UserThreatDescriptionfalseAn adversary may gain unauthorized access to {source.Name}, tamper its OS and get access to confidential information in the field gateway22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEncrypt OS and additional partitions of IoT Field Gateway with Bitlocker. Refer: <a href="https://aka.ms/tmtconfigmgmt#field-bitlocker">https://aka.ms/tmtconfigmgmt#field-bitlocker</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to IoT Field Gateway and tamper its OSfalseTAn adversary can use various tools, reverse engineer binaries and abuse them by tamperingsource is 'SE.EI.TMCore.Mobile'TH95UserThreatDescriptionfalseAn adversary can use various tools, reverse engineer binaries and abuse them by tampering22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseObfuscate generated binaries before distributing to end users. Refer: <a href="https://aka.ms/tmtdata#binaries-end">https://aka.ms/tmtdata#binaries-end</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can reverse engineer and tamper binariesfalseTSQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed. target is 'SE.P.TMCore.WebApp'TH96UserThreatDescriptionfalseSQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that type-safe parameters are used in Web Application for data access. Refer: <a href="https://aka.ms/tmtinputval#typesafe">https://aka.ms/tmtinputval#typesafe</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data by performing SQL injection through Web AppfalseTSQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed. target is 'SE.P.TMCore.WebAPI'TH97UserThreatDescriptionfalseSQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that type-safe parameters are used in Web API for data access. Refer: <a href="https://aka.ms/tmtinputval#typesafe-api">https://aka.ms/tmtinputval#typesafe-api</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data by performing SQL injection through Web APIfalseTAn adversary can gain access to the config files. and if sensitive data is stored in it, it would be compromised.target is 'SE.P.TMCore.WebApp'TH98UserThreatDescriptionfalseAn adversary can gain access to the config files. and if sensitive data is stored in it, it would be compromised.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEncrypt sections of Web App's configuration files that contain sensitive data. Refer: <a href="https://aka.ms/tmtdata#encrypt-data">https://aka.ms/tmtdata#encrypt-data</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to sensitive data stored in Web App's config filesfalseEAn adversary can gain unauthorized access to Azure SQL DB instances due to weak network security configuration.target is 'SE.DS.TMCore.AzureSQLDB' and not target.e68e212d-896e-403e-8a2d-8c6d2b2505df is 'Allow access from selected networks'TH143UserThreatDescriptionfalseAn adversary can gain unauthorized access to Azure SQL DB instances due to weak network security configuration.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict access to Azure SQL Database instances by configuring server-level and database-level firewall rules to permit connections from selected networks (e.g. a virtual network or a custom set of IP addresses) where possible. Refer:<a href="https://aka.ms/tmt-th143">https://aka.ms/tmt-th143</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to Azure SQL DB instances due to weak network security configuration.falseIAn adversary can read confidential data due to weak connection string configuration.target is 'SE.DS.TMCore.AzureSQLDB'TH144UserThreatDescriptionfalseAn adversary can read confidential data due to weak connection string configuration.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseClients connecting to an Azure SQL Database instance using a connection string should ensure encrypt=true and trustservercertificate=false are set. This configuration ensures that connections are encrypted only if there is a verifiable server certificate (otherwise the connection attempt fails). This helps protect against Man-In-The-Middle attacks. Refer: <a href="https://aka.ms/tmt-th144">https://aka.ms/tmt-th144</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can read confidential data due to weak connection string configurationfalseIAn adversary having access to the storage container (e.g. physical access to the storage media) may be able to read sensitive data.target is 'SE.DS.TMCore.AzureSQLDB' and not target.3a2a095f-94bc-467f-987c-8dac8307cdc6 is 'True'TH145UserThreatDescriptionfalseAn adversary having access to the storage container (e.g. physical access to the storage media) may be able to read sensitive data.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable Transparent Data Encryption (TDE) on Azure SQL Database instances to have data encrypted at rest. Refer:<a href="https://aka.ms/tmt-th145a">https://aka.ms/tmt-th145a</a>. Use the Always Encrypted feature to allow client applications to encrypt sensitive data before it is sent to the Azure SQL Database. Refer: <a href="https://aka.ms/tmt-th145b">https://aka.ms/tmt-th145b</a> 22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary having access to the storage container (e.g. physical access to the storage media) may be able to read sensitive datafalseEA compromised identity may permit more privileges than intended to an adversary due to weak permission and role assignments.target is 'SE.DS.TMCore.AzureSQLDB'TH146UserThreatDescriptionfalseA compromised identity may permit more privileges than intended to an adversary due to weak permission and role assignments.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseIt is recommended to review permission and role assignments to ensure the users are granted the least privileges necessary. Refer: <a href="https://aka.ms/tmt-th146">https://aka.ms/tmt-th146</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221A compromised identity may permit more privileges than intended to an adversary due to weak permission and role assignmentsfalseRAn adversary can deny actions performed on {target.Name} due to a lack of auditing.target is 'SE.DS.TMCore.AzureSQLDB' and target.6a3509e5-a3fd-41db-8dea-6fb44b031e4b is 'True'target is 'SE.DS.TMCore.AzureSQLDB'TH147UserThreatDescriptionfalseAn adversary can deny actions performed on {target.Name} due to a lack of auditing.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable auditing on Azure SQL Database instances to track and log database events. After configuring and customizing the audited events, enable threat detection to receive alerts on anomalous database activities indicating potential security threats. Refer: <a href="https://aka.ms/tmt-th147">https://aka.ms/tmt-th147</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary can deny actions performed on {target.Name} due to a lack of auditingfalseEAn adversary can gain long term, persistent access to an Azure SQL DB instance through the compromise of local user account password(s).target is 'SE.DS.TMCore.AzureSQLDB'TH148UserThreatDescriptionfalseAn adversary can gain long term, persistent access to an Azure SQL DB instance through the compromise of local user account password(s).22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseIt is recommended to rotate user account passwords (e.g. those used in connection strings) regularly, in accordance with your organization's policies. Store secrets in a secret storage solution (e.g. Azure Key Vault).22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain long term, persistent access to an Azure SQL DB instance through the compromise of local user account password(s)falseEAn adversary may abuse weak {target.Name} configuration.target is 'SE.DS.TMCore.AzureSQLDB' and target.212cf67e-047a-4617-860f-92282e04b8d8 is 'True'target is 'SE.DS.TMCore.AzureSQLDB'TH149UserThreatDescriptionfalseAn adversary may abuse weak {target.Name} configuration.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable SQL Vulnerability Assessment to gain visibility into the security posture of your Azure SQL Database instances. Acting on the assessment results help reduce attack surface and enhance your database security. Refer: <a href="https://aka.ms/tmt-th149">https://aka.ms/tmt-th149</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may abuse weak {target.Name} configurationfalseEAn adversary can gain unauthorized access to {target.Name} instances due to weak network security configuration.target is 'SE.DS.TMCore.AzureMySQLDB' and not target.9afccb81-bc8b-4527-ad05-f90ec3e396cb is 'Allow access from selected networks'TH150UserThreatDescriptionfalseAn adversary can gain unauthorized access to Azure MySQL DB instances due to weak network security configuration.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict access to Azure MySQL DB instances by configuring server-level firewall rules to only permit connections from selected IP addresses where possible. Refer: <a href="https://aka.ms/tmt-th150">https://aka.ms/tmt-th150</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to Azure MySQL DB instances due to weak network security configurationfalseTAn adversary may read and/or tamper with the data transmitted to {target.Name} due to weak configuration.target is 'SE.DS.TMCore.AzureMySQLDB' and not target.4d3b2548-8c31-460e-88e5-4c26135003ac is 'True'TH151UserThreatDescriptionfalseAn adversary may read and/or tamper with the data transmitted to Azure MySQL DB due to weak configuration.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnforce communication between clients and Azure MySQL DB to be over SSL/TLS by enabling the Enforce SSL connection feature on the server. Check that the connection strings used to connect to MySQL databases have the right configuration (e.g. ssl = true or sslmode=require or sslmode=true are set). Refer: <a href="https://aka.ms/tmt-th151a">https://aka.ms/tmt-th151a</a> Configure MySQL server to use a verifiable SSL certificate (needed for SSL/TLS communication). Refer: <a href="https://aka.ms/tmt-th151b">https://aka.ms/tmt-th151b</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may read and/or tamper with the data transmitted to Azure MySQL DB due to weak configurationfalseEAn adversary can gain long term, persistent access to {target.Name} instance through the compromise of local user account password(s).target is 'SE.DS.TMCore.AzureMySQLDB'TH152UserThreatDescriptionfalseAn adversary can gain long term, persistent access to an Azure MySQL DB instance through the compromise of local user account password(s).22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseIt is recommended to rotate user account passwords (e.g. those used in connection strings) regularly, in accordance with your organization's policies. Store secrets in a secret storage solution (e.g. Azure Key Vault).22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain long term, persistent access to an Azure MySQL DB instance through the compromise of local user account password(s)falseEAn adversary can gain unauthorized access to {target.Name} instances due to weak network security configuration.target is 'SE.DS.TMCore.AzurePostgresDB' and not target.ba682010-cfcf-4916-9f88-524f8d9ce8a8 is 'Allow access from selected networks'TH153UserThreatDescriptionfalseAn adversary can gain unauthorized access to Azure Postgres DB instances due to weak network security configuration.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict access to Azure Postgres DB instances by configuring server-level firewall rules to only permit connections from selected IP addresses where possible. Refer: <a href="https://aka.ms/tmt-th153">https://aka.ms/tmt-th153</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to Azure Postgres DB instances due to weak network security configurationfalseTAn adversary may read and/or tamper with the data transmitted to {target.Name} due to weak configuration.target is 'SE.DS.TMCore.AzurePostgresDB' and not target.65a8827c-6efd-4243-aa81-0625c4aea98e is 'True'TH154UserThreatDescriptionfalseAn adversary may read and/or tamper with the data transmitted to Azure Postgres DB due to weak configuration.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnforce communication between clients and Azure Postgres DB to be over SSL/TLS by enabling the Enforce SSL connection feature on the server. Check that the connection strings used to connect to MySQL databases have the right configuration (e.g. ssl = true or sslmode=require or sslmode=true are set). Refer: <a href="https://aka.ms/tmt-th154a">https://aka.ms/tmt-th154a</a> Configure MySQL server to use a verifiable SSL certificate (needed for SSL/TLS communication). Refer: <a href="https://aka.ms/tmt-th154b">https://aka.ms/tmt-th154b</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may read and/or tamper with the data transmitted to Azure Postgres DB due to weak configurationfalseEAn adversary can gain long term, persistent access to {target.Name} instance through the compromise of local user account password(s).target is 'SE.DS.TMCore.AzurePostgresDB'TH155UserThreatDescriptionfalseAn adversary can gain long term, persistent access to an Azure Postgres DB instance through the compromise of local user account password(s).22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseIt is recommended to rotate user account passwords (e.g. those used in connection strings) regularly, in accordance with your organization's policies. Store secrets in a secret storage solution (e.g. Azure Key Vault).22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain long term, persistent access to an Azure Postgres DB instance through the compromise of local user account password(s)falseEAn adversary can gain unauthorized access to {target.Name} due to weak account policytarget is 'SE.DS.TMCore.AzureSQLDWDB'TH156UserThreatDescriptionfalseAn adversary can gain unauthorized access to {target.Name} due to weak account policy22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseWhen possible use Azure Active Directory Authentication for Connecting to SQL DW Database. Refer: <a href="https://aka.ms/tmt-th156a">https://aka.ms/tmt-th156a</a>. Ensure that least-privileged accounts are used to connect to SQL DW Database. Refer: <a href="https://aka.ms/tmt-th156b">https://aka.ms/tmt-th156b</a> and <a href="https://aka.ms/tmt-th156c">https://aka.ms/tmt-th156c</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to {target.Name} due to weak account policyfalseEAn adversary can gain unauthorized access to {target.Name} instances due to weak network security configurationtarget is 'SE.DS.TMCore.AzureSQLDWDB' and not target.b8c8850c-979b-4db0-b536-9aa364b7e6a2 is 'Allow access from selected networks (excluding Azure)'TH157UserThreatDescriptionfalseAn adversary can gain unauthorized access to Azure SQL DW DB instances due to weak network security configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict access to Azure SQL DW DB instances by configuring server-level firewall rules to permit connections from selected networks (e.g. a virtual network or a custom set of IP addresses) where possible. Refer: <a href="https://aka.ms/tmt-th157">https://aka.ms/tmt-th157</a>.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to Azure SQL DW DB instances due to weak network security configurationfalseTAn adversary can read confidential data or tamper with it due to weak connection string configuration at {target.Name} target is 'SE.DS.TMCore.AzureSQLDWDB'TH158UserThreatDescriptionfalseAn adversary can read confidential data or tamper with it due to weak connection string configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseClients connecting to a Azure SQL DW DB instance using a connection string should ensure that encryption is enabled and trusting the server certificate by default is disabled (e.g. encrypt=true and trustservercertificate=false are set). This configuration ensures that connections are encrypted only if there is a verifiable server certificate (otherwise the connection attempt fails). This helps protect against Man-In-The-Middle attacks. Refer: <a href="https://aka.ms/tmt-th158">https://aka.ms/tmt-th158</a>.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can read confidential data or tamper with it due to weak connection string configurationfalseIAn adversary having access to the storage container (e.g. physical access to the storage media) may read sensitive datatarget is 'SE.DS.TMCore.AzureSQLDWDB' and not target.d2ce181d-abae-448d-8ef4-9acdbeb839fe is 'True'TH159UserThreatDescriptionfalseAn adversary having access to the storage container (e.g. physical access to the storage media) may read sensitive data22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable Transparent Data Encryption (TDE) on Azure SQL Data Warehouse Database instances to have data encrypted at rest. Refer: <a href="https://aka.ms/tmt-th159">https://aka.ms/tmt-th159</a>.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary having access to the storage container (e.g. physical access to the storage media) may read sensitive datafalseEAn identity that is compromised may permit more privileges than intended to an adversary due to weak permission and role assignmentstarget is 'SE.DS.TMCore.AzureSQLDWDB'TH160UserThreatDescriptionfalseAn identity that is compromised may permit more privileges than intended to an adversary due to weak permission and role assignments22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseReview permission and role assignments to ensure users are granted the least privileges necessary. Refer: <a href="https://aka.ms/tmt-th160">https://aka.ms/tmt-th160</a>.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An identity that is compromised may permit more privileges than intended to an adversary due to weak permission and role assignmentsfalseRAn adversary can deny actions performed on {target.Name} due to lack of auditingtarget is 'SE.DS.TMCore.AzureSQLDWDB' and not target.cd2a18a2-cebd-4b0f-ae4c-964b190e84f2 is 'True'TH161UserThreatDescriptionfalseAn adversary can deny actions performed on {target.Name} due to lack of auditing22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable auditing on Azure SQL DW DB instances to track and log database events. After configuring and customizing the audited events, enable threat detection to receive alerts on anomalous activities indicating potential security threats. Refer: <a href="https://aka.ms/tmt-th161">https://aka.ms/tmt-th161</a>.22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can deny actions performed on {target.Name} due to lack of auditingfalseEAn adversary can gain long term, persistent access to {target.Name} through a compromise of its connection string(s)target is 'SE.DS.TMCore.AzureSQLDWDB'TH162UserThreatDescriptionfalseAn adversary can gain long term, persistent access to {target.Name} through a compromise of its connection string(s)22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseIt is recommended to rotate user account passwords (e.g. those used in connection strings) regularly, in accordance with your organization's policies. Store secrets in a secret storage solution (e.g. Azure Key Vault).22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain long term, persistent access to {target.Name} through a compromise of its connection string(s)falseEAn adversary can gain unauthorized access to {target.Name} instances due to weak network security configurationtarget is 'SE.P.TMCore.AzureRedis' and not target.1bda806d-f9b6-4d4e-ab89-bf649f2c2ca5 is 'Allow access from selected networks'TH163UserThreatDescriptionfalseAn adversary can gain unauthorized access to {target.Name} instances due to weak network security configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict access to Azure Redis Cache instances by configuring firewall rules to only permit connections from selected IP addresses or VNETs where possible. Refer: <a href="https://aka.ms/tmt-th163">https://aka.ms/tmt-th163</a>.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to {target.Name} instances due to weak network security configurationfalseEAn adversary can gain long term, persistent access to {target.Name} instance through a compromise of its access key(s)target is 'SE.P.TMCore.AzureRedis'TH164UserThreatDescriptionfalseAn adversary can gain long term, persistent access to {target.Name} instance through a compromise of its access key(s)22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseIt is recommended to rotate user account passwords (e.g. those used in connection strings) regularly, in accordance with your organization's policies. Store secrets in a secret storage solution (e.g. Azure Key Vault).22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain long term, persistent access to {target.Name} instance through a compromise of its access key(s)falseDAn adversary may block access to the application or API hosted on {target.Name} through a denial of service attacktarget is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp'TH165UserThreatDescriptionfalseAn adversary may block access to the application or API hosted on {target.Name} through a denial of service attack22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseNetwork level denial of service mitigations are automatically enabled as part of the Azure platform (Basic Azure DDoS Protection). Refer: <a href="https://aka.ms/tmt-th165a">https://aka.ms/tmt-th165a</a>. Implement application level throttling (e.g. per-user, per-session, per-API) to maintain service availability and protect against DoS attacks. Leverage Azure API Management for managing and protecting APIs. Refer: <a href="https://aka.ms/tmt-th165b">https://aka.ms/tmt-th165b</a>. General throttling guidance, refer: <a href="https://aka.ms/tmt-th165c">https://aka.ms/tmt-th165c</a> 22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may block access to the application or API hosted on {target.Name} through a denial of service attackfalseEAn adversary may gain long term persistent access to related resources through the compromise of an application identitytarget is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp'TH166UserThreatDescriptionfalseAn adversary may gain long term persistent access to related resources through the compromise of an application identity22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseStore secrets in secret storage solutions where possible, and rotate secrets on a regular cadence. Use Managed Service Identity to create a managed app identity on Azure Active Directory and use it to access AAD-protected resources. Refer: <a href="https://aka.ms/tmt-th166">https://aka.ms/tmt-th166</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain long term persistent access to related resources through the compromise of an application identityfalseEAn adversary may gain unauthorized access to {target.Name} due to weak network configuration(target is 'SE.P.TMCore.AzureAppServiceWebApp' and not target.327ab565-9b38-4f6a-8171-6ab7deb2246b is 'Allow access from selected networks') or (target is 'SE.P.TMCore.AzureAppServiceApiApp' and not target.cb0fca77-c600-4622-b9a5-118107fcd9dd is 'Allow access from selected networks') or (target is 'SE.P.TMCore.AzureAppServiceMobileApp' and not target.9b54ed83-3970-475b-97a0-be7641051497 is 'Allow access from selected networks')TH167UserThreatDescriptionfalseAn adversary may gain unauthorized access to {target.Name} due to weak network configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict access to Azure App Service to selected networks (e.g. IP whitelisting, VNET integrations). Refer: <a href="https://aka.ms/tmt-th167">https://aka.ms/tmt-th167</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to {target.Name} due to weak network configurationfalseIAn adversary can achieve remote code execution on a server hosting an application or API by exploiting JSON deserialization logic(source is 'GE.EI' or source is 'SE.EI.TMCore.Browser') and ((target is 'SE.P.TMCore.AzureAppServiceWebApp' and target.d69db950-2372-4bd3-8328-f751f0b04c03 is 'True') or (target is 'SE.P.TMCore.AzureAppServiceApiApp' and target.0945adcf-1cfd-432f-8032-05391ab62336 is 'True') or (target is 'SE.P.TMCore.AzureAppServiceMobileApp' and target.015d94e3-d54e-4c09-9ce2-2731a0dc86f0 is 'True'))TH168UserThreatDescriptionfalseAn adversary can achieve remote code execution on a server hosting an application or API by exploiting JSON deserialization logic22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure serialized objects from untrusted sources are not being deserialized, or handle objects that have been serialized using a serializer that only permits primitive data types. Refer: <a href="https://aka.ms/tmt-th168">https://aka.ms/tmt-th168</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can achieve remote code execution on a server hosting an application or API by exploiting JSON deserialization logicfalseIAn adversary can achieve remote code execution on a server hosting an application or API by exploiting XML parsing logic or through XSLT scripting(source is 'GE.EI' or source is 'SE.EI.TMCore.Browser') and ((target is 'SE.P.TMCore.AzureAppServiceWebApp' and target.049c845a-28c2-46f8-bda2-971ff7df9bd4 is 'True') or (target is 'SE.P.TMCore.AzureAppServiceApiApp' and target.0eb10857-97b7-4c8c-8fdd-c289b7921a7e is 'True') or (target is 'SE.P.TMCore.AzureAppServiceMobileApp' and target.6c7ab607-e310-4d74-aa5b-397d87f02ee9 is 'True'))TH169UserThreatDescriptionfalseAn adversary can achieve remote code execution on a server hosting an application or API by exploiting XML parsing logic or through XSLT scripting22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseDisable XSLT scripting for all transforms using untrusted style sheets. Refer: <a href="https://aka.ms/tmt-th169a">https://aka.ms/tmt-th169a</a>. Disable DTD processing and external entity resolution on XML parsers to protect against XXE attacks. Refer: <a href="https://aka.ms/tmt-th169b">https://aka.ms/tmt-th169b</a>, <a href="https://aka.ms/tmt-th169c">https://aka.ms/tmt-th169c</a>, <a href="https://aka.ms/tmt-th169d">https://aka.ms/tmt-th169d</a> and <a href="https://aka.ms/tmt-th169e">https://aka.ms/tmt-th169e</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can achieve remote code execution on a server hosting an application or API by exploiting XML parsing logic or through XSLT scriptingfalseIAttacker can steal user session cookies due to insecure cookie attributessource is 'SE.EI.TMCore.Browser' and (target is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp')TH170UserThreatDescriptionfalseAttacker can steal user session cookies due to insecure cookie attributes22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseApplications available over HTTPS must use secure cookies. Refer: <a href="https://aka.ms/tmt-th170a">https://aka.ms/tmt-th170a</a>. All HTTP based applications should specify http only for cookie definition. Refer: <a href="https://aka.ms/tmt-th170b">https://aka.ms/tmt-th170b</a> and <a href="https://aka.ms/tmt-th170c">https://aka.ms/tmt-th170c</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221Attacker can steal user session cookies due to insecure cookie attributesfalseEAn adversary may get access to a user's session due to improper logout from ADFSsource is 'SE.P.TMCore.ADFS' and (target is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp')TH171UserThreatDescriptionfalseAn adversary may get access to a user's session due to improper logout from ADFS22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement proper logout using WsFederation methods when using ADFS. Refer: <a href="https://aka.ms/tmt-th171">https://aka.ms/tmt-th171</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may get access to a user's session due to improper logout from ADFSfalseEAn adversary may get access to a user's session due to improper logout from Azure ADsource is 'SE.P.TMCore.AzureAD' and (target is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp')TH172UserThreatDescriptionfalseAn adversary may get access to a user's session due to improper logout from Azure AD22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement proper logout using ADAL methods when using Azure AD. Refer: <a href="https://aka.ms/tmt-th172">https://aka.ms/tmt-th172</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may get access to a user's session due to improper logout from Azure ADfalseRAn adversary can deny performing actions against {target.Name} due to lack of auditing, leading to repudiation issues(source is 'GE.EI' or source is 'SE.EI.TMCore.Browser') and (target is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp')TH173UserThreatDescriptionfalseAn adversary can deny performing actions against {target.Name} due to lack of auditing, leading to repudiation issues22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseImplement application level auditing and logging, especially for sensitive operations, like accessing secrets from secrets storage solutions. Other examples include user management events like successful and failed user logins, password resets, password changes, account lockouts and user registrations.22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can deny performing actions against {target.Name} due to lack of auditing, leading to repudiation issuesfalseIAn adversary can fingerprint an Azure web application or API by leveraging server header information(source is 'GE.EI' or source is 'SE.EI.TMCore.Browser') and (target is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp')TH174UserThreatDescriptionfalseAn adversary can fingerprint an Azure web application or API by leveraging server header information22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRemove standard server headers to avoid fingerprinting. Refer: <a href="https://aka.ms/tmt-th174a">https://aka.ms/tmt-th174a</a> and <a href="https://aka.ms/tmt-th174b">https://aka.ms/tmt-th174b</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can fingerprint an Azure web application or API by leveraging server header informationfalseTAn adversary can read sensitive data by sniffing or intercepting traffic to {target.Name}source is 'SE.EI.TMCore.Browser' and (target is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp')TH175UserThreatDescriptionfalseAn adversary can read sensitive data by sniffing or intercepting traffic to {target.Name}22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseConfigure SSL certificate for custom domain in Azure App Service. Force all HTTP traffic to the app service to be over HTTPS by enabling the HTTPS only option on the instance. Refer: <a href="https://aka.ms/tmt-th175a">https://aka.ms/tmt-th175a</a> and <a href="https://aka.ms/tmt-th175b">https://aka.ms/tmt-th175b</a>. Enable HTTP Strict Transport Security (HSTS). Refer: <a href="https://aka.ms/tmt-th175c">https://aka.ms/tmt-th175c</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can read sensitive data by sniffing or intercepting traffic to {target.Name}falseEAn adversary may perform action(s) on behalf of another user due to lack of controls against cross domain requests(target is 'SE.P.TMCore.AzureAppServiceWebApp' and target.f6b0309d-2020-4c3f-838f-5ab8ea0d2194 is 'False') or (target is 'SE.P.TMCore.AzureAppServiceApiApp' and target.3f4a2250-9087-44c1-9fb7-61e9eb1e4df7 is 'False') or (target is 'SE.P.TMCore.AzureAppServiceMobileApp' and target.6ddbac5e-2e11-4b88-b917-587749ea4721 is 'False')target is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp'TH176UserThreatDescriptionfalseAn adversary may perform action(s) on behalf of another user due to lack of controls against cross domain requests22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that only trusted origins are allowed if CORS is being used. Refer: <a href="https://aka.ms/tmt-th176">https://aka.ms/tmt-th176</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may perform action(s) on behalf of another user due to lack of controls against cross domain requestsfalseSAn adversary may be able to perform action(s) on behalf of another user due to lack of controls against cross domain requestssource is 'SE.EI.TMCore.Browser' and (target is 'SE.P.TMCore.AzureAppServiceWebApp' or target is 'SE.P.TMCore.AzureAppServiceApiApp' or target is 'SE.P.TMCore.AzureAppServiceMobileApp')TH177UserThreatDescriptionfalseAn adversary may be able to perform action(s) on behalf of another user due to lack of controls against cross domain requests22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure that authenticated pages incorporate UI Redressing or clickjacking defences. Refer: <a href="https://aka.ms/tmt-th177a">https://aka.ms/tmt-th177a</a>. Mitigate against Cross-Site Request Forgery (CSRF) attacks. Refer: <a href="https://aka.ms/tmt-th177b">https://aka.ms/tmt-th177b</a> and <a href="https://aka.ms/tmt-th177c">https://aka.ms/tmt-th177c</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may be able to perform action(s) on behalf of another user due to lack of controls against cross domain requestsfalseSAn adversary may spoof the service or service endpoints by leveraging stale CNAME DNS records and executing a subdomain hijack attacktarget is 'SE.P.TMCore.AzureTrafficManager'TH178UserThreatDescriptionfalseAn adversary may spoof the service or service endpoints by leveraging stale CNAME DNS records and executing a subdomain hijack attack22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseAddress stale CNAME DNS records mapping custom domain names to the domain name of the Azure Traffic Manager instance. In some cases, deleting the stale CNAME records may be sufficient, while in other cases, the domain name of the Azure Traffic Manager instance should be kept to prevent subdomain hijack attacks. Refer: <a href="https://aka.ms/tmt-th178 ">https://aka.ms/tmt-th178 </a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may spoof the service or service endpoints by leveraging stale CNAME DNS records and executing a subdomain hijack attackfalseEAn adversary can gain unauthorized access to Azure Key Vault instances due to weak network security configuration.target is 'SE.DS.TMCore.AzureKeyVault' and not target.cd610fb8-4fbd-49c0-966f-8b4634b39262 is 'Allow access from selected networks'TH179UserThreatDescriptionfalseAn adversary can gain unauthorized access to Azure Key Vault instances due to weak network security configuration.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict access to Azure Key Vault instances by configuring firewall rules to permit connections from selected networks (e.g. a virtual network or a custom set of IP addresses).For Key Vault client applications behind a firewall trying to access a Key Vault instance, see best practices mentioned here: <a href="https://aka.ms/tmt-th179 ">https://aka.ms/tmt-th179 </a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain unauthorized access to Azure Key Vault instances due to weak network security configuration.falseRAn adversary can deny actions performed on {target.Name} due to a lack of auditing. target is 'SE.DS.TMCore.AzureKeyVault' and not target.78bf9482-5267-41c6-84fd-bac2fb6ca0b9 is 'True'TH180UserThreatDescriptionfalseAn adversary can deny actions performed on {target.Name} due to a lack of auditing. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable audit logging on Azure Key Vault instances to monitor how and when the instances are access, and by whom. Use standard Azure access controls to restrict access to the logs. Refer : <a href="https://aka.ms/tmt-th180 ">https://aka.ms/tmt-th180 </a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can deny actions performed on {target.Name} due to a lack of auditing. falseEAn adversary may gain unauthorized access to manage {target.Name} due to weak authorization rules. target is 'SE.DS.TMCore.AzureKeyVault'TH181UserThreatDescriptionfalseAn adversary may gain unauthorized access to manage {target.Name} due to weak authorization rules.22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseAccess to the Azure Key Vault management plane should be restricted by choosing appropriate Role-Based Access Control (RBAC) roles and privileges in accordance with the principle of least privilege. Over permissive or weak authorization rules may potentially permit data plane access (e.g. a user with Contribute (RBAC) permissions to Key Vault management plane may grant themselves access to the data plane by setting the Azure Key Vault access policy). Refer : <a href="https://aka.ms/tmt-th181 ">https://aka.ms/tmt-th181 </a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to manage {target.Name} due to weak authorization rules.falseEAn adversary may gain unauthorized access to {target.Name} secrets due to weak authorization rules target is 'SE.DS.TMCore.AzureKeyVault'TH182UserThreatDescriptionfalseAn adversary may gain unauthorized access to {target.Name} secrets due to weak authorization rules22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseLimit Azure Key Vault data plane access by configuring strict access policies. Grant users, groups and applications the ability to perform only the necessary operations against keys or secrets in a Key Vault instance. Follow the principle of least privilege and grant privileges only as needed. Refer : <a href="https://aka.ms/tmt-th181 ">https://aka.ms/tmt-th181 </a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to {target.Name} secrets due to weak authorization rulesfalseEAn adversary can abuse poorly managed service principal Certificate. An adversary may gain unauthorized access to {target.Name} due to compromise of User or Service Principal . target is 'SE.DS.TMCore.AzureKeyVault' and target.ae94fa17-596d-476e-a283-0afc166dcf26 is 'Service or User Principal and Certificate'TH183UserThreatDescriptionfalseAn adversary can abuse poorly managed service principal Certificate. An adversary may gain unauthorized access to {target.Name} due to compromise of User or Service Principal .22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure secure management and storage of Azure Key Vault Service/User Principal certificate. It is recommended to rotate service principal certificate regularly, in accordance with organizational policies. If supported , use managed identities for Azure resources and details can be found here. Refer : <a href="https://aka.ms/tmt-th183 ">https://aka.ms/tmt-th183 </a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can abuse poorly managed service principal Certificate. An adversary may gain unauthorized access to {target.Name} due to compromise of User or Service Principal . falseEAn adversary can abuse poorly managed service principal secret. An adversary may gain unauthorized access to {target.Name} due to compromise of Service Principal Secret . target is 'SE.DS.TMCore.AzureKeyVault' and target.ae94fa17-596d-476e-a283-0afc166dcf26 is 'Service or User Principal and Secret' TH184UserThreatDescriptionfalseAn adversary can abuse poorly managed service principal secret. An adversary may gain unauthorized access to {target.Name} due to compromise of Service Principal Secret .22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse managed identities for Azure resources and details can be found here at <a href="https://aka.ms/tmt-th183 ">https://aka.ms/tmt-th183</a>. If managed identities is not supported , use Service/User Principal and Certificate. If none of the above options are feasible, please ensure secure management and storage of Azure Key Vault Service/User Principal secret . It is recommended to rotate service/user principal secret regularly, in accordance with organizational policies.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can abuse poorly managed service principal secret. An adversary may gain unauthorized access to {target.Name} due to compromise of Service Principal Secret . falseEAn adversary can abuse poorly managed authentication/access policies. An adversary may gain unauthorized access to {target.Name} due to compromise of secret/certificate used to authenticate to {target.Name} .target is 'SE.DS.TMCore.AzureKeyVault' and target.ae94fa17-596d-476e-a283-0afc166dcf26 is 'Select' TH185UserThreatDescriptionfalseAn adversary can abuse poorly managed authentication/access policies. An adversary may gain unauthorized access to {target.Name} due to compromise of secret/certificate used to authenticate to {target.Name} 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse managed identities for Azure resources and details can be found here at <a href="https://aka.ms/tmt-th183 ">https://aka.ms/tmt-th183 </a>. If managed identities is not supported , use Service/User Principal and Certificate. If none of the above options are feasible, please ensure secure management and storage of Azure Key Vault Service/User Principal secret . It is recommended to rotate service/user principal secret regularly, in accordance with organizational policies.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can abuse poorly managed authentication/access policies. An adversary may gain unauthorized access to {target.Name} due to compromise of secret/certificate used to authenticate to {target.Name} . falseDAn adversary may attempt to delete key vault or key vault object causing business disruption. target is 'SE.DS.TMCore.AzureKeyVault'TH186UserThreatDescriptionfalseAn adversary may attempt to delete key vault or key vault object causing business disruption. 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseKey Vault's soft delete feature allows recovery of the deleted vaults and vault objects, known as soft-delete . Soft deleted resources are retained for a set period of time, 90 days. Refer : <a href="https://aka.ms/tmt-th186 ">https://aka.ms/tmt-th186 </a>22222222-2222-2222-2222-2222222222222PriorityfalseLow22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may attempt to delete key vault or key vault object causing business disruption. falseEAn adversary may gain unauthorized access to manage {target.Name} due to weak authorization rulestarget is 'SE.P.TMCore.ALA'TH187UserThreatDescriptionfalseAn adversary may gain unauthorized access to manage {target.Name} due to weak authorization rules22222222-2222-2222-2222-2222222222220PossibleMitigationsfalse + Access to the Azure Logic Apps management plane should be restricted by assigning the appropriate Role-Based Access Control (RBAC) roles to only those needing the privileges. Follow the principle of least privilege.  + Refer : <a href="https://aka.ms/tmt-th187 ">https://aka.ms/tmt-th187 </a> + 22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to manage {target.Name} due to weak authorization rulesfalseEAn adversary may gain unauthorized access to {target.Name} workflow run history data due to weak network configurationtarget is 'SE.P.TMCore.ALA' and not target.0b0ab9bc-a582-4509-a6c4-8d56de65661e is 'Specific IP'TH188UserThreatDescriptionfalseAn adversary may gain unauthorized access to {target.Name} workflow run history data due to weak network configuration22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseLimit Azure Logic Apps data plane access to workflow run history data by only allowing requests from specific IP address ranges. Grant access only as necessary, adhering to the principle of least privilege. Refer : <a href="https://aka.ms/tmt-th188 ">https://aka.ms/tmt-th188 </a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to {target.Name} workflow run history data due to weak network configurationfalseEAn adversary may gain unauthorized access to {target.Name} triggers/actions inputs or outputs by workflow run history datatarget is 'SE.P.TMCore.ALA' and not target.b1724997-7ae6-4b30-a001-9c5b42d9d1d1 is 'No'TH189UserThreatDescriptionfalseAn adversary may gain unauthorized access to {target.Name} triggers/actions inputs or outputs by workflow run history data22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnable secure inputs or outputs on the trigger or action to prevent sensitive data from being logged into run history. Refer : <a href="https://aka.ms/tmt-th189 ">https://aka.ms/tmt-th189 </a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to {target.Name} triggers/actions inputs or outputs by workflow run history datafalseEAn adversary may gain unauthorized access to {target.Name} trigger due to weak controls on the triggertarget is 'SE.P.TMCore.ALA' and not target.5afb52dc-dffb-4319-aa22-523f78ee3845 is 'No'TH190UserThreatDescriptionfalseAn adversary may gain unauthorized access to {target.Name} trigger due to weak controls on the trigger22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseLimit access to invoke the trigger by Logic Apps Shared Access Signatures ( SAS) keys and callback URLs. Refer : <a href="https://aka.ms/tmt-th190 ">https://aka.ms/tmt-th190</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to {target.Name} trigger due to weak controls on the triggerfalseEAn adversary may gain unauthorized access to trigger {target.Name} workflows due to weak network configuration  target is 'SE.P.TMCore.ALA' and ( target.d488c23c-1667-45a1-994b-f56f2655727b is 'Allow any IP inbound' or target.d488c23c-1667-45a1-994b-f56f2655727b is 'Select')TH191UserThreatDescriptionfalseAn adversary may gain unauthorized access to trigger {target.Name} workflows due to weak network configuration 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrict calls to Azure Logic Apps on a network level, only permitting specific clients (belonging to a set of IP addresses or IP address range) to trigger workflows. Refer : <a href="https://aka.ms/tmt-th191 ">https://aka.ms/tmt-th191</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseDesign22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to trigger {target.Name} workflows due to weak network configuration falseIAn adversary may read sensitive workflow parameters due to improper handling and management of workflow parameters and inputs target is 'SE.P.TMCore.ALA'TH192UserThreatDescriptionfalseAn adversary may read sensitive workflow parameters due to improper handling and management of workflow parameters and inputs 22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseDefine resource parameters and leverage Azure Logic Apps workflow definition language, such as the @parameters() operation, to access resource parameter values at runtime. Use the securestring parameter type to better protect when and how parameter values can be accessed. For sensitive parameters (e.g. secrets), use Azure Key Vault to store and retrieve secrets when needed. Refer : <a href="https://aka.ms/tmt-th192 ">https://aka.ms/tmt-th192</a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may read sensitive workflow parameters due to improper handling and management of workflow parameters and inputs falseEAn adversary can abuse poorly managed credentials or secrets used to access other resources in AAD tenantstarget is 'SE.P.TMCore.ALA'TH193UserThreatDescriptionfalseAn adversary can abuse poorly managed credentials or secrets used to access other resources in AAD tenants22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseUse managed identities , if possible , for your logic apps to connect to different resources managed in AAD tenant.  Refer : <a href="https://aka.ms/tmt-th193 ">https://aka.ms/tmt-th193</a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can abuse poorly managed credentials or secrets used to access other resources in AAD tenants.falseEAn adversary may gain unauthorized access to run any action on {target.Name} due to weak authorization rulestarget is 'SE.P.TMCore.ADE'TH194UserThreatDescriptionfalseAn adversary may gain unauthorized access to run any action on {target.Name} due to weak authorization rules22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure access to run any action on a Kusto resource is restricted by assigning the appropriate Role-Based Access Control (RBAC) roles to only those needing the privileges. Follow the principle of least privilege. Security roles define which security principals (users and applications) can have permissions to operate on a secured resource (such as a database or a table), and what operations are permitted. Refer : 1) <a href="https://aka.ms/tmt-th194 ">https://aka.ms/tmt-th194 </a> 2)<a href="https://aka.ms/tmt-th194a ">https://aka.ms/tmt-th194a </a>22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary may gain unauthorized access to run any action on {target.Name} due to weak authorization rulesfalseISecret information should not be logged in {target.Name}target is 'SE.P.TMCore.ADE'TH195UserThreatDescriptionfalseSecret information should not be logged in {target.Name}22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnsure any secret information like passwords , SAS Tokens , refresh tokens etc are not logged in Azure Data Explorer.22222222-2222-2222-2222-2222222222222PriorityfalseHigh22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221Secret information should not be logged in {target.Name}falseISensitive information might get disclosed while querying {target.Name}target is 'SE.P.TMCore.ADE'TH196UserThreatDescriptionfalseSensitive information might get disclosed while querying {target.Name}22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseRestrictedViewAccess policy can be enabled on tables in database which contain sensitive information and only principals with "UnrestrictedViewer" role in the database can query that data.Refer : <a href="https://aka.ms/tmt-th196 ">https://aka.ms/tmt-th196 </a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221Sensitive information might get disclosed while querying {target.Name}falseEAn adversary can run malicious Kusto queries on {target.Name} if user provided input is used in non-parameterised queriestarget is 'SE.P.TMCore.ADE'TH197UserThreatDescriptionfalseAn adversary can run malicious Kusto queries on {target.Name} if user provided input is used in non-parameterised queries22222222-2222-2222-2222-2222222222220PossibleMitigationsfalsePlease use query parameters to protect against injection attacks.Refer : <a href="https://aka.ms/tmt-th197 ">https://aka.ms/tmt-th197 </a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can run malicious Kusto queries on {target.Name} if user provided input is used in non-parameterised queriesfalseIAn adversary can gain access to unencrypted sensitive data stored in {target.Name} clustertarget is 'SE.P.TMCore.ADE'TH198UserThreatDescriptionfalseAn adversary can gain access to unencrypted sensitive data stored in {target.Name} cluster22222222-2222-2222-2222-2222222222220PossibleMitigationsfalseEnabling encryption at rest on your cluster provides data protection for stored data (at rest). Refer : <a href="https://aka.ms/tmt-th198 ">https://aka.ms/tmt-th198 </a>22222222-2222-2222-2222-2222222222222PriorityfalseMedium22222222-2222-2222-2222-2222222222221SDLPhasefalseImplementation22222222-2222-2222-2222-2222222222221An adversary can gain access to unencrypted sensitive data stored in {target.Name} cluster \ No newline at end of file From 2c2461a7fa383f664bb75546f03a2c6087f3819d Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 09:22:09 +1000 Subject: [PATCH 06/25] add AkashAi7 as a contributor for content (#2293) * update README.md * update .all-contributorsrc * update website/src/pages/contributors.astro --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + website/src/pages/contributors.astro | 1 + 3 files changed, 11 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index ae703d31..bf2e668c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -3560,6 +3560,15 @@ "contributions": [ "bug" ] + }, + { + "login": "AkashAi7", + "name": "Akash Dwivedi", + "avatar_url": "https://avatars.githubusercontent.com/u/46550108?v=4", + "profile": "https://github.com/AkashAi7", + "contributions": [ + "content" + ] } ] } diff --git a/README.md b/README.md index fe3e19fa..fde29411 100644 --- a/README.md +++ b/README.md @@ -540,6 +540,7 @@ Thanks goes to these wonderful people ([emoji key](./CONTRIBUTING.md#contributor
Lovy Jain

kimtth
+
Akash Dwivedi
diff --git a/website/src/pages/contributors.astro b/website/src/pages/contributors.astro index e4bface5..d4c49f62 100644 --- a/website/src/pages/contributors.astro +++ b/website/src/pages/contributors.astro @@ -495,6 +495,7 @@ import PageHeader from '../components/PageHeader.astro';
Lovy Jain

kimtth
+
Akash Dwivedi
From 733c8cd0095660a98cdaa5be910eb91011f8b75d Mon Sep 17 00:00:00 2001 From: Aaron Powell Date: Thu, 16 Jul 2026 09:03:29 +1000 Subject: [PATCH 07/25] Fixing some stuff with learning hub and app automations (#2291) --- website/astro.config.mjs | 1 + .../using-automations-in-copilot-app.md | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/website/astro.config.mjs b/website/astro.config.mjs index 1df5c300..253dace8 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -76,6 +76,7 @@ export default defineConfig({ items: [ "learning-hub/github-copilot-app", "learning-hub/working-with-canvas-extensions", + "learning-hub/using-automations-in-copilot-app", "learning-hub/what-are-agents-skills-instructions", "learning-hub/agents-and-subagents", "learning-hub/understanding-copilot-context", diff --git a/website/src/content/docs/learning-hub/using-automations-in-copilot-app.md b/website/src/content/docs/learning-hub/using-automations-in-copilot-app.md index 86dfea88..c5918e1b 100644 --- a/website/src/content/docs/learning-hub/using-automations-in-copilot-app.md +++ b/website/src/content/docs/learning-hub/using-automations-in-copilot-app.md @@ -1,10 +1,10 @@ --- -title: 'Using Automations in the GitHub Copilot app' -description: 'A practical guide to getting started with Copilot app automations using templates, iterative refinement, and real-world examples.' +title: "Using Automations in the GitHub Copilot app" +description: "A practical guide to getting started with Copilot app automations using templates, iterative refinement, and real-world examples." authors: - GitHub Copilot Learning Hub Team lastUpdated: 2026-06-17 -estimatedReadingTime: '10 minutes' +estimatedReadingTime: "10 minutes" tags: - copilot-app - automations @@ -61,13 +61,15 @@ If your first version is only 70% right, that is normal. The fastest path is to Here is a real in-app automation used on the `github/awesome-copilot` repository: -| Field | Value | -|---|---| -| **Name** | Awesome Copilot daily PR summary | -| **Interval** | Daily at 09:00 | -| **Mode** | Autopilot | +| Field | Value | +| ---------------- | --------------------------------------------------------------------------------------------------------- | +| **Name** | Awesome Copilot daily PR summary | +| **Interval** | Daily at 09:00 | +| **Mode** | Autopilot | | **What it does** | Pulls open PRs via `gh api`, filters to updates in the last 24 hours, and returns a concise summary table | +[![Create Automation](https://img.shields.io/badge/automation-daily_pr_summary-blue?logo=github-copilot)](ghapp://automations/new?name=Awesome%20Copilot%20daily%20PR%20summary&trigger=daily&time=09%3A00&prompt=Pulls%20open%20PRs%20via%20gh%20api%2C%20filters%20to%20updates%20in%20the%20last%2024%20hours%2C%20and%20returns%20a%20concise%20summary%20table) + Why this works well: - It is narrowly scoped (one repo, one reporting goal). From e4a1f57fd9d8c22d2a345d498fe6fde306c6456e Mon Sep 17 00:00:00 2001 From: Willie Yao Date: Thu, 16 Jul 2026 07:06:49 +0800 Subject: [PATCH 08/25] feat: add convert-excel-to-md, convert-pdf-to-md, and convert-word-to-md skills (#2294) * feat: add convert-excel-to-md, convert-pdf-to-md, and convert-word-to-md skills Add three new agent skills that convert common document formats to Markdown using bundled Python scripts powered by MarkItDown: - convert-excel-to-md: Converts .xlsx workbooks to Markdown with per-sheet tables and embedded image extraction via a bundled Python script. - convert-pdf-to-md: Converts .pdf documents to Markdown with text/table extraction and embedded image extraction via PyMuPDF. - convert-word-to-md: Converts .docx documents to Markdown with proper image extraction replacing MarkItDown's base64 placeholders. Each skill includes: - SKILL.md with detailed usage instructions, output structure docs, and a troubleshooting table - scripts/ with the conversion Python script and requirements.txt - references/setup.md with environment setup instructions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove Markdown image syntax from convert-word-to-md SKILL.md The CI valid-refs linter flagged the literal Markdown image syntax containing a data URI as an invalid file reference. Replaced it with a plain text description of the placeholder format. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: update pip install command to use scripts/requirements.txt for setup * fix: clarify installation instructions for requirements-file in setup documentation * fix: correct indentation in image extraction function * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * feat: add comprehensive documentation and setup instructions for convert-to-md skills * fix: add trailing slashes to skill paths in plugin.json * fix: reorder skills in plugin.json for consistency * fix: update plugin.json and README.md for clarity and consistency * feat: add convert-to-md plugin and update related documentation * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: enhance conversion skills to handle mixed file types and improve error handling --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .github/plugin/marketplace.json | 6 + docs/README.plugins.md | 1 + docs/README.skills.md | 3 + .../convert-to-md/.github/plugin/plugin.json | 24 ++ plugins/convert-to-md/README.md | 47 +++ skills/convert-excel-to-md/SKILL.md | 131 +++++++ .../convert-excel-to-md/references/setup.md | 73 ++++ .../scripts/convert_excel_to_md.py | 354 ++++++++++++++++++ .../scripts/requirements.txt | 1 + skills/convert-pdf-to-md/SKILL.md | 130 +++++++ skills/convert-pdf-to-md/references/setup.md | 71 ++++ .../scripts/convert_pdf_to_md.py | 321 ++++++++++++++++ .../scripts/requirements.txt | 2 + skills/convert-word-to-md/SKILL.md | 129 +++++++ skills/convert-word-to-md/references/setup.md | 66 ++++ .../scripts/convert_word_to_md.py | 301 +++++++++++++++ .../scripts/requirements.txt | 1 + 17 files changed, 1661 insertions(+) create mode 100644 plugins/convert-to-md/.github/plugin/plugin.json create mode 100644 plugins/convert-to-md/README.md create mode 100644 skills/convert-excel-to-md/SKILL.md create mode 100644 skills/convert-excel-to-md/references/setup.md create mode 100644 skills/convert-excel-to-md/scripts/convert_excel_to_md.py create mode 100644 skills/convert-excel-to-md/scripts/requirements.txt create mode 100644 skills/convert-pdf-to-md/SKILL.md create mode 100644 skills/convert-pdf-to-md/references/setup.md create mode 100644 skills/convert-pdf-to-md/scripts/convert_pdf_to_md.py create mode 100644 skills/convert-pdf-to-md/scripts/requirements.txt create mode 100644 skills/convert-word-to-md/SKILL.md create mode 100644 skills/convert-word-to-md/references/setup.md create mode 100644 skills/convert-word-to-md/scripts/convert_word_to_md.py create mode 100644 skills/convert-word-to-md/scripts/requirements.txt diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index d3fba171..e91a7607 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -253,6 +253,12 @@ "description": "Coding agents hallucinate APIs. ContextMatic gives them curated, versioned API and SDK docs. Ask your agent to \"integrate the payments API\" and it guesses — falling back on outdated training data and generic patterns that don't match your actual SDK. ContextMatic solves this by giving the agent deterministic, version-aware, SDK-native context at the exact moment it's needed.", "version": "0.1.0" }, + { + "name": "convert-to-md", + "source": "plugins/convert-to-md", + "description": "A collection of Copilot skills that convert common document formats into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Just tell Copilot what you need — the right skill is invoked automatically and the conversion happens behind the scenes.", + "version": "1.0.1" + }, { "name": "copilot-goal-skill", "description": "Goal-driven task orchestration with independent verification. Interviews the user to define a clear goal, then loops between a Builder subagent (does the work) and an Inspector subagent (judges the result with fresh context). The Inspector never trusts the Builder. Output is auditable in git commits from each subagent actions. Use when the user says \"achieve this goal\", \"make this work\", \"implement until done\", or wants verified autonomous task completion with independent quality review.", diff --git a/docs/README.plugins.md b/docs/README.plugins.md index ca23476d..bff4a4b4 100644 --- a/docs/README.plugins.md +++ b/docs/README.plugins.md @@ -40,6 +40,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-plugins) for guidelines on how t | [cms-development](../plugins/cms-development/README.md) | Skills for CMS development across themes, plugins, admin tooling, media workflows, markdown rendering, and static export pipelines. | 3 items | cms, content-management-system, wordpress, shopify, drupal, theme, plugin, media, static-site | | [context-engineering](../plugins/context-engineering/README.md) | Tools and techniques for maximizing GitHub Copilot effectiveness through better context management. Includes guidelines for structuring code, an agent for planning multi-file changes, and prompts for context-aware development. | 4 items | context, productivity, refactoring, best-practices, architecture | | [context-matic](../plugins/context-matic/README.md) | Coding agents hallucinate APIs. ContextMatic gives them curated, versioned API and SDK docs. Ask your agent to "integrate the payments API" and it guesses — falling back on outdated training data and generic patterns that don't match your actual SDK. ContextMatic solves this by giving the agent deterministic, version-aware, SDK-native context at the exact moment it's needed. | 2 items | api-context, api-integration, mcp, sdk, apimatic, third-party-apis, sdks | +| [convert-to-md](../plugins/convert-to-md/README.md) | A collection of Copilot skills that convert common document formats into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Just tell Copilot what you need — the right skill is invoked automatically and the conversion happens behind the scenes. | 3 items | skills, configuration, copilot, convert-word-to-md, convert-excel-to-md, convert-pdf-to-md | | [copilot-sdk](../plugins/copilot-sdk/README.md) | Build applications with the GitHub Copilot SDK across multiple programming languages. Includes comprehensive instructions for C#, Go, Node.js/TypeScript, and Python to help you create AI-powered applications. | 1 items | copilot-sdk, sdk, csharp, go, nodejs, typescript, python, ai, github-copilot | | [csharp-dotnet-development](../plugins/csharp-dotnet-development/README.md) | Essential prompts, instructions, and chat modes for C# and .NET development including testing, documentation, and best practices. | 9 items | csharp, dotnet, aspnet, testing | | [database-data-management](../plugins/database-data-management/README.md) | Database administration, SQL optimization, and data management tools for PostgreSQL, SQL Server, and general database development best practices. | 6 items | database, sql, postgresql, sql-server, dba, optimization, queries, data-management | diff --git a/docs/README.skills.md b/docs/README.skills.md index 63ddc1e5..fb94c86e 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -100,7 +100,10 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [context-map](../skills/context-map/SKILL.md)
`gh skills install github/awesome-copilot context-map` | Generate a map of all files relevant to a task before making changes | None | | [conventional-branch](../skills/conventional-branch/SKILL.md)
`gh skills install github/awesome-copilot conventional-branch` | Create Git branches following the Conventional Branch specification (feature/, bugfix/, hotfix/, release/, chore/). Use when creating a new branch, naming a branch, or checking whether a branch name complies with the spec. | None | | [conventional-commit](../skills/conventional-commit/SKILL.md)
`gh skills install github/awesome-copilot conventional-commit` | Prompt and workflow for generating conventional commit messages using a structured XML format. Guides users to create standardized, descriptive commit messages in line with the Conventional Commits specification, including instructions, examples, and validation. | None | +| [convert-excel-to-md](../skills/convert-excel-to-md/SKILL.md)
`gh skills install github/awesome-copilot convert-excel-to-md` | Converts Excel (.xlsx) workbooks into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Use this skill whenever the user shares, references, or asks about a .xlsx file — even if they don't say "convert" or "markdown" explicitly. This includes requests to "read", "summarize", "review", "extract data from", "compare", "chart", or "analyze" a spreadsheet, workbook, budget, data export, or tracker. Always run the bundled conversion script to produce Markdown first; do not attempt to parse .xlsx content directly or write ad-hoc extraction code. Also use this skill for batch requests involving a whole folder of Excel workbooks. IMPORTANT: When the user references a folder or set of documents containing multiple file types (.pdf, .docx, .xlsx), invoke ALL three sibling skills — convert-pdf-to-md, convert-word-to-md, and convert-excel-to-md — so no file type is silently skipped. | `references/setup.md`
`scripts/convert_excel_to_md.py`
`scripts/requirements.txt` | +| [convert-pdf-to-md](../skills/convert-pdf-to-md/SKILL.md)
`gh skills install github/awesome-copilot convert-pdf-to-md` | Converts PDF (.pdf) documents into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Use this skill whenever the user shares, references, or asks about a .pdf file — even if they don't say "convert" or "markdown" explicitly. This includes requests to "read", "summarize", "review", "extract data from", "compare", or "analyze" a PDF report, paper, invoice, form, contract, or scanned document. Always run the bundled conversion script to produce Markdown first; do not attempt to parse PDF content directly or write ad-hoc extraction code. Also use this skill for batch requests involving a whole folder of PDF documents. IMPORTANT: When the user references a folder or set of documents containing multiple file types (.pdf, .docx, .xlsx), invoke ALL three sibling skills — convert-pdf-to-md, convert-word-to-md, and convert-excel-to-md — so no file type is silently skipped. | `references/setup.md`
`scripts/convert_pdf_to_md.py`
`scripts/requirements.txt` | | [convert-plaintext-to-md](../skills/convert-plaintext-to-md/SKILL.md)
`gh skills install github/awesome-copilot convert-plaintext-to-md` | Convert a text-based document to markdown following instructions from prompt, or if a documented option is passed, follow the instructions for that option. | None | +| [convert-word-to-md](../skills/convert-word-to-md/SKILL.md)
`gh skills install github/awesome-copilot convert-word-to-md` | Converts Word (.docx) documents into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Use this skill whenever the user shares, references, or asks about a .docx file — even if they don't say "convert" or "markdown" explicitly. This includes requests to "read", "summarize", "review", "extract data from", "compare", or "analyze" a Word document, resume, report, contract, or proposal. Always run the bundled conversion script to produce Markdown first; do not attempt to parse .docx content directly or write ad-hoc conversion code. Also use this skill for batch requests involving a whole folder of Word documents. IMPORTANT: When the user references a folder or set of documents containing multiple file types (.pdf, .docx, .xlsx), invoke ALL three sibling skills — convert-pdf-to-md, convert-word-to-md, and convert-excel-to-md — so no file type is silently skipped. | `references/setup.md`
`scripts/convert_word_to_md.py`
`scripts/requirements.txt` | | [copilot-cli-quickstart](../skills/copilot-cli-quickstart/SKILL.md)
`gh skills install github/awesome-copilot copilot-cli-quickstart` | Use this skill when someone wants to learn GitHub Copilot CLI from scratch. Offers interactive step-by-step tutorials with separate Developer and Non-Developer tracks, plus on-demand Q&A. Just say "start tutorial" or ask a question! Note: This skill targets GitHub Copilot CLI specifically and uses CLI-specific tools (ask_user, sql, fetch_copilot_cli_documentation). | None | | [copilot-instructions-blueprint-generator](../skills/copilot-instructions-blueprint-generator/SKILL.md)
`gh skills install github/awesome-copilot copilot-instructions-blueprint-generator` | Technology-agnostic blueprint generator for creating comprehensive copilot-instructions.md files that guide GitHub Copilot to produce code consistent with project standards, architecture patterns, and exact technology versions by analyzing existing codebase patterns and avoiding assumptions. | None | | [copilot-pr-autopilot](../skills/copilot-pr-autopilot/SKILL.md)
`gh skills install github/awesome-copilot copilot-pr-autopilot` | Copilot left 14 review comments on your PR — half are nits. Hours of fix → reply → resolve → re-request, and each round lands MORE comments. This skill runs loop engineering: auto-triggers Copilot Code Review via GraphQL (no @copilot mention), triages every open thread (Copilot, humans, advanced-security) with a fix / decline / escalate rubric, dispatches parallel fix sub-agents that obey the repo build/test/lint conventions, commits per iteration, replies+resolves citing the pushed SHA, then re-triggers until HEAD is reviewed with zero threads awaiting the agent's reply (remaining open threads are explicit hand-offs to the human — escalated declines, design tradeoffs). You merge a clean PR; the bot runs it. Trigger phrases: "address copilot comments", "run a copilot review loop", "fix this PR", "iterate on copilot feedback". Repo-agnostic, gh CLI + PowerShell. Full autopilot needs repo Triage/Write; external PR authors get single-iteration mode plus manual re-trigger (UI 🔄 or substantive-commit push). | `references/01-request-review.md`
`references/02-wait.md`
`references/03-list-threads.md`
`references/04-triage.md`
`references/05-fix.md`
`references/06-build-test.md`
`references/07-commit-push.md`
`references/08-reply-resolve.md`
`references/09-convergence.md`
`references/10-cleanup.md`
`references/api-quirks.md`
`references/orchestration.md`
`scripts/01-request-review.ps1`
`scripts/02-check-review-status.ps1`
`scripts/03-list-open-threads.ps1`
`scripts/08-reply-and-resolve.ps1`
`scripts/09-review-round.ps1`
`scripts/10-cleanup-outdated.ps1`
`scripts/_lib.ps1`
`templates` | diff --git a/plugins/convert-to-md/.github/plugin/plugin.json b/plugins/convert-to-md/.github/plugin/plugin.json new file mode 100644 index 00000000..91fd9b51 --- /dev/null +++ b/plugins/convert-to-md/.github/plugin/plugin.json @@ -0,0 +1,24 @@ +{ + "name": "convert-to-md", + "description": "A collection of Copilot skills that convert common document formats into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Just tell Copilot what you need — the right skill is invoked automatically and the conversion happens behind the scenes.", + "version": "1.0.1", + "keywords": [ + "skills", + "configuration", + "copilot", + "convert-word-to-md", + "convert-excel-to-md", + "convert-pdf-to-md" + ], + "author": { + "name": "Willie Yao", + "url": "https://github.com/1YaoWei0" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "skills": [ + "./skills/convert-excel-to-md/", + "./skills/convert-pdf-to-md/", + "./skills/convert-word-to-md/" + ] +} diff --git a/plugins/convert-to-md/README.md b/plugins/convert-to-md/README.md new file mode 100644 index 00000000..5e075419 --- /dev/null +++ b/plugins/convert-to-md/README.md @@ -0,0 +1,47 @@ +# Convert to Markdown Plugin + +A collection of Copilot skills that convert common document formats into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Just tell Copilot what you need — the right skill is invoked automatically and the conversion happens behind the scenes. + +## Installation + +```bash +copilot plugin install convert-to-md@awesome-copilot +``` + +## What's Included + +This plugin includes Word, Excel, and PDF conversion skills, detailed below. + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## Skills + +### convert-word-to-md + +Converts Word (`.docx`) documents to Markdown. Use it any time you want to read, summarize, review, compare, or extract information from a `.docx` file — even if you don't say "convert" explicitly. + +> "Summarize this Word document." +> "Extract all the action items from report.docx." +> "Compare these two contracts." + +### convert-excel-to-md + +Converts Excel (`.xlsx`) workbooks to Markdown, rendering each sheet as a table. Use it any time you want to analyze, query, or summarize data in a spreadsheet — single file or a whole folder at once. + +> "What are the top 5 rows by revenue in this spreadsheet?" +> "Summarize all the worksheets in this workbook." +> "Process every Excel file in this folder." + +### convert-pdf-to-md + +Converts PDF (`.pdf`) documents to Markdown, extracting both text and embedded images. Use it any time you want to read, summarize, or pull data from a PDF report, invoice, paper, or form. + +> "Summarize this PDF." +> "Extract all the dates mentioned in this contract." +> "Process all the PDFs in this folder." + +## License + +MIT diff --git a/skills/convert-excel-to-md/SKILL.md b/skills/convert-excel-to-md/SKILL.md new file mode 100644 index 00000000..00d465f4 --- /dev/null +++ b/skills/convert-excel-to-md/SKILL.md @@ -0,0 +1,131 @@ +--- +name: convert-excel-to-md +description: 'Converts Excel (.xlsx) workbooks into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Use this skill whenever the user shares, references, or asks about a .xlsx file — even if they don''t say "convert" or "markdown" explicitly. This includes requests to "read", "summarize", "review", "extract data from", "compare", "chart", or "analyze" a spreadsheet, workbook, budget, data export, or tracker. Always run the bundled conversion script to produce Markdown first; do not attempt to parse .xlsx content directly or write ad-hoc extraction code. Also use this skill for batch requests involving a whole folder of Excel workbooks. IMPORTANT: When the user references a folder or set of documents containing multiple file types (.pdf, .docx, .xlsx), invoke ALL three sibling skills — convert-pdf-to-md, convert-word-to-md, and convert-excel-to-md — so no file type is silently skipped.' +--- + +# Convert Excel to Markdown + +## When to use this skill + +Trigger this skill any time there is a `.xlsx` file that needs to be +understood or processed — for example, a user attaches a spreadsheet and +asks questions about it, wants a summary of the data, wants specific rows or +values pulled out, or wants multiple workbooks in a folder processed +together. Excel's native `.xlsx` format is a zipped XML bundle that is not +reliably readable as plain text, so always convert it to Markdown first +using the script in this skill rather than trying to open or parse the file +directly. + +This skill only supports `.xlsx`. If asked to convert a legacy `.xls` file, +tell the user it isn't supported and ask them to re-save it as `.xlsx` +(Excel: File > Save As > Excel Workbook (.xlsx)) first. + +**Mixed file types:** When the user references a folder or set of documents +containing multiple supported file types (`.pdf`, `.docx`, `.xlsx`), this +skill handles only `.xlsx` files. The agent MUST also invoke the sibling +skills in parallel: +- `convert-pdf-to-md` for any `.pdf` files +- `convert-word-to-md` for any `.docx` files + +Never process a folder and silently skip a supported file type. All three +skills must be invoked together when mixed types are present. + +## Setup (once per environment) + +Before the first conversion in a given environment, follow +[`references/setup.md`](references/setup.md) step by step to ensure Python, +pip, and the `markitdown` package are installed. Do this proactively rather +than guessing whether the environment is ready — the script itself will +also fail with a clear pointer back to that file if `markitdown` turns out +to be missing, so it's safe to just try the conversion first if you're +reasonably confident setup was already done. + +## Usage + +The conversion script lives at `scripts/convert_excel_to_md.py`. + +**Output structure:** MarkItDown's XLSX converter renders each sheet as its +own `## ` Markdown table — it has no support for embedded images +at all. This script separately extracts real embedded images (raster +pictures, not charts) and maps them to the sheet they belong to, writing a +self-contained folder per document: + +``` +/ + img/ + sheet001__img001. + sheet002__img001. + ... + .md (each sheet's images appear right after its table, + under a "#### Images in this sheet" heading) +``` + +This is per-sheet placement, not exact cell position — the finest +granularity MarkItDown's stable output anchors (the `## ` +headings) allow. If a workbook has no embedded images, no `img/` folder or +image sections are created. Native Excel **charts** are not extracted as +images (only actual embedded pictures are — charts would need to be +rendered by Excel/LibreOffice, which this lightweight skill does not do). + +**Single file:** + +```powershell +python scripts\convert_excel_to_md.py "C:\path\to\workbook.xlsx" +``` + +This creates a `workbook\` folder next to the source file (containing +`workbook.md` and, if present, `workbook\img\`). To control the destination +folder explicitly: + +```powershell +python scripts\convert_excel_to_md.py "C:\path\to\workbook.xlsx" -o "C:\path\to\output_folder" +``` + +**A folder of workbooks (batch mode):** + +```powershell +python scripts\convert_excel_to_md.py "C:\path\to\folder" +``` + +Add `--recursive` to also include subfolders: + +```powershell +python scripts\convert_excel_to_md.py "C:\path\to\folder" --recursive +``` + +Each `.xlsx` found gets its own `\` output folder next to it by +default. Pass `-o "C:\path\to\output_parent"` to collect all the generated +`\` folders under a separate parent directory instead (subfolder +structure is preserved when combined with `--recursive`). + +After conversion, read the resulting `.md` file(s) to perform the actual +analysis the user asked for — the script's job is only to produce accurate +Markdown (and images), not to interpret the content. + +## Deciding where output goes + +**Default — always output next to the source file.** The `/` folder +is created in the same directory as the source `.xlsx`. This is the required +default for every case. Do NOT override it unless the user explicitly asks +for a different location. + +**Only use `-o` when** the user explicitly provides an output path (e.g., +"save the output to `C:\output`", "put the results in `D:\work`"). Do NOT +pass `-o` based on the agent's current working directory, the session state +folder, or any implied location. + +**If the source file path cannot be fully resolved** — for example, the +user provides only a filename with no directory, or the path is ambiguous — +use `ask_user` to confirm the full absolute path before running the +conversion. Never guess or assume the directory. + +## Troubleshooting + +| Symptom | Likely cause | Fix | +|---|---|---| +| `ModuleNotFoundError: No module named 'markitdown'` / exit code 2 | MarkItDown not installed | Follow `references/setup.md` | +| `ERROR: Unsupported file type '.xls'` / exit code 3 | Legacy `.xls`, not `.xlsx` | Ask the user to re-save as `.xlsx` | +| `ERROR: Input path not found` / exit code 3 | Wrong path, or file moved | Confirm the correct path with the user | +| `FAILED -> ...` in batch output | That specific file is corrupt, password-protected, or otherwise unreadable | Report which file(s) failed; other files in the batch still succeed | +| `NOTE: skipped N non-.xlsx file(s)` | Folder contains non-Excel files | Expected — those files are intentionally ignored | +| A sheet's charts don't appear as images | Charts are chart objects, not embedded pictures — this skill only extracts real embedded raster images | Expected; mention this limitation if the user specifically needs chart images | diff --git a/skills/convert-excel-to-md/references/setup.md b/skills/convert-excel-to-md/references/setup.md new file mode 100644 index 00000000..f3e49e15 --- /dev/null +++ b/skills/convert-excel-to-md/references/setup.md @@ -0,0 +1,73 @@ +# Environment Setup for convert-excel-to-md + +Follow these steps exactly, in order, before running `scripts/convert_excel_to_md.py` +for the first time in a given environment. Don't skip steps or improvise +alternatives — they're written to be deterministic and safe to re-run. + +## 1. Check Python is available (3.10+) + +```powershell +python --version +``` + +- If this fails (command not found), install Python 3.10 or newer: + - Windows: `winget install --id Python.Python.3.12 -e` + - macOS: `brew install python@3.12` + - Linux (Debian/Ubuntu): `sudo apt-get update && sudo apt-get install -y python3 python3-pip python-is-python3` +- If the reported version is older than 3.10, install a newer Python using + the same command above (MarkItDown requires 3.10+). + +## 2. Check pip is available + +```powershell +python -m pip --version +``` + +- If this fails, bootstrap pip: + +```powershell +python -m ensurepip --upgrade +``` + +## 3. Install MarkItDown with Excel (.xlsx) support + +Use the `scripts/requirements.txt` file bundled with this skill to install a pinned, +known-good version of the dependency: + +```powershell +python -m pip install -r scripts/requirements.txt +``` + +This pulls in `markitdown[xlsx]` (MarkItDown's XLSX table conversion +dependencies, which include `pandas` and `openpyxl`). No extra package is needed for image extraction — this +skill's script reads embedded images directly from the `.xlsx` zip +structure using Python's built-in `zipfile` and `xml` modules. + +## 4. Verify the install + +```powershell +python -c "from markitdown import MarkItDown; print('markitdown OK')" +``` + +Expect to see `markitdown OK` printed with no errors. If you see +`ModuleNotFoundError: No module named 'markitdown'`, repeat step 3 — pip may +be installing into a different Python environment than the one being +invoked (check `python -m pip --version` shows the same path as `python +--version`'s interpreter). + +## Notes + +- This setup only needs to be done once per environment/virtual environment, + not once per conversion. +- `convert_excel_to_md.py` itself also checks for `markitdown` at startup + and prints a pointer back to this file if it's missing, so re-running + setup is safe and idempotent. +- Only `.xlsx` is supported by this skill. Legacy binary `.xls` files are + out of scope (a completely different, harder-to-parse file format) — ask + the user to re-save the file as `.xlsx` (Excel: File > Save As > Excel + Workbook (.xlsx)) if one is encountered. +- Chart objects (as opposed to embedded pictures) are not extracted as + images — only raster pictures actually embedded in the workbook's + `xl/media` folder are. Native Excel charts would need to be rendered by + Excel/LibreOffice to become images, which this lightweight skill does not + attempt. diff --git a/skills/convert-excel-to-md/scripts/convert_excel_to_md.py b/skills/convert-excel-to-md/scripts/convert_excel_to_md.py new file mode 100644 index 00000000..6f7b562a --- /dev/null +++ b/skills/convert-excel-to-md/scripts/convert_excel_to_md.py @@ -0,0 +1,354 @@ +#!/usr/bin/env python3 +"""Convert Excel (.xlsx) workbooks to Markdown using Microsoft's MarkItDown, +with embedded images extracted to real files and placed under the correct +sheet (MarkItDown's XLSX converter only extracts sheet data as tables -- it +has no support for embedded images at all). + +Usage: + python convert_excel_to_md.py [-o OUTPUT] [--recursive] + + may be either: + - a path to a single .xlsx file, or + - a path to a directory (batch mode: every .xlsx file directly inside it + is converted; pass --recursive to also descend into subdirectories). + +Output: + For each source .xlsx (named ".xlsx"), a folder is created + containing the Markdown and its images, in this layout: + + / + img/ + Sheet1_img001. + Sheet2_img001. + ... + .md + + MarkItDown renders each sheet as its own "## " section with a + Markdown table. This script independently maps embedded images to the + sheet they belong to (via the .xlsx zip's drawing relationships) and + inserts a "#### Images in this sheet" block right after that sheet's + table, before the next "## " heading. This is per-sheet placement (not + exact cell position), which is the finest granularity MarkItDown's stable + output anchors allow. + + - Single file mode: the "/" folder is created next to the source + file, or at -o/--output (treated as the exact destination folder) if + given. + - Batch/directory mode: a "/" folder is created next to each source + file, or under -o/--output (treated as a parent directory, created if + missing) if given, preserving relative subfolder structure when + --recursive is used. + - If a workbook has no embedded images, no "img/" folder or "Images in + this sheet" sections are created. + +Exit codes: + 0 - all requested conversions succeeded + 1 - one or more conversions failed (partial success in batch mode) + 2 - required dependency ("markitdown") is not installed + 3 - invalid input (path not found, or single-file input is not .xlsx) +""" +import argparse +import posixpath +import re +import shutil +import sys +import zipfile +from pathlib import Path +from xml.etree import ElementTree as ET + +EXIT_OK = 0 +EXIT_CONVERSION_FAILED = 1 +EXIT_MISSING_DEPENDENCY = 2 +EXIT_INVALID_INPUT = 3 + +_REL_NS = "http://schemas.openxmlformats.org/package/2006/relationships" +_MAIN_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main" +_R_NS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" +_A_NS = "http://schemas.openxmlformats.org/drawingml/2006/main" + +# Matches MarkItDown's per-sheet heading, e.g. "## Sheet1" +_SHEET_HEADER_RE = re.compile(r"^## (.+)$", re.MULTILINE) + + +def _import_markitdown(): + """Import MarkItDown, failing with a clear, actionable message if absent.""" + try: + from markitdown import MarkItDown + return MarkItDown + except ImportError: + print( + "ERROR: The 'markitdown' package is not installed.\n" + "See references/setup.md for this skill, or run:\n" + ' pip install "markitdown[xlsx]"', + file=sys.stderr, + ) + sys.exit(EXIT_MISSING_DEPENDENCY) + + +def _normalize_rel_path(base_dir: str, target: str) -> str: + """Resolve a (possibly relative, e.g. '../media/image1.png') relationship + target against the directory containing the part that referenced it.""" + if target.startswith("/"): + return target.lstrip("/") + return posixpath.normpath(posixpath.join(base_dir, target)) + + +def _sheet_name_to_media(xlsx_path: Path): + """Return {sheet_name: [media_zip_path, ...]} in per-sheet document + order, by walking workbook.xml -> worksheet -> drawing -> media + relationships. Returns {} if anything is missing/malformed (falls back + gracefully -- images just won't be extracted for that sheet).""" + try: + with zipfile.ZipFile(xlsx_path) as z: + names = set(z.namelist()) + if "xl/workbook.xml" not in names or "xl/_rels/workbook.xml.rels" not in names: + return {} + workbook_xml = z.read("xl/workbook.xml") + workbook_rels_xml = z.read("xl/_rels/workbook.xml.rels") + + sheet_rid = {} + for sheet_el in ET.fromstring(workbook_xml).iter(f"{{{_MAIN_NS}}}sheet"): + name = sheet_el.get("name") + rid = sheet_el.get(f"{{{_R_NS}}}id") + if name and rid: + sheet_rid[name] = rid + + rid_target = {} + for rel in ET.fromstring(workbook_rels_xml).findall(f"{{{_REL_NS}}}Relationship"): + rid_target[rel.get("Id")] = rel.get("Target") + + result = {} + for sheet_name, rid in sheet_rid.items(): + target = rid_target.get(rid) + if not target: + continue + # workbook.xml.rels targets are typically relative to "xl/", + # but OOXML allows package-absolute targets (leading "/") too. + sheet_path = _normalize_rel_path("xl", target) + if sheet_path not in names or "/" not in sheet_path: + continue + sheet_dir, sheet_file = sheet_path.rsplit("/", 1) + sheet_rels_path = f"{sheet_dir}/_rels/{sheet_file}.rels" + if sheet_rels_path not in names: + continue + + drawing_rid = None + for d in ET.fromstring(z.read(sheet_path)).iter(f"{{{_MAIN_NS}}}drawing"): + drawing_rid = d.get(f"{{{_R_NS}}}id") + break + if not drawing_rid: + continue + + drawing_target = None + for rel in ET.fromstring(z.read(sheet_rels_path)).findall(f"{{{_REL_NS}}}Relationship"): + if rel.get("Id") == drawing_rid: + drawing_target = rel.get("Target") + break + if not drawing_target: + continue + drawing_path = _normalize_rel_path(sheet_dir, drawing_target) + if drawing_path not in names or "/" not in drawing_path: + continue + drawing_dir, drawing_file = drawing_path.rsplit("/", 1) + drawing_rels_path = f"{drawing_dir}/_rels/{drawing_file}.rels" + if drawing_rels_path not in names: + continue + + drawing_rel_map = {} + for rel in ET.fromstring(z.read(drawing_rels_path)).findall(f"{{{_REL_NS}}}Relationship"): + drawing_rel_map[rel.get("Id")] = rel.get("Target") + + media_paths = [] + for blip in ET.fromstring(z.read(drawing_path)).iter(f"{{{_A_NS}}}blip"): + embed_rid = blip.get(f"{{{_R_NS}}}embed") + if not embed_rid: + continue + rel_target = drawing_rel_map.get(embed_rid) + if not rel_target: + continue + media_path = _normalize_rel_path(drawing_dir, rel_target) + if media_path in names: + media_paths.append(media_path) + + if media_paths: + result[sheet_name] = media_paths + return result + except (zipfile.BadZipFile, KeyError, OSError, ET.ParseError): + return {} + + +def _sanitize_filename_part(name: str) -> str: + safe = re.sub(r"[^A-Za-z0-9_.-]+", "_", name).strip("_") + return safe or "sheet" + + +def extract_images(xlsx_path: Path, img_dir: Path): + """Extract embedded images from xlsx_path, grouped by sheet name. + Returns {sheet_name: [filename, ...]} in per-sheet order. Files are + named '_img{N:03d}.'.""" + sheet_media = _sheet_name_to_media(xlsx_path) + if not sheet_media: + return {} + + written = {} + with zipfile.ZipFile(xlsx_path) as z: + names_in_zip = set(z.namelist()) + for sheet_idx, (sheet_name, media_paths) in enumerate(sheet_media.items(), start=1): + safe_name = f"sheet{sheet_idx:03d}_{_sanitize_filename_part(sheet_name)}" + files = [] + for idx, media_path in enumerate(media_paths, start=1): + if media_path not in names_in_zip: + print(f"WARNING: {media_path} not found in {xlsx_path}", file=sys.stderr) + continue + ext = Path(media_path).suffix.lstrip(".").lower() or "bin" + if ext == "jpg": + ext = "jpeg" + out_name = f"{safe_name}_img{idx:03d}.{ext}" + img_dir.mkdir(parents=True, exist_ok=True) + (img_dir / out_name).write_bytes(z.read(media_path)) + files.append(out_name) + if files: + written[sheet_name] = files + return written + + +def insert_sheet_images(markdown_text: str, sheet_images) -> str: + """Insert a '#### Images in this sheet' block right after each sheet's + section (before the next '## ' heading or end of text). If a sheet has + no images, or no '## ' headings are found at all, the text is returned + unchanged for that part.""" + if not sheet_images: + return markdown_text + matches = list(_SHEET_HEADER_RE.finditer(markdown_text)) + if not matches: + return markdown_text + + pieces = [] + last_end = 0 + for i, m in enumerate(matches): + sheet_name = m.group(1).removesuffix("\r") + start = m.start() + end = matches[i + 1].start() if i + 1 < len(matches) else len(markdown_text) + pieces.append(markdown_text[last_end:start]) + section = markdown_text[start:end].rstrip("\n") + images = sheet_images.get(sheet_name) + if images: + section += "\n\n#### Images in this sheet\n\n" + section += "\n".join(f"![{name}](img/{name})" for name in images) + pieces.append(section + "\n\n") + last_end = end + pieces.append(markdown_text[last_end:]) + return "".join(pieces).rstrip() + "\n" + + +def convert_one(md, source: Path, dest_dir: Path) -> bool: + """Convert a single .xlsx file to a '/' folder containing the + Markdown file and an 'img/' folder of extracted images. Returns True on + success.""" + try: + result = md.convert(str(source)) + except Exception as exc: # noqa: BLE001 - surface any conversion error + print(f"FAILED {source} -> {exc}", file=sys.stderr) + return False + + try: + img_dir = dest_dir / "img" + if dest_dir.exists(): + if img_dir.exists(): + shutil.rmtree(img_dir) + dest_dir.mkdir(parents=True, exist_ok=True) + sheet_images = extract_images(source, img_dir) + text = insert_sheet_images(result.text_content, sheet_images) + md_path = dest_dir / f"{source.stem}.md" + md_path.write_text(text, encoding="utf-8") + except OSError as exc: + print(f"FAILED {source} -> could not write output in {dest_dir}: {exc}", file=sys.stderr) + return False + + img_count = sum(len(v) for v in sheet_images.values()) + img_note = f", {img_count} image(s)" if img_count else "" + print(f"OK {source} -> {md_path}{img_note}") + return True + + +def find_xlsx_files(root: Path, recursive: bool): + """Return (xlsx_files, skipped_count) for files directly/recursively under root.""" + pattern_iter = root.rglob("*") if recursive else root.iterdir() + xlsx_files = [] + skipped = 0 + for entry in pattern_iter: + if entry.is_dir(): + continue + if entry.suffix.lower() == ".xlsx": + xlsx_files.append(entry) + else: + skipped += 1 + return sorted(xlsx_files), skipped + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("input", help="Path to a .xlsx file or a directory of .xlsx files") + parser.add_argument( + "-o", "--output", + help=( + "Destination folder for the '/' output (single-file mode), " + "or parent directory under which each '/' output folder is " + "created (batch mode)" + ), + ) + parser.add_argument( + "--recursive", action="store_true", + help="When input is a directory, also search subdirectories", + ) + args = parser.parse_args() + + #MarkItDown = _import_markitdown() + #md = MarkItDown() + + source = Path(args.input) + if not source.exists(): + print(f"ERROR: Input path not found: {source}", file=sys.stderr) + return EXIT_INVALID_INPUT + + if source.is_file() and source.suffix.lower() != ".xlsx": + print( + f"ERROR: Unsupported file type '{source.suffix}'. " + "This skill only converts .xlsx files.", + file=sys.stderr, + ) + return EXIT_INVALID_INPUT + + MarkItDown = _import_markitdown() + md = MarkItDown() + + if source.is_file(): + dest_dir = Path(args.output) if args.output else source.parent / source.stem + return EXIT_OK if convert_one(md, source, dest_dir) else EXIT_CONVERSION_FAILED + + # Directory / batch mode + xlsx_files, skipped = find_xlsx_files(source, args.recursive) + if skipped: + print(f"NOTE: skipped {skipped} non-.xlsx file(s) in {source}") + if not xlsx_files: + print(f"ERROR: No .xlsx files found under {source}", file=sys.stderr) + return EXIT_INVALID_INPUT + + out_dir = Path(args.output) if args.output else None + success_count = 0 + for xlsx_path in xlsx_files: + if out_dir is not None: + rel = xlsx_path.relative_to(source) + dest_dir = out_dir / rel.parent / xlsx_path.stem + else: + dest_dir = xlsx_path.parent / xlsx_path.stem + if convert_one(md, xlsx_path, dest_dir): + success_count += 1 + + total = len(xlsx_files) + print(f"\nConverted {success_count}/{total} file(s).") + return EXIT_OK if success_count == total else EXIT_CONVERSION_FAILED + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/skills/convert-excel-to-md/scripts/requirements.txt b/skills/convert-excel-to-md/scripts/requirements.txt new file mode 100644 index 00000000..be2934a4 --- /dev/null +++ b/skills/convert-excel-to-md/scripts/requirements.txt @@ -0,0 +1 @@ +markitdown[xlsx]>=0.1.0 diff --git a/skills/convert-pdf-to-md/SKILL.md b/skills/convert-pdf-to-md/SKILL.md new file mode 100644 index 00000000..e9f79ec5 --- /dev/null +++ b/skills/convert-pdf-to-md/SKILL.md @@ -0,0 +1,130 @@ +--- +name: convert-pdf-to-md +description: 'Converts PDF (.pdf) documents into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Use this skill whenever the user shares, references, or asks about a .pdf file — even if they don''t say "convert" or "markdown" explicitly. This includes requests to "read", "summarize", "review", "extract data from", "compare", or "analyze" a PDF report, paper, invoice, form, contract, or scanned document. Always run the bundled conversion script to produce Markdown first; do not attempt to parse PDF content directly or write ad-hoc extraction code. Also use this skill for batch requests involving a whole folder of PDF documents. IMPORTANT: When the user references a folder or set of documents containing multiple file types (.pdf, .docx, .xlsx), invoke ALL three sibling skills — convert-pdf-to-md, convert-word-to-md, and convert-excel-to-md — so no file type is silently skipped.' +--- + +# Convert PDF to Markdown + +## When to use this skill + +Trigger this skill any time there is a `.pdf` file that needs to be +understood or processed — for example, a user attaches a PDF and asks +questions about it, wants a summary, wants specific data or tables pulled +out, or wants multiple PDFs in a folder processed together. PDF is a +layout/print format, not reliably readable as plain text, so always convert +it to Markdown first using the script in this skill rather than trying to +open or parse the file directly. + +This skill only supports `.pdf` — that's MarkItDown's only PDF-family +format, so there's no legacy format to worry about here (unlike Word's +`.doc` or Excel's `.xls`). + +**Mixed file types:** When the user references a folder or set of documents +containing multiple supported file types (`.pdf`, `.docx`, `.xlsx`), this +skill handles only `.pdf` files. The agent MUST also invoke the sibling +skills in parallel: +- `convert-word-to-md` for any `.docx` files +- `convert-excel-to-md` for any `.xlsx` files + +Never process a folder and silently skip a supported file type. All three +skills must be invoked together when mixed types are present. + +## Setup (once per environment) + +Before the first conversion in a given environment, follow +[`references/setup.md`](references/setup.md) step by step to ensure Python, +pip, `markitdown`, and `pymupdf` (for image extraction) are installed. Do +this proactively rather than guessing whether the environment is ready — the +script itself will also fail with a clear pointer back to that file if a +dependency turns out to be missing, so it's safe to just try the conversion +first if you're reasonably confident setup was already done. + +## Usage + +The conversion script lives at `scripts/convert_pdf_to_md.py`. + +**Output structure:** MarkItDown's PDF converter extracts text and tables +only — it has no concept of embedded images at all. This script separately +extracts real embedded images via PyMuPDF and writes a self-contained folder +per document: + +``` +/ + img/ + page001_img001. + page002_img001. + ... + .md +``` + +Because MarkItDown's PDF text does not preserve reliable per-page markers, +there's no safe way to know exactly where inline an image belongs. Rather +than risk misplacing images next to the wrong paragraph, the script appends +a `## Extracted Images` section at the end of the Markdown, with a +`### Page N` subheading per page that has images — read this section +separately from the main body text. If the document has no embedded images, +no `img/` folder or `Extracted Images` section is created. + +**Single file:** + +```powershell +python scripts\convert_pdf_to_md.py "C:\path\to\document.pdf" +``` + +This creates a `document\` folder next to the source file (containing +`document.md` and, if present, `document\img\`). To control the destination +folder explicitly: + +```powershell +python scripts\convert_pdf_to_md.py "C:\path\to\document.pdf" -o "C:\path\to\output_folder" +``` + +**A folder of PDFs (batch mode):** + +```powershell +python scripts\convert_pdf_to_md.py "C:\path\to\folder" +``` + +Add `--recursive` to also include subfolders: + +```powershell +python scripts\convert_pdf_to_md.py "C:\path\to\folder" --recursive +``` + +Each `.pdf` found gets its own `\` output folder next to it by +default. Pass `-o "C:\path\to\output_parent"` to collect all the generated +`\` folders under a separate parent directory instead (subfolder +structure is preserved when combined with `--recursive`). + +After conversion, read the resulting `.md` file(s) to perform the actual +analysis the user asked for — the script's job is only to produce accurate +Markdown (and images), not to interpret the content. + +## Deciding where output goes + +**Default — always output next to the source file.** The `/` folder +is created in the same directory as the source `.pdf`. This is the required +default for every case. Do NOT override it unless the user explicitly asks +for a different location. + +**Only use `-o` when** the user explicitly provides an output path (e.g., +"save the output to `C:\output`", "put the results in `D:\work`"). Do NOT +pass `-o` based on the agent's current working directory, the session state +folder, or any implied location. + +**If the source file path cannot be fully resolved** — for example, the +user provides only a filename with no directory, or the path is ambiguous — +use `ask_user` to confirm the full absolute path before running the +conversion. Never guess or assume the directory. + +## Troubleshooting + +| Symptom | Likely cause | Fix | +|---|---|---| +| `ModuleNotFoundError: No module named 'markitdown'` or `'fitz'` / exit code 2 | MarkItDown or PyMuPDF not installed | Follow `references/setup.md` | +| `ERROR: Unsupported file type '...'` / exit code 3 | Not a `.pdf` file | Ask the user for the correct file, or if it's `.doc`/`.docx`/`.xlsx`, use the matching sibling skill instead | +| `ERROR: Input path not found` / exit code 3 | Wrong path, or file moved | Confirm the correct path with the user | +| `FAILED -> ...` in batch output | That specific file is corrupt, password-protected, or otherwise unreadable | Report which file(s) failed; other files in the batch still succeed | +| `NOTE: skipped N non-.pdf file(s)` | Folder contains non-PDF files | Expected — those files are intentionally ignored | +| Markdown body is empty or near-empty despite images being extracted | The PDF is scanned/image-only with no embedded text layer; MarkItDown does not perform OCR | Tell the user OCR isn't supported — the extracted page images are still available for them to view | +| Images appear in an appendix instead of inline with the text | Deliberate limitation — MarkItDown's PDF text has no reliable per-page markers to place images inline | Expected behavior; cross-reference the `### Page N` heading with the surrounding text context if needed | diff --git a/skills/convert-pdf-to-md/references/setup.md b/skills/convert-pdf-to-md/references/setup.md new file mode 100644 index 00000000..4c8a95e6 --- /dev/null +++ b/skills/convert-pdf-to-md/references/setup.md @@ -0,0 +1,71 @@ +# Environment Setup for convert-pdf-to-md + +Follow these steps exactly, in order, before running `scripts/convert_pdf_to_md.py` +for the first time in a given environment. Don't skip steps or improvise +alternatives — they're written to be deterministic and safe to re-run. + +## 1. Check Python is available (3.10+) + +```powershell +python --version +``` + +- If this fails (command not found), install Python 3.10 or newer: + - Windows: `winget install --id Python.Python.3.12 -e` + - macOS: `brew install python@3.12` + - Linux (Debian/Ubuntu): `sudo apt-get update && sudo apt-get install -y python3 python3-pip python-is-python3` +- If the reported version is older than 3.10, install a newer Python using + the same command above (MarkItDown requires 3.10+). + +## 2. Check pip is available + +```powershell +python -m pip --version +``` + +- If this fails, bootstrap pip: + +```powershell +python -m ensurepip --upgrade +``` + +## 3. Install MarkItDown with PDF support, plus PyMuPDF for image extraction + +Use the `scripts/requirements.txt` file bundled with this skill to install pinned, +known-good versions of the dependencies: + +```powershell +python -m pip install -r scripts/requirements.txt +``` + +This pulls in `markitdown[pdf]` and `pymupdf>=1.24.0`. PyMuPDF (imported as `fitz`) +is required separately because MarkItDown's PDF +converter only extracts text and tables — it has no support for embedded +images at all, so this skill's script extracts them itself. + +## 4. Verify the install + +```powershell +python -c "from markitdown import MarkItDown; import fitz; print('markitdown + pymupdf OK')" +``` + +Expect to see `markitdown + pymupdf OK` printed with no errors. If you see a +`ModuleNotFoundError`, repeat step 3 — pip may be installing into a +different Python environment than the one being invoked (check +`python -m pip --version` shows the same path as `python --version`'s +interpreter). + +## Notes + +- This setup only needs to be done once per environment/virtual environment, + not once per conversion. +- `convert_pdf_to_md.py` itself also checks for `markitdown` and `fitz` at + startup and prints a pointer back to this file if either is missing, so + re-running setup is safe and idempotent. +- Only `.pdf` is supported by this skill — it's MarkItDown's only PDF-family + format, so there's no legacy-format equivalent to worry about (unlike + Word's `.doc` or Excel's `.xls`). +- Scanned/image-only PDFs (no embedded text layer) will produce little or + no text from MarkItDown, since it does not perform OCR. The images + themselves will still be extracted and appended, but the text body may be + empty or near-empty in that case — mention this to the user if it happens. diff --git a/skills/convert-pdf-to-md/scripts/convert_pdf_to_md.py b/skills/convert-pdf-to-md/scripts/convert_pdf_to_md.py new file mode 100644 index 00000000..8beb5b9f --- /dev/null +++ b/skills/convert-pdf-to-md/scripts/convert_pdf_to_md.py @@ -0,0 +1,321 @@ +#!/usr/bin/env python3 +"""Convert PDF documents to Markdown using Microsoft's MarkItDown, with +embedded images extracted to real files via PyMuPDF (MarkItDown's PDF +converter only extracts text/tables -- it does not detect or emit anything +for embedded images at all). + +Usage: + python convert_pdf_to_md.py [-o OUTPUT] [--recursive] + + may be either: + - a path to a single .pdf file, or + - a path to a directory (batch mode: every .pdf file directly inside it + is converted; pass --recursive to also descend into subdirectories). + +Output: + For each source .pdf (named ".pdf"), a folder is created containing + the Markdown and its images, in this layout: + + / + img/ + page001_img001. + page001_img002. + page002_img001. + ... + .md + + IMPORTANT: MarkItDown's PDF text extraction does not preserve reliable + per-page markers in the returned Markdown (pages are simply joined + together, or in some cases returned as a single unmarked block of text). + That means there is no safe way to know exactly where, inline, an image + should go. Rather than guess and risk misplacing an image next to the + wrong paragraph, this script appends a clearly labeled "## Extracted + Images" section at the end of the Markdown, with a "### Page N" + subheading per page that contains images. This is a deliberate, honest + tradeoff -- read the images section separately from the main body text. + + - Single file mode: the "/" folder is created next to the source + file, or at -o/--output (treated as the exact destination folder) if + given. + - Batch/directory mode: a "/" folder is created next to each source + file, or under -o/--output (treated as a parent directory, created if + missing) if given, preserving relative subfolder structure when + --recursive is used. + - If a document has no embedded images, no "img/" folder or "Extracted + Images" section is created. + +Exit codes: + 0 - all requested conversions succeeded + 1 - one or more conversions failed (partial success in batch mode) + 2 - a required dependency ("markitdown" or "pymupdf") is not installed + 3 - invalid input (path not found, or single-file input is not .pdf) +""" +import argparse +import sys +import hashlib +import shutil +from pathlib import Path + +EXIT_OK = 0 +EXIT_CONVERSION_FAILED = 1 +EXIT_MISSING_DEPENDENCY = 2 +EXIT_INVALID_INPUT = 3 + + +def _import_markitdown(): + """Import MarkItDown, failing with a clear, actionable message if absent.""" + try: + from markitdown import MarkItDown + return MarkItDown + except ImportError: + print( + "ERROR: The 'markitdown' package is not installed.\n" + "See references/setup.md for this skill, or run:\n" + ' pip install "markitdown[pdf]"', + file=sys.stderr, + ) + sys.exit(EXIT_MISSING_DEPENDENCY) + + +def _import_fitz(): + """Import PyMuPDF (module name 'fitz'), failing with a clear message if absent.""" + try: + import fitz + import hashlib + return fitz + except ImportError: + print( + "ERROR: The 'pymupdf' package is not installed (needed for image " + "extraction).\nSee references/setup.md for this skill, or run:\n" + " pip install pymupdf", + file=sys.stderr, + ) + sys.exit(EXIT_MISSING_DEPENDENCY) + + +def extract_images(fitz, pdf_path: Path, img_dir: Path): + """Extract embedded images from pdf_path, grouped by 1-based page number. + Returns {page_num: [filename, ...]} in per-page image order. Files are + named 'page{P:03d}_img{N:03d}.'. Corrupt/unreadable images are + skipped with a warning rather than aborting the whole conversion. + + Two sources are combined and deduplicated: + 1. Image XObjects via page.get_images(full=True) -- covers most embedded + images in modern PDFs. + 2. Inline image blocks via page.get_text("dict") -- covers images stored + directly in the page content stream, which get_images() misses entirely. + Deduplication is by image bytes hash so the same raster is never written twice + on the same page regardless of which source reported it.""" + written_by_page = {} + try: + doc = fitz.open(str(pdf_path)) + except Exception as exc: # noqa: BLE001 + print(f"WARNING: could not open {pdf_path} for image extraction: {exc}", file=sys.stderr) + return written_by_page + + try: + for page_index in range(len(doc)): + page = doc[page_index] + page_label = page_index + 1 + seen_hashes: set = set() + raw_images: list[tuple[bytes, str]] = [] # (image_bytes, ext) + + # --- Source 1: XObject images --- + try: + xobjects = page.get_images(full=True) + except Exception as exc: # noqa: BLE001 + print( + f"WARNING: failed to enumerate XObject images on page {page_label} " + f"of {pdf_path}: {exc}", + file=sys.stderr, + ) + xobjects = [] + + for img in xobjects: + xref = img[0] + try: + base_image = doc.extract_image(xref) + except Exception as exc: # noqa: BLE001 + print( + f"WARNING: failed to extract XObject image xref={xref} on page " + f"{page_label} of {pdf_path}: {exc}", + file=sys.stderr, + ) + continue + img_bytes = base_image.get("image") or b"" + if not img_bytes: + continue + ext = (base_image.get("ext") or "png").lower() + raw_images.append((img_bytes, ext)) + + # --- Source 2: Inline images via get_text("dict") --- + try: + blocks = page.get_text("dict", flags=fitz.TEXT_PRESERVE_IMAGES).get("blocks", []) + except Exception as exc: # noqa: BLE001 + print( + f"WARNING: failed to extract text/image dict on page {page_label} " + f"of {pdf_path}: {exc}", + file=sys.stderr, + ) + blocks = [] + + for block in blocks: + # Image blocks have type == 1 + if block.get("type") != 1: + continue + img_bytes = block.get("image") or b"" + if not img_bytes: + continue + # Derive extension from the block's "ext" key (fitz sets this) + ext = (block.get("ext") or "png").lower() + raw_images.append((img_bytes, ext)) + + # --- Write deduplicated images --- + page_files = [] + img_idx = 1 + for img_bytes, ext in raw_images: + h = hashlib.sha256(img_bytes).digest() + if h in seen_hashes: + continue + seen_hashes.add(h) + out_name = f"page{page_label:03d}_img{img_idx:03d}.{ext}" + img_dir.mkdir(parents=True, exist_ok=True) + (img_dir / out_name).write_bytes(img_bytes) + page_files.append(out_name) + img_idx += 1 + + if page_files: + written_by_page[page_label] = page_files + finally: + doc.close() + + return written_by_page + + +def build_image_appendix(written_by_page) -> str: + """Build the '## Extracted Images' appendix text. Returns "" if empty.""" + if not written_by_page: + return "" + lines = ["", "## Extracted Images", ""] + for page_num in sorted(written_by_page): + lines.append(f"### Page {page_num}") + lines.append("") + for name in written_by_page[page_num]: + lines.append(f"![{name}](img/{name})") + lines.append("") + return "\n".join(lines).rstrip() + "\n" + + +def convert_one(md, fitz, source: Path, dest_dir: Path) -> bool: + """Convert a single .pdf file to a '/' folder containing the + Markdown file and an 'img/' folder of extracted images. Returns True on + success.""" + try: + result = md.convert(str(source)) + except Exception as exc: # noqa: BLE001 - surface any conversion error + print(f"FAILED {source} -> {exc}", file=sys.stderr) + return False + + try: + if dest_dir.exists(): + shutil.rmtree(dest_dir) + dest_dir.mkdir(parents=True, exist_ok=True) + written_by_page = extract_images(fitz, source, dest_dir / "img") + appendix = build_image_appendix(written_by_page) + text = result.text_content.rstrip("\n") + full_text = f"{text}\n{appendix}" if appendix else f"{text}\n" + md_path = dest_dir / f"{source.stem}.md" + md_path.write_text(full_text, encoding="utf-8") + except OSError as exc: + print(f"FAILED {source} -> could not write output in {dest_dir}: {exc}", file=sys.stderr) + return False + + img_count = sum(len(v) for v in written_by_page.values()) + img_note = f", {img_count} image(s)" if img_count else "" + print(f"OK {source} -> {md_path}{img_note}") + return True + + +def find_pdf_files(root: Path, recursive: bool): + """Return (pdf_files, skipped_count) for files directly/recursively under root.""" + pattern_iter = root.rglob("*") if recursive else root.iterdir() + pdf_files = [] + skipped = 0 + for entry in pattern_iter: + if entry.is_dir(): + continue + if entry.suffix.lower() == ".pdf": + pdf_files.append(entry) + else: + skipped += 1 + return sorted(pdf_files), skipped + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("input", help="Path to a .pdf file or a directory of .pdf files") + parser.add_argument( + "-o", "--output", + help=( + "Destination folder for the '/' output (single-file mode), " + "or parent directory under which each '/' output folder is " + "created (batch mode)" + ), + ) + parser.add_argument( + "--recursive", action="store_true", + help="When input is a directory, also search subdirectories", + ) + args = parser.parse_args() + + #MarkItDown = _import_markitdown() + #fitz = _import_fitz() + #md = MarkItDown() + + source = Path(args.input) + if not source.exists(): + print(f"ERROR: Input path not found: {source}", file=sys.stderr) + return EXIT_INVALID_INPUT + + if source.is_file() and source.suffix.lower() != ".pdf": + print( + f"ERROR: Unsupported file type '{source.suffix}'. " + "This skill only converts .pdf files.", + file=sys.stderr, + ) + return EXIT_INVALID_INPUT + + MarkItDown = _import_markitdown() + fitz = _import_fitz() + md = MarkItDown() + + if source.is_file(): + dest_dir = Path(args.output) if args.output else source.parent / source.stem + return EXIT_OK if convert_one(md, fitz, source, dest_dir) else EXIT_CONVERSION_FAILED + + # Directory / batch mode + pdf_files, skipped = find_pdf_files(source, args.recursive) + if skipped: + print(f"NOTE: skipped {skipped} non-.pdf file(s) in {source}") + if not pdf_files: + print(f"ERROR: No .pdf files found under {source}", file=sys.stderr) + return EXIT_INVALID_INPUT + + out_dir = Path(args.output) if args.output else None + success_count = 0 + for pdf_path in pdf_files: + if out_dir is not None: + rel = pdf_path.relative_to(source) + dest_dir = out_dir / rel.parent / pdf_path.stem + else: + dest_dir = pdf_path.parent / pdf_path.stem + if convert_one(md, fitz, pdf_path, dest_dir): + success_count += 1 + + total = len(pdf_files) + print(f"\nConverted {success_count}/{total} file(s).") + return EXIT_OK if success_count == total else EXIT_CONVERSION_FAILED + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/skills/convert-pdf-to-md/scripts/requirements.txt b/skills/convert-pdf-to-md/scripts/requirements.txt new file mode 100644 index 00000000..ae70f025 --- /dev/null +++ b/skills/convert-pdf-to-md/scripts/requirements.txt @@ -0,0 +1,2 @@ +markitdown[pdf]>=0.1.0 +pymupdf>=1.24.0 diff --git a/skills/convert-word-to-md/SKILL.md b/skills/convert-word-to-md/SKILL.md new file mode 100644 index 00000000..482778ea --- /dev/null +++ b/skills/convert-word-to-md/SKILL.md @@ -0,0 +1,129 @@ +--- +name: convert-word-to-md +description: 'Converts Word (.docx) documents into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Use this skill whenever the user shares, references, or asks about a .docx file — even if they don''t say "convert" or "markdown" explicitly. This includes requests to "read", "summarize", "review", "extract data from", "compare", or "analyze" a Word document, resume, report, contract, or proposal. Always run the bundled conversion script to produce Markdown first; do not attempt to parse .docx content directly or write ad-hoc conversion code. Also use this skill for batch requests involving a whole folder of Word documents. IMPORTANT: When the user references a folder or set of documents containing multiple file types (.pdf, .docx, .xlsx), invoke ALL three sibling skills — convert-pdf-to-md, convert-word-to-md, and convert-excel-to-md — so no file type is silently skipped.' +--- + +# Convert Word to Markdown + +## When to use this skill + +Trigger this skill any time there is a `.docx` file that needs to be +understood or processed — for example, a user attaches a Word document and +asks questions about it, wants a summary, wants specific data pulled out, or +wants multiple Word documents in a folder processed together. Word's native +`.docx` format is a zipped XML bundle that is not reliably readable as plain +text, so always convert it to Markdown first using the script in this +skill rather than trying to open or parse the file directly. + +This skill only supports `.docx`. If asked to convert a legacy `.doc` file, +tell the user it isn't supported and ask them to re-save it as `.docx` +(Word: File > Save As > Word Document (.docx)) first. + +**Mixed file types:** When the user references a folder or set of documents +containing multiple supported file types (`.pdf`, `.docx`, `.xlsx`), this +skill handles only `.docx` files. The agent MUST also invoke the sibling +skills in parallel: +- `convert-pdf-to-md` for any `.pdf` files +- `convert-excel-to-md` for any `.xlsx` files + +Never process a folder and silently skip a supported file type. All three +skills must be invoked together when mixed types are present. + +## Setup (once per environment) + +Before the first conversion in a given environment, follow +[`references/setup.md`](references/setup.md) step by step to ensure Python, +pip, and the `markitdown` package are installed. Do this proactively rather +than guessing whether the environment is ready — the script itself will +also fail with a clear pointer back to that file if `markitdown` turns out +to be missing, so it's safe to just try the conversion first if you're +reasonably confident setup was already done. + +## Usage + +The conversion script lives at `scripts/convert_word_to_md.py`. + +**Output structure:** MarkItDown embeds images as a truncated `data:image/png;base64...` URI +placeholder (not real image data), so the script +extracts real images directly from the `.docx` and writes a self-contained +folder per document instead of a single loose `.md` file: + +``` +/ + img/ + img001. + img002. + ... + .md (image references are relative: img/imgNNN.ext) +``` + +If the document has no embedded images, no `img/` folder is created. + +**Single file:** + +```powershell +# Windows +python scripts\convert_word_to_md.py "C:\path\to\document.docx" +``` + +```bash +# macOS / Linux +python scripts/convert_word_to_md.py "/path/to/document.docx" +``` + +This creates a `document\` folder next to the source file (containing +`document.md` and, if present, `document\img\`). To control the destination +folder explicitly: + +```powershell +python scripts\convert_word_to_md.py "C:\path\to\document.docx" -o "C:\path\to\output_folder" +``` + +**A folder of Word documents (batch mode):** + +```powershell +python scripts\convert_word_to_md.py "C:\path\to\folder" +``` + +Add `--recursive` to also include subfolders: + +```powershell +python scripts\convert_word_to_md.py "C:\path\to\folder" --recursive +``` + +Each `.docx` found gets its own `\` output folder next to it by +default. Pass `-o "C:\path\to\output_parent"` to collect all the generated +`\` folders under a separate parent directory instead (subfolder +structure is preserved when combined with `--recursive`). + +After conversion, read the resulting `.md` file(s) to perform the actual +analysis the user asked for — the script's job is only to produce accurate +Markdown (and images), not to interpret the content. + +## Deciding where output goes + +**Default — always output next to the source file.** The `/` folder +is created in the same directory as the source `.docx`. This is the required +default for every case. Do NOT override it unless the user explicitly asks +for a different location. + +**Only use `-o` when** the user explicitly provides an output path (e.g., +"save the output to `C:\output`", "put the results in `D:\work`"). Do NOT +pass `-o` based on the agent's current working directory, the session state +folder, or any implied location. + +**If the source file path cannot be fully resolved** — for example, the +user provides only a filename with no directory, or the path is ambiguous — +use `ask_user` to confirm the full absolute path before running the +conversion. Never guess or assume the directory. + +## Troubleshooting + +| Symptom | Likely cause | Fix | +|---|---|---| +| `ModuleNotFoundError: No module named 'markitdown'` / exit code 2 | MarkItDown not installed | Follow `references/setup.md` | +| `ERROR: Unsupported file type '.doc'` / exit code 3 | Legacy `.doc`, not `.docx` | Ask the user to re-save as `.docx` | +| `ERROR: Input path not found` / exit code 3 | Wrong path, or file moved | Confirm the correct path with the user | +| `FAILED -> ...` in batch output | That specific file is corrupt, password-protected, or otherwise unreadable | Report which file(s) failed; other files in the batch still succeed | +| `NOTE: skipped N non-.docx file(s)` | Folder contains non-Word files | Expected — those files are intentionally ignored | +| `WARNING: found N image placeholder(s) ... but extracted M image file(s)` | Mismatch between MarkItDown's placeholder count and images found in `word/media/` (unusual/malformed docx) | Placeholders are left unreplaced rather than risk wrong images; inspect the source file's media manually if images are needed | diff --git a/skills/convert-word-to-md/references/setup.md b/skills/convert-word-to-md/references/setup.md new file mode 100644 index 00000000..c8fac5ea --- /dev/null +++ b/skills/convert-word-to-md/references/setup.md @@ -0,0 +1,66 @@ +# Environment Setup for convert-word-to-md + +Follow these steps exactly, in order, before running `scripts/convert_word_to_md.py` +for the first time in a given environment. Don't skip steps or improvise +alternatives — they're written to be deterministic and safe to re-run. + +## 1. Check Python is available (3.10+) + +```powershell +python --version +``` + +- If this fails (command not found), install Python 3.10 or newer: + - Windows: `winget install --id Python.Python.3.12 -e` + - macOS: `brew install python@3.12` + - Linux (Debian/Ubuntu): `sudo apt-get update && sudo apt-get install -y python3 python3-pip python-is-python3` +- If the reported version is older than 3.10, install a newer Python using + the same command above (MarkItDown requires 3.10+). + +## 2. Check pip is available + +```powershell +python -m pip --version +``` + +- If this fails, bootstrap pip: + +```powershell +python -m ensurepip --upgrade +``` + +## 3. Install MarkItDown with Word (.docx) support + +Use the `scripts/requirements.txt` file bundled with this skill to install a pinned, +known-good version of the dependency: + +```powershell +python -m pip install -r scripts/requirements.txt +``` + +This pulls in `markitdown[docx]` (MarkItDown's Word conversion dependency, which +includes `mammoth` for `.docx` file parsing). No extra package is needed — this +skill's script uses MarkItDown's built-in Word converter. + +## 4. Verify the install + +```powershell +python -c "from markitdown import MarkItDown; print('markitdown OK')" +``` + +Expect to see `markitdown OK` printed with no errors. If you see +`ModuleNotFoundError: No module named 'markitdown'`, repeat step 3 — pip may +be installing into a different Python environment than the one being +invoked (check `python -m pip --version` shows the same path as `python +--version`'s interpreter). + +## Notes + +- This setup only needs to be done once per environment/virtual environment, + not once per conversion. +- `convert_word_to_md.py` itself also checks for `markitdown` at startup and + prints a pointer back to this file if it's missing, so re-running setup is + safe and idempotent. +- Only `.docx` is supported by this skill. Legacy binary `.doc` files are + out of scope — ask the user to re-save the file as `.docx` (e.g., via + Word's "Save As") if one is encountered. diff --git a/skills/convert-word-to-md/scripts/convert_word_to_md.py b/skills/convert-word-to-md/scripts/convert_word_to_md.py new file mode 100644 index 00000000..4723fa63 --- /dev/null +++ b/skills/convert-word-to-md/scripts/convert_word_to_md.py @@ -0,0 +1,301 @@ +#!/usr/bin/env python3 +"""Convert Word (.docx) documents to Markdown using Microsoft's MarkItDown, +with embedded images extracted to real files (MarkItDown only emits a +truncated `data:image/...;base64...` placeholder, not real image data). + +Usage: + python convert_word_to_md.py [-o OUTPUT] [--recursive] + + may be either: + - a path to a single .docx file, or + - a path to a directory (batch mode: every .docx file directly inside it + is converted; pass --recursive to also descend into subdirectories). + +Output: + For each source .docx (named ".docx"), a folder is created + containing the Markdown and its images, in this layout: + + / + img/ + img001. + img002. + ... + .md (image references are relative: img/imgNNN.ext) + + - Single file mode: the "/" folder is created next to the source + file, or at -o/--output (treated as the exact destination folder) if + given. + - Batch/directory mode: a "/" folder is created next to each source + file, or under -o/--output (treated as a parent directory, created if + missing) if given, preserving relative subfolder structure when + --recursive is used. + - If a document has no embedded images, no "img/" folder is created. + +Exit codes: + 0 - all requested conversions succeeded + 1 - one or more conversions failed (partial success in batch mode) + 2 - required dependency ("markitdown") is not installed + 3 - invalid input (path not found, or single-file input is not .docx) +""" +import argparse +import re +import shutil +import sys +import zipfile +from pathlib import Path +from xml.etree import ElementTree as ET + +EXIT_OK = 0 +EXIT_CONVERSION_FAILED = 1 +EXIT_MISSING_DEPENDENCY = 2 +EXIT_INVALID_INPUT = 3 + +_W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" +_R_NS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" +_REL_NS = "http://schemas.openxmlformats.org/package/2006/relationships" + +# MarkItDown embeds images as a literal truncated placeholder, e.g. +# ![alt](data:image/png;base64...) -- NOT real base64 data. This pattern +# matches that placeholder so it can be swapped for a real relative path. +_PLACEHOLDER_IMAGE_RE = re.compile( + r'!\[([^\]]*)\]\(data:image/[a-zA-Z0-9.+-]+;base64[^)]*\)' +) + + +def _import_markitdown(): + """Import MarkItDown, failing with a clear, actionable message if absent.""" + try: + from markitdown import MarkItDown + return MarkItDown + except ImportError: + print( + "ERROR: The 'markitdown' package is not installed.\n" + "See references/setup.md for this skill, or run:\n" + ' pip install "markitdown[docx]"', + file=sys.stderr, + ) + sys.exit(EXIT_MISSING_DEPENDENCY) + + +def _document_order_media(docx_path: Path): + """Return [(rel_id, media_zip_path), ...] in the order images appear in + word/document.xml (via r:embed / r:id), resolved through + word/_rels/document.xml.rels. Returns [] if the document has no body + part or no images (e.g. malformed docx falls back gracefully).""" + try: + with zipfile.ZipFile(docx_path) as z: + if "word/document.xml" not in z.namelist() or \ + "word/_rels/document.xml.rels" not in z.namelist(): + return [] + rels_xml = z.read("word/_rels/document.xml.rels") + doc_xml = z.read("word/document.xml") + except (zipfile.BadZipFile, KeyError, OSError): + return [] + + try: + rels_root = ET.fromstring(rels_xml) + doc_root = ET.fromstring(doc_xml) + except ET.ParseError: + return [] + + rel_map = {} + for rel in rels_root.findall(f"{{{_REL_NS}}}Relationship"): + rel_map[rel.get("Id")] = rel.get("Target") + + ordered_rel_ids = [] + for elem in doc_root.iter(): + tag = elem.tag.rsplit("}", 1)[-1] + if tag == "blip": + rid = elem.get(f"{{{_R_NS}}}embed") + elif tag == "imagedata": + rid = elem.get(f"{{{_R_NS}}}id") + else: + rid = None + if rid: + ordered_rel_ids.append(rid) + ordered_media = [] + for rid in ordered_rel_ids: + target = rel_map.get(rid) + if not target or "media/" not in target: + continue + import posixpath + media_path = ( + target.lstrip("/") + if target.startswith("/") + else posixpath.normpath( + target if target.startswith("word/") else posixpath.join("word", target) + ) + ) + ordered_media.append((rid, media_path)) + return ordered_media + + +def _extract_images(docx_path: Path, img_dir: Path): + """Extract embedded images from docx_path into img_dir as img001.ext, + img002.ext, ... in document order. Returns the list of written filenames + (relative to img_dir), in that same order.""" + ordered_media = _document_order_media(docx_path) + if not ordered_media: + return [] + + written = [] + with zipfile.ZipFile(docx_path) as z: + names_in_zip = set(z.namelist()) + for idx, (rid, media_path) in enumerate(ordered_media, start=1): + if media_path not in names_in_zip: + print(f"WARNING: {media_path} (rel {rid}) not found in {docx_path}", file=sys.stderr) + continue + ext = Path(media_path).suffix.lstrip(".").lower() or "bin" + if ext == "jpg": + ext = "jpeg" + out_name = f"img{idx:03d}.{ext}" + img_dir.mkdir(parents=True, exist_ok=True) + (img_dir / out_name).write_bytes(z.read(media_path)) + written.append(out_name) + return written + + +def _rewrite_image_refs(markdown_text: str, image_files) -> str: + """Replace MarkItDown's truncated base64 image placeholders with real + relative img/imgNNN.ext references, in left-to-right order. If the + counts don't match (unexpected), the placeholders are left as-is rather + than risk mismatched references.""" + matches = list(_PLACEHOLDER_IMAGE_RE.finditer(markdown_text)) + if not matches: + return markdown_text + if len(matches) != len(image_files): + print( + f"WARNING: found {len(matches)} image placeholder(s) in markdown but " + f"extracted {len(image_files)} image file(s); leaving placeholders " + "unreplaced to avoid mismatched references.", + file=sys.stderr, + ) + return markdown_text + + counter = {"i": 0} + + def _replace(m): + name = image_files[counter["i"]] + counter["i"] += 1 + return f"![{m.group(1)}](img/{name})" + + return _PLACEHOLDER_IMAGE_RE.sub(_replace, markdown_text) + + +def convert_one(md, source: Path, dest_dir: Path) -> bool: + """Convert a single .docx file to a "/" folder containing the + Markdown file and an "img/" folder of extracted images. Returns True on + success.""" + try: + result = md.convert(str(source)) + except ImportError as exc: + print( + f"ERROR: A required dependency for converting '{source.name}' is not installed.\n" + f" {exc}\n" + "See references/setup.md for this skill, or run:\n" + ' pip install "markitdown[docx]"', + file=sys.stderr, + ) + sys.exit(EXIT_MISSING_DEPENDENCY) + except Exception as exc: # noqa: BLE001 - surface any conversion error + print(f"FAILED {source} -> {exc}", file=sys.stderr) + return False + + try: + if dest_dir.exists(): + shutil.rmtree(dest_dir) + dest_dir.mkdir(parents=True, exist_ok=True) + image_files = _extract_images(source, dest_dir / "img") + text = _rewrite_image_refs(result.text_content, image_files) + md_path = dest_dir / f"{source.stem}.md" + md_path.write_text(text, encoding="utf-8") + except OSError as exc: + print(f"FAILED {source} -> could not write output in {dest_dir}: {exc}", file=sys.stderr) + return False + + img_note = f", {len(image_files)} image(s)" if image_files else "" + print(f"OK {source} -> {md_path}{img_note}") + return True + + +def find_docx_files(root: Path, recursive: bool): + """Return (docx_files, skipped_count) for files directly/recursively under root.""" + pattern_iter = root.rglob("*") if recursive else root.iterdir() + docx_files = [] + skipped = 0 + for entry in pattern_iter: + if entry.is_dir(): + continue + if entry.suffix.lower() == ".docx": + docx_files.append(entry) + else: + skipped += 1 + return sorted(docx_files), skipped + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("input", help="Path to a .docx file or a directory of .docx files") + parser.add_argument( + "-o", "--output", + help=( + "Destination folder for the '/' output (single-file mode), " + "or parent directory under which each '/' output folder is " + "created (batch mode)" + ), + ) + parser.add_argument( + "--recursive", action="store_true", + help="When input is a directory, also search subdirectories", + ) + args = parser.parse_args() + + #MarkItDown = _import_markitdown() + #md = MarkItDown() + + source = Path(args.input) + if not source.exists(): + print(f"ERROR: Input path not found: {source}", file=sys.stderr) + return EXIT_INVALID_INPUT + + if source.is_file() and source.suffix.lower() != ".docx": + print( + f"ERROR: Unsupported file type '{source.suffix}'. " + "This skill only converts .docx files.", + file=sys.stderr, + ) + return EXIT_INVALID_INPUT + + MarkItDown = _import_markitdown() + md = MarkItDown() + + if source.is_file(): + dest_dir = Path(args.output) if args.output else source.parent / source.stem + return EXIT_OK if convert_one(md, source, dest_dir) else EXIT_CONVERSION_FAILED + + # Directory / batch mode + docx_files, skipped = find_docx_files(source, args.recursive) + if skipped: + print(f"NOTE: skipped {skipped} non-.docx file(s) in {source}") + if not docx_files: + print(f"ERROR: No .docx files found under {source}", file=sys.stderr) + return EXIT_INVALID_INPUT + + out_dir = Path(args.output) if args.output else None + success_count = 0 + for docx_path in docx_files: + if out_dir is not None: + rel = docx_path.relative_to(source) + dest_dir = out_dir / rel.parent / docx_path.stem + else: + dest_dir = docx_path.parent / docx_path.stem + if convert_one(md, docx_path, dest_dir): + success_count += 1 + + total = len(docx_files) + print(f"\nConverted {success_count}/{total} file(s).") + return EXIT_OK if success_count == total else EXIT_CONVERSION_FAILED + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/skills/convert-word-to-md/scripts/requirements.txt b/skills/convert-word-to-md/scripts/requirements.txt new file mode 100644 index 00000000..47a07c70 --- /dev/null +++ b/skills/convert-word-to-md/scripts/requirements.txt @@ -0,0 +1 @@ +markitdown[docx]>=0.1.0 From 191309165e54ae1aab978fbdc01c727bce511694 Mon Sep 17 00:00:00 2001 From: "Alex Yang [MSFT]" Date: Wed, 15 Jul 2026 17:29:48 -0700 Subject: [PATCH 09/25] =?UTF-8?q?Add=20Azure=20Connector=20Namespaces=20ca?= =?UTF-8?q?nvas=20extension=20=F0=9F=A4=96=F0=9F=A4=96=F0=9F=A4=96=20(#225?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add MCP Connectors (connector-namespaces) canvas extension A Copilot CLI canvas extension for browsing and adding MCP connectors from an Azure Connector Namespace into a Copilot session. Sign-in is dependency-free (OAuth 2.0 auth-code + PKCE via the Azure CLI public client, loopback redirect); network access is restricted to the public Azure Resource Manager endpoint. MIT licensed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update Connector Namespaces canvas extension Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Harden Connector Namespaces canvas extension Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Sanitize connector icon brand colors Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Connector Namespace playground actions Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Replace sandbox skill with native tool Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Clarify connector disconnect action Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Color disconnect action red Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Add connector extension plugin manifest Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Address connector canvas review feedback Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Remove legacy connector canvas manifest Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Address remaining connector review feedback Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Harden connector review fixes Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Harden connector convergence Address the latest connector review batch across config persistence, executable trust, reauthentication, JSON-RPC transport, smoke safety, and accessibility. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Use native HTTP connector configs Persist Connector Namespace MCP servers as direct HTTPS entries with API-key headers, remove the stdio unwrap proxy, and exercise the native Streamable HTTP path in smoke coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf * Secure persisted connector state Create the Connector Namespace artifacts directory and saved gateway config with private permissions, and align the reduced-motion regression notes with the static fallback behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a986299f-86be-46c3-9562-cbf7d25174cf --------- Co-authored-by: Alex Yang Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../.github/plugin/plugin.json | 19 + extensions/connector-namespaces/LICENSE | 21 + extensions/connector-namespaces/README.md | 85 + extensions/connector-namespaces/armClient.mjs | 444 +++++ .../assets/preview-connected.png | Bin 0 -> 22914 bytes .../connector-namespaces/assets/preview.png | Bin 0 -> 32685 bytes extensions/connector-namespaces/catalog.mjs | 70 + .../connector-namespaces/categories.mjs | 15 + .../copilot-extension.json | 4 + .../connector-namespaces/createPage.mjs | 403 +++++ extensions/connector-namespaces/extension.mjs | 101 ++ extensions/connector-namespaces/install.mjs | 1007 +++++++++++ .../install.reauth.test.mjs | 558 ++++++ .../connector-namespaces/install.test.mjs | 253 +++ .../mcp-http-probe.test.mjs | 58 + extensions/connector-namespaces/package.json | 19 + .../connector-namespaces/preview/.gitignore | 2 + .../connector-namespaces/preview/README.md | 112 ++ .../connector-namespaces/preview/fixtures.mjs | 117 ++ .../connector-namespaces/preview/server.mjs | 151 ++ .../connector-namespaces/preview/shots.mjs | 96 + extensions/connector-namespaces/renderer.mjs | 1563 +++++++++++++++++ .../connector-namespaces/renderer.test.mjs | 393 +++++ .../review-fixes.test.mjs | 139 ++ extensions/connector-namespaces/sandbox.mjs | 49 + .../connector-namespaces/sandbox.test.mjs | 54 + extensions/connector-namespaces/server.mjs | 616 +++++++ .../connector-namespaces/server.test.mjs | 215 +++ extensions/connector-namespaces/state.mjs | 115 ++ .../connector-namespaces/state.test.mjs | 32 + .../connector-namespaces/test/README.md | 128 ++ .../connector-namespaces/test/mcp-probe.mjs | 173 ++ .../connector-namespaces/test/safe-tools.mjs | 168 ++ .../test/safe-tools.test.mjs | 150 ++ .../connector-namespaces/test/smoke.mjs | 328 ++++ 35 files changed, 7658 insertions(+) create mode 100644 extensions/connector-namespaces/.github/plugin/plugin.json create mode 100644 extensions/connector-namespaces/LICENSE create mode 100644 extensions/connector-namespaces/README.md create mode 100644 extensions/connector-namespaces/armClient.mjs create mode 100644 extensions/connector-namespaces/assets/preview-connected.png create mode 100644 extensions/connector-namespaces/assets/preview.png create mode 100644 extensions/connector-namespaces/catalog.mjs create mode 100644 extensions/connector-namespaces/categories.mjs create mode 100644 extensions/connector-namespaces/copilot-extension.json create mode 100644 extensions/connector-namespaces/createPage.mjs create mode 100644 extensions/connector-namespaces/extension.mjs create mode 100644 extensions/connector-namespaces/install.mjs create mode 100644 extensions/connector-namespaces/install.reauth.test.mjs create mode 100644 extensions/connector-namespaces/install.test.mjs create mode 100644 extensions/connector-namespaces/mcp-http-probe.test.mjs create mode 100644 extensions/connector-namespaces/package.json create mode 100644 extensions/connector-namespaces/preview/.gitignore create mode 100644 extensions/connector-namespaces/preview/README.md create mode 100644 extensions/connector-namespaces/preview/fixtures.mjs create mode 100644 extensions/connector-namespaces/preview/server.mjs create mode 100644 extensions/connector-namespaces/preview/shots.mjs create mode 100644 extensions/connector-namespaces/renderer.mjs create mode 100644 extensions/connector-namespaces/renderer.test.mjs create mode 100644 extensions/connector-namespaces/review-fixes.test.mjs create mode 100644 extensions/connector-namespaces/sandbox.mjs create mode 100644 extensions/connector-namespaces/sandbox.test.mjs create mode 100644 extensions/connector-namespaces/server.mjs create mode 100644 extensions/connector-namespaces/server.test.mjs create mode 100644 extensions/connector-namespaces/state.mjs create mode 100644 extensions/connector-namespaces/state.test.mjs create mode 100644 extensions/connector-namespaces/test/README.md create mode 100644 extensions/connector-namespaces/test/mcp-probe.mjs create mode 100644 extensions/connector-namespaces/test/safe-tools.mjs create mode 100644 extensions/connector-namespaces/test/safe-tools.test.mjs create mode 100644 extensions/connector-namespaces/test/smoke.mjs diff --git a/extensions/connector-namespaces/.github/plugin/plugin.json b/extensions/connector-namespaces/.github/plugin/plugin.json new file mode 100644 index 00000000..18b8c116 --- /dev/null +++ b/extensions/connector-namespaces/.github/plugin/plugin.json @@ -0,0 +1,19 @@ +{ + "name": "connector-namespaces", + "description": "Browse, connect, and open MCP connectors from an Azure Connector Namespace.", + "version": "1.1.0", + "author": { + "name": "Alex Yang", + "url": "https://github.com/alexyaang" + }, + "keywords": [ + "azure", + "connector-namespace", + "mcp", + "mcp-connectors", + "model-context-protocol", + "tool-discovery" + ], + "logo": "assets/preview.png", + "extensions": "." +} diff --git a/extensions/connector-namespaces/LICENSE b/extensions/connector-namespaces/LICENSE new file mode 100644 index 00000000..22aed37e --- /dev/null +++ b/extensions/connector-namespaces/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/extensions/connector-namespaces/README.md b/extensions/connector-namespaces/README.md new file mode 100644 index 00000000..f7346247 --- /dev/null +++ b/extensions/connector-namespaces/README.md @@ -0,0 +1,85 @@ +# MCP Connectors — Copilot CLI Canvas Extension + +A GitHub Copilot CLI **canvas extension** that lets you browse and add MCP +connectors from an Azure **Connector Namespace** directly inside a Copilot CLI +session. Search by name or category, sign in to a connector, then restart the +session to make its tools available to the agent. + +> The canvas talks to public Azure Resource Manager (`management.azure.com`) +> using the signed-in Azure CLI account. The extension does not register its own +> Entra application or persist Azure credentials. + +## Prerequisites + +- **GitHub Copilot CLI** (the host that loads canvas extensions). +- **Azure CLI**, signed in with `az login`. The extension asks Azure CLI for a + short-lived ARM access token and refreshes it through the same broker. +- **An Azure subscription with a Connector Namespace** — resource type + `Microsoft.Web/connectorGateways` (API version `2026-05-01-preview`). This is + a preview resource provider; you must have access to it for the catalog to + load. Without it the extension installs fine but has nothing to show. + +## Install + +Install it from the public Awesome Copilot repository: + +``` +install_extension https://github.com/github/awesome-copilot/tree/main/extensions/connector-namespaces +``` + +For a reproducible install, swap `main` for a reviewed commit SHA from this +repository. + +The destination **scope** is chosen at install time: + +- **user** (default) — installs globally for you at + `$COPILOT_HOME/extensions/connector-namespaces/`. The usual choice for a + personal tool. +- **project** — installs into the current repo. +- **session** — scoped to a single CLI session. + +## Usage + +1. Open the **MCP Connectors** canvas from Copilot CLI. +2. The canvas loads subscriptions from your signed-in Azure CLI account. Pick an + Azure **subscription** and a **Connector Namespace**. The choice is saved for + future sessions (change it any time via **Change namespace**). +3. Browse or filter the connector catalog, then **Connect**. A browser tab + opens for Microsoft sign-in; complete it and the canvas updates on its own. +4. Connected connectors move into **My MCPs**. Use **Sandbox** on a tile to open + that server directly in the namespace MCP playground. +5. Restart the Copilot CLI session so the agent can load the connected tools. + +The extension registers the native `connector_namespaces_open_playground` tool, +so GitHub Copilot can open a named connector from **My MCPs** without installing +an additional Agent Skill. + +## How it works + +- `extension.mjs` — entry point; declares the canvas, `open_sandbox` action, and + native `connector_namespaces_open_playground` tool. +- `server.mjs` — a loopback HTTP server (bound to `127.0.0.1` only) that serves + the canvas UI and the JSON/OAuth endpoints the iframe calls. +- `armClient.mjs` — thin ARM client (token brokered by Azure CLI, public ARM + base only, SSRF-guarded path segments). +- `catalog.mjs` — fetches and curates the connector list for a namespace. +- `install.mjs` — the connect/install pipeline (managed-API connection, consent, + rollback on cancel, and native HTTPS MCP config registration). +- `renderer.mjs` — all canvas HTML/CSS/client JS. +- `sandbox.mjs` — builds namespace playground links and resolves named My MCPs. +- `state.mjs` — saved namespace and connector state. + +## Privacy & security + +- ARM tokens come from `az account get-access-token`, stay in process memory, + and are never logged or written by the extension. Azure CLI owns sign-in and + credential storage. +- All servers bind to loopback (`127.0.0.1`) and are never exposed externally. +- ARM requests go only to `https://management.azure.com/`; path segments are + validated to prevent SSRF-style host smuggling. +- The minted gateway API key is stored in the selected Copilot MCP config and + sent to its validated HTTPS endpoint as the `X-API-Key` header. + +## License + +[MIT](./LICENSE) © Microsoft Corporation. diff --git a/extensions/connector-namespaces/armClient.mjs b/extensions/connector-namespaces/armClient.mjs new file mode 100644 index 00000000..dc0f9fc4 --- /dev/null +++ b/extensions/connector-namespaces/armClient.mjs @@ -0,0 +1,444 @@ +// ARM API client — fetches real connector data with Azure CLI credentials. + +import { exec, execFile } from "node:child_process"; +import { constants as fsConstants, promises as fs } from "node:fs"; +import { homedir, platform } from "node:os"; +import { basename, delimiter, dirname, isAbsolute, join, resolve, sep } from "node:path"; +import { promisify } from "node:util"; + +const API_VERSION = "2026-05-01-preview"; +const RG_API_VERSION = "2021-04-01"; +const MSI_API_VERSION = "2023-01-31"; +const SUBS_API_VERSION = "2020-01-01"; + +const execFileAsync = promisify(execFile); +const execAsync = promisify(exec); +const ARM_RESOURCE = "https://management.azure.com/"; +const EXPIRY_SKEW_MS = 5 * 60 * 1000; +const LEGACY_AUTH_CACHE = join( + process.env.COPILOT_HOME || join(homedir(), ".copilot"), + "extensions", + "connector-namespaces", + "artifacts", + "auth-cache.json", +); + +let s_auth = null; // { token, expiresAt } +let s_authInFlight = null; +let s_legacyAuthCacheRemoved = false; + +export function parseAzureCliToken(stdout) { + let data; + try { + data = JSON.parse(stdout); + } catch { + throw new Error("Azure CLI returned invalid token JSON."); + } + const token = data?.accessToken; + const epochSeconds = Number(data?.expires_on); + const expiresAt = Number.isFinite(epochSeconds) && epochSeconds > 0 + ? epochSeconds * 1000 + : Date.parse(data?.expiresOn); + if (typeof token !== "string" || token.length === 0 || !Number.isFinite(expiresAt)) { + throw new Error("Azure CLI returned an incomplete ARM token."); + } + return { token, expiresAt }; +} + +async function removeLegacyAuthCache() { + if (s_legacyAuthCacheRemoved) return; + try { + await fs.unlink(LEGACY_AUTH_CACHE); + } catch (error) { + if (error?.code !== "ENOENT") { + throw new Error(`Could not remove the legacy connector credential cache at ${LEGACY_AUTH_CACHE}: ${error.message}`); + } + } + s_legacyAuthCacheRemoved = true; +} + +function windowsSystemExecutable(name) { + const systemRoot = process.env.SystemRoot; + if (systemRoot && isAbsolute(systemRoot)) return join(systemRoot, "System32", name); + throw new Error(`Could not resolve the Windows system executable ${name}.`); +} + +async function trustedExecutablePath(path, expectedName, workspaceRoot = process.cwd()) { + if (!isAbsolute(path) || /["\r\n]/.test(path)) return null; + let candidate; + let workspace; + try { + [candidate, workspace] = await Promise.all([ + fs.realpath(path), + fs.realpath(workspaceRoot), + ]); + if (!(await fs.stat(candidate)).isFile()) return null; + if (platform() !== "win32") await fs.access(candidate, fsConstants.X_OK); + } catch { + return null; + } + const insensitive = platform() === "win32"; + const normalize = (value) => insensitive ? value.toLowerCase() : value; + const normalizedCandidate = normalize(resolve(candidate)); + const normalizedWorkspace = normalize(resolve(workspace)); + const workspacePrefix = normalizedWorkspace.endsWith(sep) + ? normalizedWorkspace + : `${normalizedWorkspace}${sep}`; + if ( + normalize(basename(candidate)) !== normalize(expectedName) || + normalizedCandidate === normalizedWorkspace || + normalizedCandidate.startsWith(workspacePrefix) + ) return null; + return candidate; +} + +async function resolveWindowsAzureCli() { + const trustedCwd = homedir(); + const { stdout } = await execFileAsync( + windowsSystemExecutable("where.exe"), + ["az.cmd"], + { cwd: trustedCwd, encoding: "utf8", windowsHide: true, timeout: 10_000, maxBuffer: 64 * 1024 }, + ); + for (const path of stdout.split(/\r?\n/).map((line) => line.trim())) { + if (/[%]/.test(path)) continue; + const candidate = await trustedExecutablePath(path, "az.cmd"); + if (candidate) return candidate; + } + throw new Error("Azure CLI was not found outside the current workspace."); +} + +export async function resolvePosixAzureCli(pathValue = process.env.PATH || "", workspaceRoot = process.cwd()) { + for (const directory of pathValue.split(delimiter)) { + const candidate = await trustedExecutablePath(resolve(directory || workspaceRoot, "az"), "az", workspaceRoot); + if (candidate) return candidate; + } + throw new Error("Azure CLI was not found outside the current workspace."); +} + +export async function resolveSystemExecutable(name, workspaceRoot = process.cwd()) { + const candidates = platform() === "win32" + ? [windowsSystemExecutable(name)] + : [join("/usr/bin", name), join("/bin", name), join("/usr/local/bin", name)]; + for (const path of candidates) { + const candidate = await trustedExecutablePath(path, name, workspaceRoot); + if (candidate) return candidate; + } + throw new Error(`Could not resolve the trusted system executable ${name}.`); +} + +async function acquireToken() { + await removeLegacyAuthCache(); + try { + const windows = platform() === "win32"; + const azureCli = windows ? await resolveWindowsAzureCli() : await resolvePosixAzureCli(); + const options = { cwd: homedir(), encoding: "utf8", windowsHide: true, timeout: 60_000, maxBuffer: 1024 * 1024 }; + const { stdout } = windows + ? await execAsync( + `"${azureCli}" account get-access-token --resource https://management.azure.com/ --output json --only-show-errors`, + { ...options, shell: windowsSystemExecutable("cmd.exe") }, + ) + : await execFileAsync( + azureCli, + ["account", "get-access-token", "--resource", ARM_RESOURCE, "--output", "json", "--only-show-errors"], + options, + ); + s_auth = parseAzureCliToken(stdout); + return s_auth.token; + } catch (error) { + const detail = String(error?.stderr || error?.message || "").trim(); + throw new Error( + `Azure CLI authentication failed. Install Azure CLI and run "az login" before opening the canvas.${detail ? ` ${detail}` : ""}`, + ); + } +} + +export async function getToken() { + if (s_auth && s_auth.expiresAt - EXPIRY_SKEW_MS > Date.now()) return s_auth.token; + if (s_authInFlight) return s_authInFlight; + s_authInFlight = acquireToken().finally(() => { + s_authInFlight = null; + }); + return s_authInFlight; +} + +/** + * List all enabled Azure subscriptions the user has access to. + */ +// The set of enabled subscriptions is stable for a session, so cache it — the +// first /setup pays the ARM round-trip once and every "Change namespace" +// afterwards serves from memory. +let s_subsCache = null; // { subs, expiresAt } +const SUBS_TTL_MS = 30 * 60 * 1000; + +export async function listSubscriptions() { + const now = Date.now(); + if (s_subsCache && s_subsCache.expiresAt > now) return s_subsCache.subs; + const token = await getToken(); + const url = `https://management.azure.com/subscriptions?api-version=${SUBS_API_VERSION}`; + const raw = await paginateAll(url, token); + const subs = raw + .filter((s) => s.state === "Enabled") + .map((s) => ({ id: s.subscriptionId, name: s.displayName, tenantId: s.tenantId, state: s.state })); + s_subsCache = { subs, expiresAt: now + SUBS_TTL_MS }; + return subs; +} + +// ARM resource identifiers are a restricted charset (letters, digits and a few +// punctuation chars). Validating each path segment against this allowlist before +// it enters a URL rejects anything containing "/", "?", "#", "@" or ":" — the +// characters that could otherwise alter the request path or redirect the host — +// and acts as a taint barrier so config/file-derived names cannot reach fetch +// unvalidated. +const ARM_SEGMENT = /^[A-Za-z0-9._()-]{1,256}$/; + +export function armSegment(value) { + const s = String(value); + if (s === "." || s === ".." || !ARM_SEGMENT.test(s)) { + throw new Error(`Invalid ARM resource identifier: ${s}`); + } + return s; +} + +function buildBaseUrl(subscriptionId, resourceGroup, gatewayName) { + return `https://management.azure.com/subscriptions/${armSegment(subscriptionId)}/resourceGroups/${armSegment(resourceGroup)}/providers/Microsoft.Web/connectorGateways/${armSegment(gatewayName)}`; +} + +// Hard host allowlist: every request this client makes targets ARM and only +// ARM. The trailing slash matters — it blocks suffix/userinfo bypasses such as +// "https://management.azure.com.evil.com/" and "https://management.azure.com@evil.com/", +// neither of which starts with this exact prefix. This guards the paginated +// nextLink (a server-supplied value) which does not pass through armSegment. +const ARM_BASE = "https://management.azure.com/"; + +// Returns the URL only if it targets ARM, otherwise throws. Used by callers +// (e.g. install.mjs) that build ARM URLs before handing them here. +export function assertArmHost(rawUrl) { + const url = String(rawUrl); + if (!url.startsWith(ARM_BASE)) { + throw new Error(`Refusing to call non-ARM URL: ${url}`); + } + return url; +} + +async function armFetch(url, token) { + // Guard the exact value handed to fetch so a tainted path segment or a + // server-supplied nextLink can never redirect the call off ARM. + if (!url.startsWith(ARM_BASE)) { + throw new Error(`Refusing to call non-ARM URL: ${url}`); + } + const res = await fetch(url, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + if (!res.ok) { + const body = await res.text(); + throw new Error(`ARM ${res.status}: ${body.slice(0, 300)}`); + } + return res.json(); +} + +// ARM normally returns distinct nextLink URLs that terminate, but a buggy or +// hostile endpoint could return a repeating/self-referential nextLink. Guard +// against an unbounded loop with a seen-set and a hard page cap. +const MAX_PAGES = 1000; + +async function paginateAll(url, token) { + const results = []; + const seen = new Set(); + let nextUrl = url; + let pages = 0; + while (nextUrl) { + if (seen.has(nextUrl) || pages >= MAX_PAGES) break; + seen.add(nextUrl); + pages++; + const data = await armFetch(nextUrl, token); + if (data.value) results.push(...data.value); + nextUrl = data.nextLink || null; + } + return results; +} + +/** + * List connector gateways in a subscription. + * Uses $top=10 and stops after the first page for speed. + * Pass fetchAll=true to paginate through everything. + */ +export async function listConnectorGateways(subscriptionId, { fetchAll = false } = {}) { + const token = await getToken(); + const url = `https://management.azure.com/subscriptions/${armSegment(subscriptionId)}/providers/Microsoft.Web/connectorGateways?api-version=${API_VERSION}&$top=10`; + if (fetchAll) return { items: await paginateAll(url, token), hasMore: false }; + // First page only — much faster + const data = await armFetch(url, token); + const items = data.value || []; + return { items, hasMore: !!data.nextLink }; +} + +/** + * List managed APIs (traditional connectors) + */ +export async function listManagedApis(subscriptionId, resourceGroup, gatewayName) { + const token = await getToken(); + const url = `${buildBaseUrl(subscriptionId, resourceGroup, gatewayName)}/managedApis?api-version=${API_VERSION}`; + return paginateAll(url, token); +} + +/** + * List managed hosted MCP servers + */ +export async function listManagedHostedMcpServers(subscriptionId, resourceGroup, gatewayName) { + const token = await getToken(); + const url = `${buildBaseUrl(subscriptionId, resourceGroup, gatewayName)}/managedHostedMcpServers?api-version=${API_VERSION}`; + return paginateAll(url, token); +} + +/** + * List managed MCP operations + */ +export async function listManagedMcpOperations(subscriptionId, resourceGroup, gatewayName) { + const token = await getToken(); + const url = `${buildBaseUrl(subscriptionId, resourceGroup, gatewayName)}/managedMcpOperations?api-version=${API_VERSION}`; + return paginateAll(url, token); +} + +// --------------------------------------------------------------------------- +// Create connector namespace (provisioning flow) +// --------------------------------------------------------------------------- + +const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); + +// Write helper (PUT/PATCH/DELETE) that mirrors armFetch's host guard but keeps +// the parsed error body so callers can surface ARM's message verbatim. +async function armWrite(method, url, body, extraHeaders = {}) { + if (!url.startsWith(ARM_BASE)) { + throw new Error(`Refusing to call non-ARM URL: ${url}`); + } + const token = await getToken(); + const headers = { Authorization: `Bearer ${token}` }; + Object.assign(headers, extraHeaders); + if (body !== undefined) headers["Content-Type"] = "application/json"; + const res = await fetch(url, { + method, + headers, + body: body !== undefined ? JSON.stringify(body) : undefined, + }); + const text = await res.text(); + let parsed; + try { parsed = text ? JSON.parse(text) : undefined; } catch { parsed = text; } + if (!res.ok) { + const msg = parsed?.error?.message ?? parsed?.message ?? text ?? `HTTP ${res.status}`; + const err = new Error(`ARM ${method} ${res.status}: ${String(msg).slice(0, 300)}`); + err.status = res.status; + throw err; + } + return parsed; +} + +/** + * List resource groups in a subscription (sorted by name). + */ +export async function listResourceGroups(subscriptionId) { + const token = await getToken(); + const url = `https://management.azure.com/subscriptions/${armSegment(subscriptionId)}/resourcegroups?api-version=${RG_API_VERSION}`; + const items = await paginateAll(url, token); + return items + .map((rg) => ({ name: rg.name, location: rg.location })) + .sort((a, b) => a.name.localeCompare(b.name)); +} + +/** + * Create a resource group without updating an existing group on a name race. + */ +export async function createResourceGroup(subscriptionId, name, location) { + const url = `https://management.azure.com/subscriptions/${armSegment(subscriptionId)}/resourcegroups/${armSegment(name)}?api-version=${RG_API_VERSION}`; + return armWrite("PUT", url, { location }, { "If-None-Match": "*" }); +} + +/** + * List user-assigned managed identities across a subscription (sorted by name). + */ +export async function listUserAssignedIdentities(subscriptionId) { + const token = await getToken(); + const url = `https://management.azure.com/subscriptions/${armSegment(subscriptionId)}/providers/Microsoft.ManagedIdentity/userAssignedIdentities?api-version=${MSI_API_VERSION}`; + const items = await paginateAll(url, token); + return items + .map((id) => { + const parts = String(id.id).split("/"); + const rgIdx = parts.findIndex((p) => p.toLowerCase() === "resourcegroups"); + return { + id: id.id, + name: id.name, + resourceGroup: rgIdx >= 0 ? parts[rgIdx + 1] || "" : "", + location: id.location || "", + }; + }) + .sort((a, b) => a.name.localeCompare(b.name)); +} + +/** + * Check whether a connector namespace name is free in the given resource group. + * Returns true when available (ARM 404), false when taken (200). Uses fetch + * directly so the 404 isn't thrown the way armFetch would. + */ +export async function checkConnectorGatewayNameAvailable(subscriptionId, resourceGroup, gatewayName) { + const token = await getToken(); + const url = `${buildBaseUrl(subscriptionId, resourceGroup, gatewayName)}?api-version=${API_VERSION}`; + const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }); + if (res.status === 404) return true; + if (res.ok) return false; + const body = await res.text(); + throw new Error(`ARM ${res.status}: ${body.slice(0, 200)}`); +} + +// ARM `identity` block — mirrors the portal's buildIdentityPayload so the PUT +// body is always explicit ({ type: "None" } when nothing is configured). +export function buildGatewayIdentity(enableSystem, userAssignedIds = []) { + const hasUser = userAssignedIds.length > 0; + const type = enableSystem && hasUser + ? "SystemAssigned,UserAssigned" + : enableSystem + ? "SystemAssigned" + : hasUser + ? "UserAssigned" + : "None"; + const identity = { type }; + if (hasUser) { + identity.userAssignedIdentities = Object.fromEntries(userAssignedIds.map((id) => [id, {}])); + } + return identity; +} + +export async function waitForProvisioning(initialResult, gatewayName, fetchLatest, { + maxPolls = 60, + delay = () => sleep(3000), +} = {}) { + let result = initialResult; + let state; + for (let poll = 0; poll <= maxPolls; poll++) { + state = result?.properties?.provisioningState; + if (state === "Succeeded") return result; + if (state === "Failed" || state === "Canceled") { + throw new Error(`Provisioning ${state} for "${gatewayName}".`); + } + if (poll === maxPolls) break; + await delay(); + result = await fetchLatest(); + } + throw new Error(`Provisioning timed out for "${gatewayName}" (last state: ${state ?? "unknown"}).`); +} + +/** + * Create a connector namespace and poll until the + * provisioningState reaches a terminal value. Throws on Failed/Canceled. + * Returns the final resource object. + */ +export async function createConnectorGateway(subscriptionId, resourceGroup, gatewayName, { location, identity }) { + const token = await getToken(); + const url = `${buildBaseUrl(subscriptionId, resourceGroup, gatewayName)}?api-version=${API_VERSION}`; + const body = { location, properties: {}, identity }; + const result = await armWrite("PUT", url, body, { "If-None-Match": "*" }); + // ~3 min ceiling (60 * 3s). A 202 may have no body, so every state other + // than explicit Succeeded enters the polling path. + return waitForProvisioning(result, gatewayName, () => armFetch(url, token)); +} diff --git a/extensions/connector-namespaces/assets/preview-connected.png b/extensions/connector-namespaces/assets/preview-connected.png new file mode 100644 index 0000000000000000000000000000000000000000..4050d8787eb92152429a831f3f0ca06176ff74d1 GIT binary patch literal 22914 zcmd43bx@nl|2CQ$lmexcV#OXxfwq+5ZY@r+;x5H4xF$&Z6e;d*1&S01l;9SixVr`t zECiQ8uplS>{@&lrnR(~D=ggTo@0|R(?7h49-n*aAwbykm;h)qLNFP0a1ONa?l@w() z0f4(>0KmQAhj;NMgeLJh0KgM~lI#a<->lswGGp!8uV=S>+?`Cx;djX&Jk9GC<^L*6 z#rjoMVBD-=D}rq&H{hj#)|zB&QUBA0Qq?kNihzaW8lJ0!(&jQ%pmdW%291+ULh^k} zW~{p6-71Thl~fB7K7k}wKBUKm*f?>GAFcZ(oJ&_fK@4Q^}q z0e~+b1M%Z}&vTa$0QeNseg^Y1-Kjf}vTCtHC) z_`<^WqOR_$>P258U0rzt`LjVM@FSy z@|qSOOSN40+Qw2va8NY*<0=SM4UzI%*yecygGxq98TFo&fEY!ut7tg>tA5#uz%V}c z=~UcK)T@jHU!)5-U%ya4xU}*vr!t39wEaktz$xbYcZQ1U8{F*y{ z#1#Mdoz`{Wa>RGv&*&gH?n&?M0NF-BiYl^UX1*ySwk`R(ZwT((47`D&5fJAD<-3-) zm4>;CjSb^gk6s1%g}fCyjz==`i=~9H|Frdl)Wy2T4+>d1*moMkv{KT={V+g2y%w() zB{({22o*oVORHY#UKCxlosX=@3Ch%+-OeU-eCs}*A%d~5E3=sASy|r9-b52W?U|cv z-}aduaVaz3Uv19LOqCQe6XW%>i?wP4Pfff80BE=+N$I0=_a*g=R)mhJn@WDhBX25b zuJ@owDbUKGrpfAEH{|8zB&BL^0rej zG7-ZoiaE|j!2nG<&3x^u=^!gtn^C64gmzA9 z?LN?!No5$$;gjNU!913<`<=Bvop$74PP+};6%f0zZa@EP;}fEZl^E(yh^^=M+sv~&?F$ALGypTzP zjkU1FM^w|(A~!-W%Xfwsz+9<}bSPoT$!{0Ao_4sWEvz zsj31Qsv%YkMWrK3jHupv-*FmU#+$(M06)Z`St&$Ovp@6UFcU4p3~7EbV8MN<$3Sv^ zO!n;t7xZ95V%w);LZ=UDK8_qS|8-n9v6xXEb4wbf)VJAch3oZGp3VF+E#Su!>e{!u zv?mUFJG-voQT)`j%}Mpv>{C5M%lQ}u7nA4Xj^NCR4ai(Zo6GEF@wugK`P`hgh%ITo z%>w{Qoa5Q?33aIxE~i!8*+HwvaTp1%xPX}r-j?6Sd0ceNX0F=8PbJv5+YXy5WJFxV zir;=Oq1~zXZ$rCytuuNF4rmY!YAvNI*s!U)){IUkAB2DPsTtvcPo@d8RQKk5lM(O= zNZE2;HXR#p$x2qPgCKuf>vd$(Wq;!wT^EUzTdEG61))7dh<+iFzgbzvkFar=Gk0zO($QfKkDuY~ zT~VBL3+zgL43)^*K`-+c2PjQjt=xw5!aa2{VmUTj@#~3GQj^~B7wqLt^_)q@SmKQ4 zz`@HHKe~8kd?rb$z6<#BHQ!&c`(np2;aJGB`LL2R@fKSHF|9n%R2p?~Pc4t~x8M5~ zzR;p!x%(5mj!#UwnQ*pu>lOV<-dBGz1)YC;^+d$HQ1y}%F&HgrRI*1DlqE9wG(U`L zvhAJ$FP=I`&YhMBJ1&jv#n8EjWZG2DiGt<8;q?nKttGr32_#Ry7WvIz97D6u_L>%` zpV0_*G-mHG(vPUdw$;8?z=z0BNraETbu3?P)s7b^faB>ziHM0koH;m-@_mo^$W#ZF z&5|3>_k-U_sRf;k!NuV6R1T)YO_k;FY=KyC!xs9>8&f`X-UL>iOF0_YMpxo(-rblf z7AhVw%c<|`dQob<)nB!*aHE8Dp-L5ZX@ zxUKu;kq#{YaG8JA3%41`^4o#bN0fP-AFc=?{k8rJu!ztL2;AdV)G#sO1OVE-24|(z z$p8RYXvNa3#T`KVEWy`%0KhASWjvM{AQ#3z<9`1!0PutUe<~gbQkMJv{WaNe>$K*1 zrb!q)Wsw)1cSvTsV8r37y2Ohn)G9EJ9nOVq2g)t#g*%)@5(3&O4?ir&4Q<5z@^BWp z@&eZG2Y_&;v|kTYbE@S@1c3(91W^ZSuYKenb220RG1JIh_l?-^uRT=ArH#XmxE%&8 zV~3u~Nd@M;2LLK~m`HzRy}jUnY5y_!9P}tQ%IWrK;luV}mBU(z>z+ne(!oH@$_!ki z*=N>kftK_=7Jh-sDQB+KrGgECZ6UQ^H+Q$KnyWd=G ziRu||PZ5E$(3p=|UJbKjRVKYO9~5*<9Jh6oo2O7lx`pZy367aDZMC40fqE8n1u{*9 zWkzGs{|b_&pa(Ndtg=Q%D5ZQOyvMGZ0I6^EM-M#cr5==n#<`uc=e~rw!LtMm<&N3p zL;{Inm&+qw$~mv8ewEc#stbu|_8(=}4;!$H>mX1`pt;$m)xM}`qm&|hh1c5=Giu-y zot12(9t9mHc%jMD$>G&?u~xz;djpZJJe}m3?=&*=MbpjEv2U|;X+A%hS+K0_Sc|62 z)OF!FXj0l-ms37a|4w7`gftm!I`_NTP|A5`f>o=B&YJOeM(o}a)bETa(|&xxT4^KU zx`XKTXM)d?(16a3RZuK3+(9LRhD}yx??z9sMRVp=jVQG$Emx$$FzW+KH@<|L3iphj)qn*_05J*bIr^xA@cfU8hKTu3-(2Gg5eXv#`CaYWiKBG3R%`lv40W6_Z+MC6@y63M7P-#1lY9Bz~9gERN$seaor&~uePeM~(66iUN zB2MGe8tk_2#)4^uZmXhRcE<0GZlutnxs)D}Gixyh`Gd5vIkwejQwqcSO;(o^a>?q> zwW9AjH+wkMA<*Fgkht|mRKu!XaB&EwVYC~2-PJm^^^2AG+;;{IzjynA%*sr;j9Nww zs9zGb_R44>7o%3CK4Fc@5YlltqYRcE8g%l97M@g|fI2-v^j~xp?Q=@FHwx zu9?##GfSUgKjYOWlTACE!_M3M%d~>LNyeB7UAf?}n)>((;J|2lv08xL$82!oX6c80 z%s2H!m}A6~+IF&Mldr!wr-VJYhO*PAvwy?ZP@svTVX7^;%l?;Gj47KZN9%m5e3a> z73s$GH)S>{ zM)72EE|?f|=02m=9g2#boDl^*rVlfG4aZ@gX{BN3PKUeM*Z&1x%+SOq{RGxpo)JYp zK~*07O1pAZNl@DLq1Wi&LAl%a6M1};-n3)hmf(D5PxSc@P2D;&(KyVKo|CP2P?W3% z14>`CINO&f8tH}aF#6<oL)noKAG5h_JNN|hU24I|iyBCnl8u;U0$;wL9PS>} zVAv!j#lMl6ADH7A|IzavrpR6@#HPY^cBlctl6u5eIC~FF%4V4 zM*8Wk1d+>ywQz>{vX8~$+8b}~4; zfGYhTY3cpwB+6Ewska;p3F)Grr7uf|)=P@k3JoijhVvE$lo_vqzYKzV+0M!^&SHau z{h(Jnt!pp1-K9%$kLJzB*Jgtq&QkQ9uPfHN2LoRXLOjrmFIu$TH9vTfz^hpxE!{Jm zk#2sXU6fxA{j7g=Pg$!sBv`f(A;qeel%#9OGLbU$ocbxfMN<%Hk^4A4;n9i&M85Mp zJ(4YSQ_fX;dm=>3>P$f{`MaVKC`j7wd%4GqRXWo!@B00)=o#sFJ#dY|0CAnf?ZO0s<=zY}^enH!6FtBR#W8oTePCMf+w@)71w)U03j6coysDu2-I?BRXNtbT zGLJViWGtpn)i*>WV}#NNeQYYp!-9(kTDg5JJGS|I0pA;&?2ezi$V9k$Ns6GG`>bB5 zm%zoI`@Oe%x{~`=AI_has&I@RHxaZ zoxvvhr~8#E%IdiJ$^z5D#j!KSV)4^5!X8IHd5CSS6S5~s13>es$!)DCJg`)gJ{u(GIgQDJ<2uB)De0YZoQ;9K>%Rs++Xp5OjIGy z+{qU~-Bp@jzCaJ>Mm!uVV;262=gtV|Lbd-F5bgg0x&5a&OC68jiYG(D!U*xd2M=gT z2<~*3>+YZiQ|ajFcDA>7y}@mDC<~K2YUlsB2~gkt@&bnAOr~>gVCLn8*45QDHX6XF z=bQxZbf17)tFh1dY*bWLheL>|TNdLYy{v^-zI9QWJp^o@zjBSD7jf_UPOhV)b9YwJ z)3c`A;%Fl~HB#Uoe5K$seAAjYm|?Y7Y*MWu!NG@tAYl6N1|CZf5~`}Iwmw_4Abo}( z!wM<{@FN4GRN!u9cuIL3C`#jhflAfT(7;5TXn%FH&HW%L**{g$J) z>+nPV8S$NVLVwU2*TGUCZqL02TRkdCLF0dO#B}SnJ6DDIU}}o!Ph@w2U2L43c+Q)d z7#K8qpw;d?Sl?=0ixESB4ZjK{s-L^+Cc2=K5vBH9nZvr!SKQW%73*yJv}`R+ zJ#;RMRhA0ssN|f(vK4Xei_to6&-8jd2ryGhr|bIL8j|5MysJxcWxWS`<-Q#A#^t6xG^dpN!7}^L4Zbn)eD@T3T9`_K+Rl z2(2kLtA5Xzes394L8qsxdX6k?ejOrwK*vjIs%<70f#~k(*+8S~rLG6fZrl%A&rY@V zu|#d|MRHm)%Eq^zA*p(hNx@qdfN>>(^78pnY|yTkftF`U;|nBq-{3bev%QuDmw$7S zdwX%#cH2sCM9X6l9QJe)I$;g2YHD?hC*tPfu-&KuqGYAGmRvhYEqkKkO+M}^OWs}` zfB*i_?+=%0%Umr#JAL~PenqtFNvVHO$S!$*>Go#1EAGkmOsgcPBhd3^`}%c^mku9; z$qH>7uMc9E@)%iAaVGt9=hasN;JRBY20vFm}>fllQUU;G*=4Qs#5H`scGVp^BkC< z2b~PxyB7Cq1MDp{SG2sEfsZVX`dS1i*=Z(}2(zvB3?>h{C)6bW=`1|_T2oUa0X}U& zW*JGod;2zv*LooL_6q$j1T41lXN^g}P2JZesDID4Xp*V=m?_<{z*@u&^XrOwer9D3 z=4P#=WM^Ew|1uFL*!ZHr$ab>!Vvx}FK}B!-3JvS8fr0*hC7;&DWW8xRih}h=Je)jJ zZ>6}UxPxb*;I{J9)_+LMi9VY^SV1*n0 z`qhF+!RK@{G>)3|Yu2>rZF=qAAlAjavu-+5wpZa>`bczb+eTdwK}^I)QHDmGV3C}O z>5c&I?=;~TWy4+_oQl(M{onv;-8k)l6<=7j3#k=?)<#-wym|#uQO{y~Bx_+8a`maO zwLW5VY(Vp3-xBk?>NP&$uY3DBmJWHq3`DlwYeQQryl{3-6+$9Hu9S%`hc9ZTjzV{R zOOoSBzw*cjYI^Iu5*p9=dZK0`u%OUkjK=w1)cqNt-xHwpT+*m7I572?Ezs*t7yKDc z!9K7;nSQtVncczgX3Lzh*`EKHw}sq?!2T%`TFNrgJ<;mQ#NL8qO4~djO4WctU1fSb=8HAc zX9a^NO@Us$Fst03A}mc|ldQKOxO&~%qlX73gKhqRYXSYcVgBq(_~4ensw{bPzP7r$ zdW!OHZcT*@)T2_$z4*yTx;~duQ{sqEBY*J~r{}M2D}yr-D_b(=QjM^y{D2Y<{~^rB zdNm|QrC0bpST9;n4C8qM+gB4zSNZz&>%OvurKLp5l;-qQ(g+0@E}9FP*qfFO?^uqg zxB&brFVEt)*90%8iTgouNsoP6vt6~+YtPWZj+TNzx1((nAduuIV3rhBFL;K)$KU$f ztI^xHoSYEX;|p}I4~Ly$QfeWRJ3BUqsW6GQLsN1~NQ|}FaM4rp)Kz0kC$PC8zkvKs{uZpjSplgvT-xVG zF;7i7n{K>%q0qNptQ%ibzUEu&d_0zLRToK-xM|1-v`L7HM13@i4$BVz8C92E%ekv` zTY1qwU+b7UM8Btwl8P2W_;z}XBh-ECrG5wIx&j~T^eR!re4jiboHqpqIb_be8C-gq z23)6-Ejy4@h|r@@2v4yj7mn0$u3kt2Lj7_{z}~a7 zXtQ?EYV=>%T>b?nL-YZ!f^9`3bYgdyYJ`ip27BuOUdmk!6e33xe)0&glUIuwuT=pP zE%|7VVK3a9nk3p#l1{i+-UJ z7=ZixN}D~=bnMzqs1&2eOpqXOeH+;5V63Q6Jp*Av8rv)|8N zEH7wE{~XTBusD#9vc8w!8ho<+XM4T#w^I0L%9Vkh@t@6PqiivJF(A zTR+WrGhfz%&-(Y??Orp)Y!L>gQ8#QPk^NfqU5m!cb670)?zi`Lb|tyFW+o=ty|u>W zcY2AKUV_@50Q}!y#6?_DGvcL0Zs90ezM|AKYxGqb|RF#n4`A;jp>-1>PZX&%&9 znWE^;%}wRhcX%u+ARzFcO7{r}2KE8-DuaTCUK@u@BJMvwz2@hia;Oc&PV3>n93E$r zJcrsl+u3o`kaTo(V7`7*x}cB2BjFAwL1KJ2ulj8aPdy%X<3Bcja(EK%0@{DDX4*5U zK-d4y!2c5^n=a~WryYN2aPUKXd)nu#z3`TGG+M}QwJSI{c%?IpxHo!K^7>>lR_bQX zxgOuCs|4NKzi;DrywMMfo|u^6vmNPUEl`M6Q&VG<3cM<-ge@#A;CpZPa>OIZq@-se zQJ65PtCiL6$Pw1wSSBg|^FyiYNh#Hguc943|IG#P+uzUgid#uY^H!J2TtK6AoL`g>r|GRio+m zoj)o*BsUA()4Fr?5I;jC5lRIG^3l9BB-HPWH(?*&kvx2OxS_WzA44CwWn~TSytJl` zehUD6>;5N$e}P!44fbvP;y5)FNl&r*+SV?c>8O)|OpL&Ak*bbsIwe}%uZxCB>S}`A zw(Sf2RW$sc;l9&o@bgBuG8m+kQQn_kjPv^a;+FBOX;U#u0+wGP7GUPzd*rk`ba4bU zYHo9=f6lV1|@3TNJjbwzm^rKLT=6gp;B2}NEph%LZZ#JUN^yoEaz|0wDu zcdk)nTi2)_czAw=V*`gNn>mg)gxGyfP33@li57qT3P4ccLe*7_>WNE)|JeaCfw z0$tHXX;rDBDfV;@*F1Y-K=^Pf6VsL_H)G1#VT3q7MD&L4RrYEW?pO(%P4zlg{o12> zYsO1P0N@4?48{%IT;qD9>FQlqq|vh$UZN(xzURRDCAMavOFyQ^dmaG>y~StoEMbFz z|6V|g^M?zMN9KR--=kkm3d^W5U^exHcvA3Ayc$YQL8RKVyf-XB+-@u$bBG>%E?yGa zJpsK%53g>-GZxJZEVJ!rRPKGfLkVbar+NFeptcqp8+5g{=`OVDyIWR2hvtm~jwoYhAhe7-LGXM7i(|^$vn0B`d4642TJ>DKfz>1I3J%+D}#9fUWTs!ReAN^PK zU2xL9vCJO0*L!h{#t$HHEm~+|6yM8_7nwHm?+0xz7aKkB(O(L|wuQaaD3I?5P(FKx z*Ztd<|54DiLWZi)31+Ik+KBvXL4s|Zr{J6Y|EVA83$%h3zJ&;8 zFBLh~hTBA{RS*Kq`7TFqFv`4Rjc7=~~pMhep$ z-6pnS_=b4yUQ|=cpnI0w-&|!(_SMo*R}B>PL(@aRhFilwyg3#U9e@ZXpIR0m<;rD0vI2nDqH)pWlpM7c_ zEeRcEfb%<<^$aD{*LhgI`(aImq+6$9)K}Rh6rD|!Dcy$m6fOh;3n}o~nS6FU?&C?9 z!P-LZrdDwmUHNtPF8ABOj}8i5&xITfTk+TL2K>LukZ~wPLriQCaNwT!*J4 z72o61?bkvsoGkUzEP;RdJZ_lifdbv58n=fKg%^3=ICaxk`{HjjjEv}bB&{Q0a~dCC zs;EB{bCjf`vT-e+E`FCqYgxj1)iz(5d&HgbnNQELZYB(35O4D_{3-i$EhaxFU5hzx z2)w|vH_?df#Q(&b_Mb~7=X}y~{G7i$FA3|k;w>yHYT}AlZ^J@dh$?kbb@*vi?TKR8 znI|do>0Yw^%GeEUAW6WSG zmwJ|P)vsS$on%r;>WPVos7a~Yi_zQoQ9*AjaATdLMr$aK<&O{vmps8vTemXG zxN1AdYX%E92L*Y#=8JoUnp^&!Ha0!{qdP9vc9V-Xz1NEm=YOpw=&4^?(yUAmVg?2V zmYRJ=GX%;C3*{tLm6YPu)pNw>b4As5Z%W=+H_<<>>gubCi>=FfGAX8;viDjnGc8V7 zBa4QKdgjwn6MES^(S*4=r7u1`4kYqYtFd*CDr>?!n5z0o&zLatfQ0k&M7+{jA@N(6 z(s|xZdQQ!0i7^@5K4raABsfI{97Jd!j7Gn=>O2e@=V}d9mc!=$9p0dihp<(PtIgw! zbM>H0Evd=Sp4H7CiXeYb*YDC+cN&&~091H>MD=T;*OL?SVcDGU8B2u_DwV)AZV#mb z`h zv{_*}C?)o^Hw_^%&0y@e7Izky@-IZX7|;s-uy8tD&>tc{ILXQRsw%=YZ-0`}3z7lD3X8jnkmI)!OZx z(kgutH!?g;f7f8d*dVRBAiq9fyF7I_l>AR6ykr2!C3OQUCN(tjtdsw{PVv6Qing;P zni~4Eqo>&}WP)}zmk;K?b&4TzgM9P%ema&PI|Bb&@+f82>$Ojq3n=!@L|GR=<*$OC z6p<l=p zH8%jXK0>$54ticIh)15w9J8>n&V8nrp&`V#?@{(L3C(e0Z*o&f;o1GQxI_+;`2 zUD2Jy4gY1Z7cbvwzEX|!^^*9mrv^2Q#QtIa9;5pC;2)qE~Ity@^g2$@13aLR{%6f z9@frDs-`su&cg2HHtd4!8|x0YOfW|k#og}*=AZ|Ok8zLcDs$=Pm5=(OI3Ez6wkFZO zu82^fQx)=7rep4?8k}VGb>5JY5b{9qDIudM9u)?z!HRoBP7It@g={2z;KRVt^*e)| zDTG{jd+$Av@MRp#ZEd^euxNY2XV4)-PEo~O5vjU1Z6|7ag3yS3m>!p5lTl?MV{-Jb zt%G=KRMr#5r!+KA+3qQ*j$#9XEIU@M2EmEw@}nBvn4f*H=nCa;VeId2N9suhaAqRD zr3j=jswn=WnTPE6adUD#S;m&zt$%uS0p^D+t|!bQyvF>=8;G+{F^AzrP5H?j9<>ZE zz8*UgMe8KYIY-8ru?&&K*%JdZC%nV>ckjlc=;BPk%kD$6Bjn?XrQ1L3z3O)ATzdZA z@;9RmbWf=flFSxqZNF!9=ofK+9+d66>pwHqqorZs`-3#py86S;u1=zUh4PV~%^`_t z^lPvyUBKO#nb!BWRq?1V`lY^Qc|MXv4>~(bT`YC@C2BwyP(7n?+=|Y>sRNqX2iOg; z^jFE>ru0-w`dyFN5(cMyO?dQ^%diwzDHPQ3SOu^X6d4(f7_83JWpm8U2< zfp~kiwId;s&GdOdlLvksS@ACY>`i+%Qr#`SP85E|Pxwi@D;qm|^D1 zAU8k6-meZy_s+or1$Do-M@DWq$gyS{!_~#@)oOLMExi|#>&7068dVSc91r&6eO*$1 z*ybZhx4}A`?l#$fZv(y&AogRGOU(55eJOWzc}eKL!p;#Z;Jv!%-;@=iM#=Ukk`a*LPJ+rAGN##H73oG!R8z zqYd3Lb6}gKHfG)TC;!a_94&fS^sLSoDMjinW#TsB7Jq^j-Cp_Z8KIc@cvF`wGwN5j zkWCqW1+P~&J&s+#MFz3C7xpt3tRJV*UCTtDNirOiZ$e*-zmm>+z2r!^?_fv9 z%z4vG%gTmrJaRLQhxf(*n`k7s6b|^-KAyVjMNCCMWDIlKm#DHQvvE<+nHp#KEO`!p z;AqusmXg+j%_-^QXGTyp#*VnLey#7Ev?7$zUtaSyPmC)@dGHe#U1=M(vMNxR8@q=3tT*h~UeWezl4jZzus zbp4L0XEM34i1y{-{;)6XE-gRI*C?=+J`dfiYq>s!Gn!==_miQwhyOg|VLKn%l8=Sg z)EUaP8Naz*9)|3BMd$Fgf`4qiGCIQLPeAKzDca&+UjDfv1t4fe+}FR8v&7Jgyr}pd zMNG|QnnX5|Ek@12z{zxiNHIh0SLg@DPTHQQL{K{*M*1^6W``)bQZu6sXFtF()dC~( zw{eA*=azpKv0Qs^=6sghzp7_-((VmW=^+*K1qGkx)XiJ~lXm%mit_iHKKAEC)gwTT zXb*L9UXKNth4%0Q&*39#cxiuGb>9T@=Owa9ClSQpu14%tIb(+7;C_M53sJ8Np&k{I zhY^#w2ZPpV_36m*qN)!af4HzlN8~f5P|!+tH5MK1hNPK1lAu=5ArkV+@GnbUie4z? zvsr7f&->5;9314z=>ERh&m8!N%Ly~LV%l~euqo{=*tgM!Kj@O&Hy9-qTKs3{ndJNu z<<7BiKse*$%ITJC6-0|?;;v{K+%kO~OQ$>fz4YBB@RSZE5Pv))#nUg7Hz9hwJGYU) zyDPN4KqZiy%(Ts5!n~I#FP0n=bq#wmG8E7F&d9+dd-qNHKNT6d)0F}Za3ST@x2^~xYuTU2Z;URGX0E0xUQ-y9_z5Y;~392M>I zE~fmo1W5PvbFhkHasbuFw}aL0X%(^&<)rip8L64F1BT%&{?~p- z-@Lfm%7pk16x@3#r|{ndTEJ6%f{&q*OE`uB`nhdSzel? zToe_4`Fnpz&PWQ~>jx=bJK^<6|P>p zUCw#Ub&_MgFpIvQVsi4oDE_vI>z?JCcf#d9hK9}=lFSar)^Blwq+mbpwu=#b>&UG9 zX-NN=L6qNncTRFL)YYG&7zUWdD0RArs~tiZJ;~1o8JEIjdBNSCMD>4xwUK7 z>?XBsw~_guPbWzHp>c9^(~g$csyCDmC@UuiF>N&@k(^x%ZeEy?x^?Wtu^Zi!Aw~Lm zp0~jmpGfK8MFKCpW%6P~>;SJNP(OQCu3shn>U6eJZLlhNx8FyVfdac1pJ!&;l#pA+ zpE(>Wj_JdH{y=P*nZ((m2QRR%7!gHyf$$RTy!F8K#`526r1#_}LM(z;ZjBgy9ijM> zz{e%8S(8L|^^_$#Jkhy~cYe6_GWhfrOY@|Q?9qCJACwSTzzx^XXfk0iw~BT zmevdBsX-U19UffA?<&w>nwpl$%N4O`g+RuJm#VoK_2FDbi;skW z9B|ezt{OvKkgy;td`F7t8od zcox5#9^dOt%caYIY$$bAy<^`g(tJv>d1r|E0l+vtj4AMZD4kF0qF;TH`eubJNWaEz z{4a4!Wc}jbu-n2q&_zevqT5;;dOrk>y*A-r@)6~=i5z#}{42~&x z)hz3!XsB~}K`Q#@V{Ix8Sh8HEfYnNHC9lWHnQ*{R(0X6|Y6g_>)~w+>gl8hEp>hMC;bWa-IqXgCQ${p;_)`=@bq2pwxGd{z+rbFUZNA~U-= zUVzdF58U1o4%h{?Om4Oxo~jj0Lft1Uv&e@3<2It6jS^4#g}vwc5Sr69F+}>{p6=(M zbSlX3lSYaC`q*i}nEJ}f3SK-zk7QHabC@d8z+Z@53M!Bt-|tFB*w_4xHGyG&h?D)& zGg>ZxM#-_c?LBkq^Q`*=l`|E4qA+3lS&ui|N|j<+79jJD{v9o!O%#otWp502E`nnL zpK0(zi)vqK{deM{m{1N8FhUm>X$|%#oJHsq@D5|_`P6b-8I@4} z^Ri`V8n~BS9pb6Iz6;~pv>Tu&vemMg<%z`r%Y=x|WLfxRHVE`gB2~)j<%V}_h`CgD zTI4pcyhEm? z&ZflQ=(DxjDt}d84X??K`d38~NE}mj?IE*Oqb5YE0Fjjg^VX={=>%z)jMK2--WY>< zXESTER!dbkQckQ5bXo(lQkq>xWnyHKn@jgwh`COnAwtQG!)1^tcZMMAoZ}MW8m+w6 zn@<`EJEaBxv{^aGqu=C+l%L;z^*yx2|DARV1iH*5>YU}rHmpXY;&(354 zG`m(0<49dgzBwi1uymy(WBA`;ecSc$plXH9-xC=Q(ob;spECj(BVB%uvKrrXWW@CY zT=!J^q{_G(w$M=OOM%q;K*iC19tRQmlbH`(QlG^xu^tm(T%gLCSGLcJ9NZXjOoa;2 z*`VhiSX|x)Zha;*nF`ifioY@gJXS!(s=A^ znAS_aH^K%}?X87mRX}iR+Vy`FqY9X0lXUY`oa#in$`B4_KQ_b@zin9hXfnYIip7C_(Rqz4MeA&YYx zAg3=7DwD`D^0N`6YWhfPQrw&L6g{nKaw)kZ(HeD1!Sl)N+1)Rd#3138F-aR{sRi#H z+gEeHUxW5|_3l9GJJLD+hyTQ}kO5*}!r|gcBGorgBUg4@BSJ8OxE{%-WH^3ai$Xaw z{i%JP+Q=5&bbz>MY#n@OCBRpvdv+P$0{>ty!M_#Lm=KaTC<@s&%(VR3=@fod}qXVj%3rQhyd@UT-Pd@ zT?}=3>)By|Gfoel z|Kint;Ezydj)`_ocoxn4`>N#s=Xd0ZGj;If=zsmcfd8#`@lWo~{%cZPk0X2(@MCH8 z$MGcG2-u`s_FG`fFvHV3^RI-3SGjU31peuArpcS!s$n0I3j{IWP7>BH>^0d$jyR0t zS<2AIcf-`@uTLOf^F)JW)cvHDnZL?6ODghb&t8h-nbxOiohxGA7iOQ*ROkYzv1Gpq zLl*Eny-e4qt(AxA!cr{Vh7BmJJCn+nvCNH1{Uje^aw6fMi8qoHn$%|-c>vqGZS zD@~&ef#IVeVM(F*v4~`eB0~R0t&q^4B2Yso} z)eF93>PkIgrZGq6A23Y8HXqeI6OZT%r?iep{U^&AtP4s4q2hZ=&cF90sFr!`6u&hT zW#Ms3domNc0G$1tTt9w_7QKyetD>t*5-M$PE%0c3p$-c05g4ZfA{aF zoX{97q~#>?)vi}!m3-_*6H-tw)2*jR3XZ$>i_f?3OVj#k$;SN_G~I4WjxlHj ze93E{O_Z0yTMJ_)FBNTK@X+Ygv2z<5K~V6Tv*YNc6-e5%Gd@<$_f3fq=fHsCBM8^U z(((MLi_|#HuCY_pqj!Th8XMa{%3sQQ;&FDuRo550yPR^^JSE!L;ZzCsOZ!MF{7o*j z1a3-ebVHB0ak}ARF!iTgdSso|Am|OrTCo(2UxzEA-WtuwL#(0min^^1Y~=kpIZ8&s zz1EhpwH1&Z6kGQ1Dx)b#;RMA3M~Y8+B{SjgU2;D&{&qTKQ(aqE2cj|CT&j|=rl3eH z`nf$AQDDO=o5eXOVWW>HXd3$`DWXUf+=W^&@w?(BbLAlbV1|N>+{!+mp^voTfbTcs zwnlxU<4X?0r@BAWHS=X}xc%Ocbo7{)HMT5=K%~1kRUT5*hGd#?RrfVii%4zh5nCj% zMXs(ocodwz8JeCp6#t!8`;pFM6g1hHswR&(t&Cj~yTMeY*6&JM9D~XPuZMwnhmhy? z)a$&2%6q+g^+-wkiJv!QzZBWMgS3-*C9ES5PZOVbpB6yagToq_S1n$ULdD zPM%klui3Qwu+|mb)3(-G4@n=Brz{!OD_Bc#d(AifBCVB!Lw#iBXhIrSzjy2WMohdS z2{m`?HiR%Xah%j&?@*leWL@qoKn`-Nu)lRGwQmFPo8upU(Vy=4d$6YV3uF42$QT35 z1jbxOsq*cDE5?m5-Km+u`{c=ETCAw#>=}iS5aCPq_0G%H;j*Bs#N9mwC-VQJoimMQ zYhB~G+a67CCq130DdwSui1vm?$vq*4Qp!OQ8ft6|QB#KqSGA?m#_6i6p{3=77NJPg z6x8gtl#-C3F^>siEJf~4?^<`QyUv&M=`0_7-Ftu9@3Y_k`|RiU|6f17G-}6_N15FRXU2rD9qFtG!viR#wAJBo0&a6E%OiE&UA`!tOFo$tsjyAz+J;q zio_#Yo}qL>p(9SVHRN0*$Sc)@zf=k=97@>=A26JxJxg2#Kb-|TrAeyxa%zJ^QfMW9 ziKvuQMyuvC9&nv?wZpBssUOJlKJ9~ zd(y#n#|83AbfUP2>w}jNM%xQEF9cfUg9M6ZQR!7cH(Uk4+pxQORlCp{m<^XUw>WUM z=GJ3tz2}!cOFh?4)g`ngOlJ*qx3Aor3cGm_&7YWTNY+j(8RDNrI<>c~UZ}lYWCb}z zl%I&9^|N0XrhF1nvKB9Uz4pyD9FXe)0Q^FNWZ~~T=EMiR0|Jqvi|^0PN_H&c zv4BfC_E;@>#K0w@JhCHb{=1%?*J-!z+rpV#>kv%LXx#Tb3&Q9-EDs z-KPY&tp=z>S_kxeLy$l9|HOoy*agV2P)ur4_lQVf_e=LafW`Ir9Ea81+avPL#r+6q z#}Xia$j0eDsOHl<&D)Mag8kOcPHir)I;Iyg&IDYlOjdb0r~-`SB;|tD$o_}-7fYE= zg~53bL!V?`Z51qkphQ#^va(8D!T_<7C)K@97_{L?O5`o+Ehni`PaN~3&c>Q_-==)t z3+$c5^U@dl#-o4n&<$L6>p|4Xp1_I&GaK*aU^Ndh9qgzIZ`re3oNTkzd|3BiPPOo| zt(!&jhBJi<4`UIoIoW?FTk8TfD+8ruW0kH2)0}ve?t*sgt>~CVS>b!Am3X0S8-d71iB^%>%Z*jE-Ip9vL0sM z#Nk9U3!H&Ko-EEMvyjr#Oo5w6_`Ig?&NGV6r6b-MzYWSxC>90wxw=BEgti>)g$Sivk=4bz5TFsfWBNm%guqLt zLT{R7!l4{$yhptYnyQR9tKgpLO3Wx3<2&${LcQe2hybBSBI*j;?@_e72NwM>KE7E7(e`QJ^5tr+s&{#m z&@tM9N%mBEXFY|5PQao}*n3NnUO$<;RgT2yhj!&S`%-YWjh?bV3na_ z{0`cO)rQ>i@aKSLrY%)B`a}~41#60*Yu>Mj;XCkjhjfj0UqH0Rf8Zk+5UC$mO90rw zEwCLFJE}l3^R*1cs3$|^^n;l7>&HitkM^}_KHgZ(dhBBfImwcQPozs4XWvtY_s}ES z0)k(jKzn8{#dxnVdA81CR&HfMSmVGh*yKO0ATE@_N{wdiTi3pFh>C*s`KpiFYt;^) z?FBM`qc6#3Zwm#OZJ@3j>o=od^My>f){Kn0oEOtG(MC^}RTFOM>^-$tP^M|&`g$?% z&J(Xe0k^y8MKDI1QDINuPcWK3*uEtuYny*e!IZEW6(gyIG_-8$1!eD^`?cFa(Oa!u zF70KOwD9KvgdkBN#?xIV5Bha+ad9IPc8*8hjz-%@(ZXA1i!*orSWQ}&F z)Jr^*(5tLmv=ZBr1zpte%~AE%%o`}4H1T|M-SKYVk_O&D9I6$mNeNja=@QAdtH|Yb zviM8dYX^kuWG@tHu>ERR8HCnx*3HKb~!q7Djy1CE_7(g#$Vv-CBI+Rv-ZSpvYty3S@g*uIMfBN7=A z#_@)7jh-2uSr1mSFr}#lfERgjzx07=>8EG8Wu{fpuR1~OtwV4GozBSFlAu%CipUne zlj-U}Cn&lnE`%*@mwu`5+pz;c(+KRUe~u5|nYn0xX;=6M;oE&De_c>sm!49ah{*o$ z!tB7Eo71;jk2^U?BoGK_5r6?hWS{UD av{%Fg!nM3x7b6c`5wSp7n-n75@BRn&z>mZL literal 0 HcmV?d00001 diff --git a/extensions/connector-namespaces/assets/preview.png b/extensions/connector-namespaces/assets/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..259e27941361c56176347838b4c592b18bff62d3 GIT binary patch literal 32685 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 E11p{EHvj+t literal 0 HcmV?d00001 diff --git a/extensions/connector-namespaces/catalog.mjs b/extensions/connector-namespaces/catalog.mjs new file mode 100644 index 00000000..79f4165c --- /dev/null +++ b/extensions/connector-namespaces/catalog.mjs @@ -0,0 +1,70 @@ +// Catalog — fetches MCP connectors from the gateway. +// +// The gateway exposes ~1600 managed APIs (the full Logic Apps connector +// catalog). MCP servers are a small subset (~43) and there is no `kind` or +// capability flag that distinguishes them. The only reliable signal is the +// string "mcp" appearing in the API's name OR its display name — and those are +// genuinely independent signals: `workiqsharepoint` has no "mcp" in its name +// (display name "Work IQ SharePoint MCP"), while `hginsightsmcp` has "mcp" in +// its name but a display name of "HG Insights Connect". Matching either keeps +// the full set without an allowlist that has to be hand-maintained. + +import { listManagedApis } from "./armClient.mjs"; +import { CATEGORY } from "./categories.mjs"; + +function isMcpServer(api) { + const name = api.name || ""; + const displayName = api.properties?.generalInformation?.displayName || ""; + return /mcp/i.test(name) || /mcp/i.test(displayName); +} + +// Microsoft first-party servers (a365*/d365*/workiq* names, or a Microsoft- +// branded display name) group under "Microsoft"; everything else is a partner +// server. Derived rather than hardcoded so new servers categorize themselves. +function categoryFor(name, displayName) { + const n = (name || "").toLowerCase(); + const d = (displayName || "").toLowerCase(); + const isMicrosoft = + /^(a365|d365|workiq)/.test(n) || + d.startsWith("microsoft") || + d.startsWith("work iq") || + d.startsWith("dynamics 365"); + return isMicrosoft ? CATEGORY.microsoft : CATEGORY.partner; +} + +let cachedCatalog = null; +let cacheKey = null; + +export function invalidateCache() { + cachedCatalog = null; + cacheKey = null; +} + +export async function fetchCatalog(subscriptionId, resourceGroup, gatewayName) { + const key = `${subscriptionId}/${resourceGroup}/${gatewayName}`; + if (cachedCatalog && cacheKey === key) return cachedCatalog; + + const apis = await listManagedApis(subscriptionId, resourceGroup, gatewayName); + + const catalog = apis + .filter(isMcpServer) + .map((a) => { + const props = a.properties || {}; + const general = props.generalInformation || {}; + const metadata = props.metadata || {}; + const displayName = general.displayName || a.name; + return { + id: a.name, + apiName: a.name, + displayName, + description: general.description || "", + iconUri: general.iconUri || "", + brandColor: metadata.brandColor || "", + category: categoryFor(a.name, displayName), + }; + }); + + cachedCatalog = catalog; + cacheKey = key; + return catalog; +} diff --git a/extensions/connector-namespaces/categories.mjs b/extensions/connector-namespaces/categories.mjs new file mode 100644 index 00000000..57cd9592 --- /dev/null +++ b/extensions/connector-namespaces/categories.mjs @@ -0,0 +1,15 @@ +// Catalog category values. +// +// `category` is a routing key, not display text: the renderer partitions catalog +// items into the Microsoft vs Partners sections by comparing against these exact +// values (see renderCatalogHtml in renderer.mjs). Kept as a frozen enum here, +// rather than free-form strings scattered across the producer, renderer, and +// tests, so the routing contract lives in one place. +// +// Zero-dependency on purpose: renderer.mjs imports this, and renderer.test.mjs +// loads renderer.mjs as a pure string-rendering gate. Sourcing the enum from +// catalog.mjs instead would drag armClient.mjs (the ARM SDK) into that gate. +export const CATEGORY = Object.freeze({ + microsoft: "Microsoft", + partner: "Partners", +}); diff --git a/extensions/connector-namespaces/copilot-extension.json b/extensions/connector-namespaces/copilot-extension.json new file mode 100644 index 00000000..3949dbe4 --- /dev/null +++ b/extensions/connector-namespaces/copilot-extension.json @@ -0,0 +1,4 @@ +{ + "name": "connector-namespaces", + "version": 1 +} diff --git a/extensions/connector-namespaces/createPage.mjs b/extensions/connector-namespaces/createPage.mjs new file mode 100644 index 00000000..3eb86659 --- /dev/null +++ b/extensions/connector-namespaces/createPage.mjs @@ -0,0 +1,403 @@ +// Renderer for the "Create connector namespace" wizard page. Mirrors the +// portal's CreateConnectorGatewayPage: subscription -> resource group +// (existing or new) -> region -> name (live availability) -> managed identity +// (system + user-assigned) -> real ARM provisioning. + +import { baseStyles, brandMark } from "./renderer.mjs"; + +function esc(s) { + return String(s || "").replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c])); +} + +// Connector namespace regions — kept in sync with the portal's +// CONNECTOR_NAMESPACE_REGIONS list (constants.ts). +const REGIONS = [ + ["australiaeast", "Australia East"], ["brazilsouth", "Brazil South"], + ["canadacentral", "Canada Central"], ["canadaeast", "Canada East"], + ["centralindia", "Central India"], ["centralus", "Central US"], + ["eastasia", "East Asia"], ["eastus", "East US"], ["eastus2", "East US 2"], + ["francecentral", "France Central"], ["germanywestcentral", "Germany West Central"], + ["italynorth", "Italy North"], ["japaneast", "Japan East"], + ["koreacentral", "Korea Central"], ["northcentralus", "North Central US"], + ["northeurope", "North Europe"], ["norwayeast", "Norway East"], + ["polandcentral", "Poland Central"], ["southafricanorth", "South Africa North"], + ["southcentralus", "South Central US"], ["southindia", "South India"], + ["southeastasia", "Southeast Asia"], ["spaincentral", "Spain Central"], + ["swedencentral", "Sweden Central"], ["switzerlandnorth", "Switzerland North"], + ["uaenorth", "UAE North"], ["uksouth", "UK South"], + ["westcentralus", "West Central US"], ["westus2", "West US 2"], + ["westus3", "West US 3"], +]; + +const DEFAULT_REGION = "eastus"; + +export function renderCreateNamespaceHtml(subscriptions, preselectedSub = "", capabilityToken = "") { + const subOptions = subscriptions.map((s) => + `` + ).join(""); + + const regionOptions = REGIONS.map(([v, l]) => + `` + ).join(""); + + return ` + +Create Connector Namespace${baseStyles()} + + +
+

${brandMark(28, "create")}Create connector namespace

+
Provisions a real Azure connector namespace (Microsoft.Web/connectorGateways) in your subscription.
+
+ +
+ + +
+ +
+ +
+ + +
+ + +
Pick the resource group the namespace will live in.
+
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ + +
+ +
+ +
+ + +
+ +
+ +`; +} diff --git a/extensions/connector-namespaces/extension.mjs b/extensions/connector-namespaces/extension.mjs new file mode 100644 index 00000000..fe6f502e --- /dev/null +++ b/extensions/connector-namespaces/extension.mjs @@ -0,0 +1,101 @@ +// Canvas extension entry point — MCP Connectors browser. + +import { joinSession, createCanvas } from "@github/copilot-sdk/extension"; +import { getServerConfig, startServer, stopServer } from "./server.mjs"; +import { getSavedConfig, loadSavedConfig, saveConfig } from "./state.mjs"; +import { fetchCatalog } from "./catalog.mjs"; +import { getInstalledState, openInBrowser, setWorkspaceRoot } from "./install.mjs"; +import { buildSandboxUrl, resolveSandboxConnector } from "./sandbox.mjs"; + +// Load any previously saved connector namespace config on startup +loadSavedConfig(); + +async function openPlayground(server, instanceId) { + const config = instanceId ? getServerConfig(instanceId) : getSavedConfig(); + if (!config) return { opened: false, reason: "no_namespace_configured" }; + const catalog = await fetchCatalog(config.subscriptionId, config.resourceGroup, config.gatewayName); + const installedState = await getInstalledState(config); + const resolved = resolveSandboxConnector(catalog, installedState, server); + if (!resolved.connector) return { opened: false, ...resolved }; + const url = buildSandboxUrl(config, resolved.connector.id); + await openInBrowser(url); + return { opened: true, server: resolved.connector, url }; +} + +const session = await joinSession({ + tools: [ + { + name: "connector_namespaces_open_playground", + description: "Open a named connector from My MCPs in the Azure Connector Namespace playground.", + parameters: { + type: "object", + properties: { + server: { + type: "string", + description: "Connector display name or server ID from My MCPs", + }, + }, + required: ["server"], + }, + handler: async ({ server }) => JSON.stringify(await openPlayground(server)), + }, + ], + canvases: [ + createCanvas({ + id: "connector-namespaces", + displayName: "MCP Connectors", + description: "Browse, connect, and open MCP connectors in the Azure Connector Namespace Sandbox.", + inputSchema: { + type: "object", + properties: { + subscriptionId: { type: "string", description: "Azure subscription ID (optional \u2014 if omitted, uses saved config or shows picker)" }, + resourceGroup: { type: "string", description: "Resource group name" }, + gatewayName: { type: "string", description: "Connector namespace name" }, + }, + }, + actions: [ + { + name: "open_sandbox", + description: "Open a named connector from My MCPs in the Azure Connector Namespace Sandbox", + inputSchema: { + type: "object", + properties: { + server: { + type: "string", + description: "Connector display name or server ID from My MCPs", + }, + }, + required: ["server"], + }, + handler: async (ctx) => openPlayground(ctx.input.server, ctx.instanceId), + }, + ], + open: async (ctx) => { + let config; + // If explicit input provided, use it and save for future + if (ctx.input && ctx.input.subscriptionId && ctx.input.resourceGroup && ctx.input.gatewayName) { + config = { + subscriptionId: ctx.input.subscriptionId, + resourceGroup: ctx.input.resourceGroup, + gatewayName: ctx.input.gatewayName, + }; + saveConfig(config); + } + // A saved config seeds a new panel only. Rehydrating an existing + // panel keeps its active namespace even if another panel changed + // the persisted default. + const entry = await startServer( + ctx.instanceId, + config ? { config } : { defaultConfig: getSavedConfig() }, + ); + return { title: "MCP Connectors", url: entry.url }; + }, + onClose: async (ctx) => { + await stopServer(ctx.instanceId); + }, + }), + ], +}); + +// Tell the install pipeline where the workspace .mcp.json lives (if any). +setWorkspaceRoot(session.workspacePath); diff --git a/extensions/connector-namespaces/install.mjs b/extensions/connector-namespaces/install.mjs new file mode 100644 index 00000000..74264d6f --- /dev/null +++ b/extensions/connector-namespaces/install.mjs @@ -0,0 +1,1007 @@ +// Install flow — creates connection, handles OAuth, creates MCP server config, +// mints API key, and writes to ~/.copilot/mcp-config.json. + +import { promises as fs } from "node:fs"; +import { spawn } from "node:child_process"; +import { randomBytes } from "node:crypto"; +import { homedir, platform } from "node:os"; +import { dirname, join } from "node:path"; +import { getToken, assertArmHost, armSegment, resolveSystemExecutable } from "./armClient.mjs"; + +const COPILOT_HOME = process.env.COPILOT_HOME || join(homedir(), ".copilot"); + +// Two scopes the Copilot CLI reads MCP servers from: +// profile -> ~/.copilot/mcp-config.json (private, follows you everywhere) +// workspace -> /.mcp.json (shared with the repo, git-tracked) +const PROFILE_MCP_PATH = join(COPILOT_HOME, "mcp-config.json"); +const PENDING_CLEANUP_DIR = join(COPILOT_HOME, "extensions", "connector-namespaces", "artifacts", "pending-cleanup"); +let s_workspaceRoot = null; + +export function setWorkspaceRoot(path) { + s_workspaceRoot = path || null; +} + +export function getWorkspaceRoot() { + return s_workspaceRoot; +} + +function mcpConfigPath(scope) { + if (scope === "workspace") { + if (!s_workspaceRoot) throw new Error("No workspace folder is available for this session."); + return join(s_workspaceRoot, ".mcp.json"); + } + return PROFILE_MCP_PATH; +} + +const CONFIG_LOCK_TIMEOUT_MS = 10_000; +const CONFIG_LOCK_STALE_MS = 30_000; + +// Serialize in-process writes, then hold an exclusive lock file so separate +// Copilot sessions cannot overwrite each other's MCP config changes. +let s_configLock = Promise.resolve(); +async function acquireConfigLock(path) { + const lockPath = `${path}.lock`; + await fs.mkdir(dirname(path), { recursive: true, mode: 0o700 }); + const deadline = Date.now() + CONFIG_LOCK_TIMEOUT_MS; + for (;;) { + const owner = `${process.pid}:${randomBytes(12).toString("hex")}\n`; + try { + const handle = await fs.open(lockPath, "wx", 0o600); + await handle.writeFile(owner, "utf8"); + return async () => { + await handle.close(); + try { + if (await fs.readFile(lockPath, "utf8") === owner) { + await fs.unlink(lockPath); + } + } catch (error) { + if (error?.code !== "ENOENT") throw error; + } + }; + } catch (error) { + if (error?.code !== "EEXIST") throw error; + try { + const stat = await fs.stat(lockPath); + if (Date.now() - stat.mtimeMs > CONFIG_LOCK_STALE_MS) { + const stalePath = `${lockPath}.${process.pid}.${randomBytes(6).toString("hex")}.stale`; + await fs.rename(lockPath, stalePath); + await fs.unlink(stalePath); + continue; + } + } catch (statError) { + if (statError?.code === "ENOENT") continue; + throw statError; + } + if (Date.now() >= deadline) { + throw new Error(`Timed out waiting for the MCP config lock at ${lockPath}.`); + } + await sleep(50); + } + } +} + +export async function waitForConnected(config, connName, options = {}) { + const maxPolls = options.maxPolls ?? 20; + const delay = options.delay ?? sleep; + const getStatus = options.getStatus ?? getConnectionStatus; + let status = "Unknown"; + for (let i = 0; i < maxPolls; i++) { + status = await getStatus(config, connName); + if (status === "Connected") return status; + if (i + 1 < maxPolls) await delay(1000); + } + throw new Error(`Connection ended in state "${status}".`); +} + +function withConfigLock(path, fn) { + const run = s_configLock.then(async () => { + const release = await acquireConfigLock(path); + try { + return await fn(); + } finally { + await release(); + } + }, async () => { + const release = await acquireConfigLock(path); + try { + return await fn(); + } finally { + await release(); + } + }); + s_configLock = run.then(() => {}, () => {}); + return run; +} + +async function readPendingCleanups(gateway, apiName) { + let names; + try { + names = await fs.readdir(PENDING_CLEANUP_DIR); + } catch (error) { + if (error?.code === "ENOENT") return []; + throw error; + } + + const records = []; + for (const name of names) { + if (!name.endsWith(".json")) continue; + const path = join(PENDING_CLEANUP_DIR, name); + let record; + try { + record = JSON.parse(await fs.readFile(path, "utf8")); + } catch (error) { + if (error?.code === "ENOENT") continue; + throw error; + } + if (!record || typeof record !== "object" || Array.isArray(record)) { + throw new Error("Pending connector cleanup data is invalid."); + } + if (record.gatewayId === gateway && record.apiName === apiName) { + records.push({ ...record, path }); + } + } + return records; +} + +async function getPendingCleanup(gateway, apiName) { + const records = await readPendingCleanups(gateway, apiName); + if (!records.length) return null; + return { + configNames: records.flatMap((record) => Array.isArray(record.configNames) ? record.configNames : []), + connectionNames: records.flatMap((record) => Array.isArray(record.connectionNames) ? record.connectionNames : []), + journalFiles: records.map((record) => record.path), + }; +} + +async function savePendingCleanup(record) { + await fs.mkdir(PENDING_CLEANUP_DIR, { recursive: true, mode: 0o700 }); + await fs.chmod(PENDING_CLEANUP_DIR, 0o700).catch(() => {}); + const id = randomBytes(16).toString("hex"); + const tempPath = join(PENDING_CLEANUP_DIR, `${id}.tmp`); + const path = join(PENDING_CLEANUP_DIR, `${id}.json`); + await fs.writeFile(tempPath, JSON.stringify(record, null, 2) + "\n", { encoding: "utf8", mode: 0o600, flag: "wx" }); + try { + await fs.chmod(tempPath, 0o600).catch(() => {}); + await fs.rename(tempPath, path); + return path; + } catch (error) { + try { + await fs.unlink(tempPath); + } catch (cleanupError) { + if (cleanupError?.code !== "ENOENT") { + throw new AggregateError([error, cleanupError], "Failed to save connector cleanup retry data."); + } + } + throw error; + } +} + +async function clearPendingCleanups(paths) { + for (const path of new Set(paths)) { + try { + await fs.unlink(path); + } catch (error) { + if (error?.code !== "ENOENT") throw error; + } + } +} + +// Validate the MCP endpoint URL before persisting it alongside an API key. The +// value comes from an authenticated ARM read of the user's own gateway, so this +// is defense in depth: require https, reject embedded credentials, and block +// obvious internal/link-local hosts. +export function assertSafeMcpTarget(rawUrl) { + let u; + try { u = new URL(rawUrl); } catch { throw new Error("MCP endpoint URL is not a valid URL."); } + if (u.protocol !== "https:") throw new Error("MCP endpoint URL must use https."); + if (u.username || u.password) throw new Error("MCP endpoint URL must not embed credentials."); + const host = u.hostname.replace(/^\[|\]$/g, "").toLowerCase(); + const isIpv6 = host.includes(":"); + const blocked = + host === "localhost" || host.endsWith(".localhost") || + host === "metadata.google.internal" || host === "0.0.0.0" || + (isIpv6 && (host === "::1" || host.startsWith("fe80:") || host.startsWith("fc") || host.startsWith("fd"))) || + /^(127|10)\./.test(host) || + /^169\.254\./.test(host) || + /^192\.168\./.test(host) || + /^172\.(1[6-9]|2\d|3[01])\./.test(host); + if (blocked) throw new Error(`MCP endpoint URL host is not allowed: ${host}`); +} + +// --------------------------------------------------------------------------- +// ARM helpers (using the shared token) +// --------------------------------------------------------------------------- + +// ARM occasionally answers with a transient 5xx/429 (backend blip, throttling) +// that clears on a retry. A single one of these shouldn't nuke a whole connect +// flow, so arm() retries them a few times with backoff before surfacing. +const ARM_TRANSIENT = new Set([429, 500, 502, 503, 504]); +const ARM_MAX_ATTEMPTS = 3; +const ARM_BACKOFF_MS = 500; + +async function arm(method, url, body) { + const token = await getToken(); + const headers = { Authorization: `Bearer ${token}`, Accept: "application/json" }; + if (body !== undefined) headers["Content-Type"] = "application/json"; + const fullUrl = url.startsWith("http") ? url : `https://management.azure.com${url}`; + // Guard the exact value handed to fetch so a tainted path segment can never + // redirect the call off ARM. assertArmHost throws unless fullUrl targets + // https://management.azure.com/. + const safeUrl = assertArmHost(fullUrl); + + for (let attempt = 1; ; attempt++) { + const res = await fetch(safeUrl, { + method, + headers, + body: body !== undefined ? JSON.stringify(body) : undefined, + }); + const text = await res.text(); + let parsed; + try { parsed = text ? JSON.parse(text) : undefined; } catch { parsed = text; } + if (res.ok) return parsed; + + const msg = parsed?.error?.message ?? parsed?.message ?? text ?? `HTTP ${res.status}`; + const err = new Error(`ARM ${method} ${res.status}: ${msg}`); + err.status = res.status; + + // Every ARM call we make is idempotent (GET/PUT/DELETE) or a list-shaped + // POST (listConsentLinks, listApiKey) that returns the same value on + // retry, so retrying a transient failure can't spawn duplicate side + // effects. A 500 is never treated like a 404 elsewhere, so a blip can't + // trigger teardown of a live resource. + if (!ARM_TRANSIENT.has(res.status) || attempt >= ARM_MAX_ATTEMPTS) throw err; + await sleep(ARM_BACKOFF_MS * Math.pow(3, attempt - 1)); // 0.5s, then 1.5s + } +} + +// DELETE that tolerates "already gone" (404) but surfaces every other failure +// instead of silently swallowing it. +async function armDelete(url) { + try { + return await arm("DELETE", url); + } catch (e) { + if (e.status === 404) return undefined; + throw e; + } +} + +// --------------------------------------------------------------------------- +// Naming helpers +// --------------------------------------------------------------------------- + +function shortId() { return randomBytes(3).toString("hex"); } +function sanitize(s) { return String(s).replace(/[^a-zA-Z0-9]+/g, "").slice(0, 24) || "x"; } +function generateName(displayName) { return `${sanitize(displayName)}-${shortId()}`; } +function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); } + +// --------------------------------------------------------------------------- +// Connector metadata (connection parameters + agentic operation id) +// --------------------------------------------------------------------------- + +const MANAGED_API_VERSION = "2022-09-01-preview"; +const metaCache = new Map(); // apiName + swagger requirement -> Promise + +export function loadConnectorMeta(config, apiName, location, requireSwagger = true) { + const sub = armSegment(config.subscriptionId); + const cacheKey = `${sub}:${location}:${apiName}:${requireSwagger}`; + if (metaCache.has(cacheKey)) return metaCache.get(cacheKey); + const promise = (async () => { + const base = `/subscriptions/${sub}/providers/Microsoft.Web/locations/${armSegment(location)}/managedApis/${armSegment(apiName)}`; + const metaRequest = arm("GET", `${base}?api-version=${MANAGED_API_VERSION}`); + const swaggerRequest = requireSwagger + ? arm("GET", `${base}?api-version=${MANAGED_API_VERSION}&export=true`) + : Promise.resolve(undefined); + const [meta, swagger] = await Promise.all([metaRequest, swaggerRequest]); + return { + connectionParameters: meta?.properties?.connectionParameters ?? null, + connectionParameterSets: meta?.properties?.connectionParameterSets ?? null, + opId: swagger ? getMcpServerOperationId(swagger) : undefined, + }; + })(); + // Cache the in-flight promise so a fast Connect click reuses the prewarm + // fetch instead of starting a second swagger export. Evict on hard failure + // so a transient error doesn't poison the cache. + promise.catch(() => metaCache.delete(cacheKey)); + metaCache.set(cacheKey, promise); + return promise; +} + +// Fire-and-forget pre-warm so the slow swagger fetch happens while the user is +// reading the catalog, not when they click Connect. Concurrency is bounded so a +// large catalog (~43 MCP servers, each 2 ARM GETs) doesn't burst ~86 parallel +// requests on open and trip rate limits. Items are warmed in catalog order, so +// the servers nearest the top of the view warm first. +export function prewarmMeta(config, apiNames, location) { + Promise.resolve(location || getGatewayLocation(config)).then(async (loc) => { + const sub = armSegment(config.subscriptionId); + const pending = apiNames.filter((name) => !metaCache.has(`${sub}:${loc}:${name}:true`)); + const CONCURRENCY = 5; + let next = 0; + const worker = async () => { + while (next < pending.length) { + const apiName = pending[next++]; + await loadConnectorMeta(config, apiName, loc).catch(() => {}); + } + }; + const poolSize = Math.min(CONCURRENCY, pending.length); + await Promise.all(Array.from({ length: poolSize }, worker)); + }).catch(() => {}); +} + +function getMcpServerOperationId(swagger) { + if (!swagger?.paths) return undefined; + for (const methods of Object.values(swagger.paths)) { + if (!methods || typeof methods !== "object") continue; + const post = methods.post; + if (!post?.operationId) continue; + const tags = (post.tags ?? []).map((t) => String(t).toLowerCase()); + if (tags.includes("deprecated")) continue; + if (tags.includes("agentic")) return post.operationId; + } + return undefined; +} + +// Find the OAuth connection parameter name. The consent call 500s if we send a +// parameterName the connector doesn't declare, so derive it from metadata. +function findOAuthParam(meta, redirectUrl) { + const fallback = { parameterName: "token", redirectUrl }; + let params; + if (meta?.connectionParameterSets?.values?.length) { + params = meta.connectionParameterSets.values[0].parameters; + } else { + params = meta?.connectionParameters; + } + if (!params) return fallback; + for (const [name, param] of Object.entries(params)) { + if (param?.type === "oauthSetting" || param?.oAuthSettings) { + return { parameterName: name, redirectUrl }; + } + } + return fallback; +} + +// --------------------------------------------------------------------------- +// JWT decode (to get user oid/tid for access policy) +// --------------------------------------------------------------------------- + +function decodeJwtPayload(token) { + const parts = token.split("."); + if (parts.length < 2) throw new Error("Invalid JWT"); + const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/"); + const pad = b64.length % 4 === 0 ? "" : "=".repeat(4 - (b64.length % 4)); + return JSON.parse(Buffer.from(b64 + pad, "base64").toString("utf8")); +} + +async function getUserContext() { + const token = await getToken(); + const claims = decodeJwtPayload(token); + return { objectId: claims.oid, tenantId: claims.tid }; +} + +// --------------------------------------------------------------------------- +// Connection management +// --------------------------------------------------------------------------- + +function gatewayId(config) { + return `/subscriptions/${armSegment(config.subscriptionId)}/resourceGroups/${armSegment(config.resourceGroup)}/providers/Microsoft.Web/connectorGateways/${armSegment(config.gatewayName)}`; +} + +const API_VERSION = "2026-05-01-preview"; + +const s_locationCache = new Map(); // gatewayId -> location (immutable per gateway) + +export async function getGatewayLocation(config) { + const id = gatewayId(config); + const cached = s_locationCache.get(id); + if (cached) return cached; + const gw = await arm("GET", `${id}?api-version=${API_VERSION}`); + const loc = (gw.location ?? "").toLowerCase().replace(/\s+/g, ""); + if (loc) s_locationCache.set(id, loc); + return loc; +} + +export async function createConnection(config, apiName, displayName, location) { + const connName = generateName(displayName); + await arm("PUT", `${gatewayId(config)}/connections/${connName}?api-version=${API_VERSION}`, { + location, + properties: { displayName, connectorName: apiName }, + }); + // Grant current user access policy + try { + const { objectId, tenantId } = await getUserContext(); + await arm("PUT", `${gatewayId(config)}/connections/${connName}/accessPolicies/user-${shortId()}?api-version=${API_VERSION}`, { + location, + properties: { principal: { type: "ActiveDirectory", identity: { objectId, tenantId } } }, + }); + } catch { /* non-fatal */ } + return connName; +} + +export async function getConsentUrl(config, connName, callbackUrl, oauthParam) { + const param = oauthParam || { parameterName: "token", redirectUrl: callbackUrl }; + const res = await arm("POST", `${gatewayId(config)}/connections/${armSegment(connName)}/listConsentLinks?api-version=${API_VERSION}`, { + parameters: [{ parameterName: param.parameterName, redirectUrl: param.redirectUrl }], + }); + return res?.value?.[0]?.link || null; +} + +export async function getConnectionStatus(config, connName) { + const conn = await arm("GET", `${gatewayId(config)}/connections/${armSegment(connName)}?api-version=${API_VERSION}`); + return conn?.properties?.statuses?.[0]?.status ?? conn?.properties?.overallStatus ?? "Unknown"; +} + +export async function createMcpServerConfig(config, apiName, displayName, connName, location, opId, configName = generateName(displayName)) { + if (!opId) { + throw new Error(`Cannot configure "${displayName}" as an MCP server: no agentic operation was found in the connector's definition. The connector may not expose an MCP-streamable endpoint, or its swagger failed to load.`); + } + const created = await arm("PUT", `${gatewayId(config)}/mcpserverConfigs/${configName}?api-version=${API_VERSION}`, { + kind: "ManagedMcpServer", + location, + properties: { + description: displayName, + state: "Enabled", + disableApiKeyAuth: false, + // TextOnlyContent must stay false: when true the dataplane wraps tools/list and + // tools/call responses in a base64 "$content" envelope that spec-compliant MCP + // clients cannot parse, so zero tools load. + settings: { TextOnlyContent: false }, + connectors: [{ + name: apiName, + connectionName: connName, + displayName, + operations: [{ name: opId, displayName, description: "" }], + }], + }, + }); + return { configName, endpointUrl: created?.properties?.mcpEndpointUrl || null }; +} + +export async function mintApiKey(config, configName) { + const notAfter = new Date(Date.now() + 365 * 24 * 3600_000).toISOString(); + const res = await arm("POST", `${gatewayId(config)}/listApiKey?api-version=${API_VERSION}`, { + keyType: "Primary", + notAfter, + scope: configName, + }); + return res.key; +} + +export async function getMcpEndpointUrl(config, configName) { + const cfg = await arm("GET", `${gatewayId(config)}/mcpserverConfigs/${armSegment(configName)}?api-version=${API_VERSION}`); + return cfg?.properties?.mcpEndpointUrl || null; +} + +// --------------------------------------------------------------------------- +// MCP config writer +// --------------------------------------------------------------------------- + +async function readMcpConfigAt(path) { + try { + const raw = await fs.readFile(path, "utf8"); + let parsed = JSON.parse(raw); + // Reject arrays and primitives before treating this as a config object. + // JSON.parse can return either (a hand-edited "[]" or a bare number), + // and both break the write path: a string key set on an array is + // silently dropped by JSON.stringify (the new entry would vanish), and + // a primitive throws on property assignment. Fall back to a fresh + // object so writeMcpEntry always persists. + if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) parsed = {}; + if (!parsed.mcpServers || typeof parsed.mcpServers !== "object" || Array.isArray(parsed.mcpServers)) parsed.mcpServers = {}; + return parsed; + } catch (e) { + if (e.code === "ENOENT") return { mcpServers: {} }; + throw e; + } +} + +async function writeMcpConfigAt(path, cfg) { + const directory = dirname(path); + const temporary = `${path}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`; + await fs.mkdir(directory, { recursive: true, mode: 0o700 }); + await fs.chmod(directory, 0o700).catch(() => {}); + try { + await fs.writeFile(temporary, JSON.stringify(cfg, null, 2) + "\n", { encoding: "utf8", mode: 0o600 }); + await fs.chmod(temporary, 0o600).catch(() => {}); + await fs.rename(temporary, path); + await fs.chmod(path, 0o600).catch(() => {}); + } finally { + await fs.unlink(temporary).catch((error) => { + if (error?.code !== "ENOENT") throw error; + }); + } +} + +export async function writeMcpEntry(name, url, key, scope = "profile", meta = null) { + assertSafeMcpTarget(url); + const path = mcpConfigPath(scope); + return withConfigLock(path, async () => { + const cfg = await readMcpConfigAt(path); + cfg.mcpServers[name] = { + url, + headers: { "X-API-Key": key }, + }; + // Stamp ARM provenance as a sibling metadata key. The underscore prefix + // marks it as "metadata, not part of the MCP launch spec" — the CLI + // tolerates and preserves unknown sibling keys across restarts. + if (meta) cfg.mcpServers[name]._connectorNamespace = meta; + await writeMcpConfigAt(path, cfg); + }); +} + +// Remove the entry from whichever scope(s) it lives in. +export async function removeMcpEntry(name) { + let removed = false; + for (const scope of ["profile", "workspace"]) { + let path; + try { path = mcpConfigPath(scope); } catch { continue; } + const removedAtPath = await withConfigLock(path, async () => { + const cfg = await readMcpConfigAt(path); + if (Object.prototype.hasOwnProperty.call(cfg.mcpServers, name)) { + delete cfg.mcpServers[name]; + await writeMcpConfigAt(path, cfg); + return true; + } + return false; + }); + removed ||= removedAtPath; + } + return removed; +} + +async function deleteMcpServerConfigs(config, configNames) { + for (const configName of configNames) { + const url = `${gatewayId(config)}/mcpserverConfigs/${armSegment(configName)}?api-version=${API_VERSION}`; + await armDelete(url); + let pending = true; + for (let i = 0; i < 20; i++) { + try { + await arm("GET", url); + } catch (error) { + if (error?.status === 404) { + pending = false; + break; + } + throw error; + } + await sleep(750); + } + if (pending) throw new Error(`Timed out waiting for connector configuration "${configName}" deletion.`); + } +} + +async function cleanupConnectorResources(config, apiName, configNames, connectionNames, priorJournalFiles = []) { + configNames = [...new Set(configNames.filter(Boolean))]; + connectionNames = [...new Set(connectionNames.filter(Boolean))]; + const gateway = gatewayId(config); + const journalFile = await savePendingCleanup({ gatewayId: gateway, apiName, configNames, connectionNames }); + const journalFiles = [...priorJournalFiles, journalFile]; + + await deleteMcpServerConfigs(config, configNames); + for (const connectionName of connectionNames) { + await armDelete(`${gateway}/connections/${armSegment(connectionName)}?api-version=${API_VERSION}`); + } + for (const configName of configNames) { + await removeMcpEntry(configName); + } + await clearPendingCleanups(journalFiles); +} + +// Remove an installed connector: delete its mcpserverConfig, its connection, +// and its CLI entry. apiName is resolved against the current installed state. +export async function uninstallConnector(config, apiName) { + const state = await getInstalledState(config); + const entry = state[apiName]; + const gateway = gatewayId(config); + const pending = await getPendingCleanup(gateway, apiName); + if (!entry && !pending) return { ok: true, removed: false }; + + const candidates = entry ? (entry._candidates ?? [entry]) : []; + const configNames = [ + ...(pending?.configNames ?? []), + ...candidates.map((candidate) => candidate.configName), + ]; + const connectionNames = [ + ...(pending?.connectionNames ?? []), + ...candidates.map((candidate) => candidate.connectionName), + ]; + await cleanupConnectorResources(config, apiName, configNames, connectionNames, pending?.journalFiles); + + return { ok: true, removed: true }; +} + +// Local-only remove: drop just the CLI mcp entry, leaving the namespace +// resources (mcpserverConfig + connection) intact. This is the default +// "Remove" action — it unwires the connector from Copilot without deleting +// anything on Azure. Fast and local; no armDelete, no convergence poll. +export async function removeLocalEntry(config, apiName) { + const state = await getInstalledState(config); + const entry = state[apiName]; + if (!entry) return { ok: true, removed: false }; + const candidates = entry._candidates ?? [entry]; + for (const candidate of candidates) { + if (candidate.inCli && candidate.configName) await removeMcpEntry(candidate.configName); + } + return { ok: true, removed: true }; +} + +// Best-effort rollback of a connection created during an install the user then +// cancelled. At that point no mcpserverConfig exists yet, so uninstallConnector +// can't see it — delete the orphaned connection directly so the tile honestly +// returns to "Connect" and we don't leak a half-made connection on the namespace. +export async function deleteConnection(config, connName) { + if (!connName) return { ok: true, removed: false }; + await armDelete(`${gatewayId(config)}/connections/${armSegment(connName)}?api-version=${API_VERSION}`); + return { ok: true, removed: true }; +} + +async function throwAfterCleanup(error, cleanups) { + for (const cleanup of cleanups) { + try { + await cleanup(); + } catch (cleanupError) { + throw new AggregateError( + [error, cleanupError], + `${error.message} Cleanup also failed: ${cleanupError.message}`, + ); + } + } + throw error; +} + +// --------------------------------------------------------------------------- +// Full install pipeline +// --------------------------------------------------------------------------- + +function oauthCallbackUrl(callbackBase, connName, capabilityToken = "") { + const url = new URL(`${callbackBase}${encodeURIComponent(connName)}`); + if (capabilityToken) { + url.searchParams.set("cn_token", capabilityToken); + } + return url.toString(); +} + +export async function installConnector(config, apiName, displayName, callbackBase, scope = "profile", capabilityToken = "") { + const pending = await getPendingCleanup(gatewayId(config), apiName); + if (pending) { + await cleanupConnectorResources( + config, + apiName, + pending.configNames, + pending.connectionNames, + pending.journalFiles, + ); + } + const location = await getGatewayLocation(config); + const meta = await loadConnectorMeta(config, apiName, location); + + // 1. Create connection + const connName = await createConnection(config, apiName, displayName, location); + let finishStarted = false; + try { + // The OAuth redirect must carry the connName so the loopback callback keys + // pendingOAuth by the same value the client polls on. + const callbackUrl = oauthCallbackUrl(callbackBase, connName, capabilityToken); + + // 2. Quick wait for the connection to converge — some connectors come up + // Connected without any OAuth (e.g. service principal / key based). + await sleep(800); + const status = await getConnectionStatus(config, connName); + if (status === "Connected") { + finishStarted = true; + return await finishInstall(config, apiName, displayName, connName, location, scope); + } + + // 3. Needs OAuth — derive the correct consent parameter from metadata. + const oauthParam = findOAuthParam(meta, callbackUrl); + const consentUrl = await getConsentUrl(config, connName, callbackUrl, oauthParam); + if (consentUrl) { + return { needsConsent: true, consentUrl, connName, location, freshConnection: true }; + } + + // 4. No consent link and not Connected — try to finish anyway. + finishStarted = true; + return await finishInstall(config, apiName, displayName, connName, location, scope); + } catch (error) { + if (finishStarted) throw error; + return throwAfterCleanup(error, [() => deleteConnection(config, connName)]); + } +} + +export async function finishInstall(config, apiName, displayName, connName, location, scope = "profile") { + let configName; + try { + if (!location) location = await getGatewayLocation(config); + const meta = await loadConnectorMeta(config, apiName, location); + + // Poll connection status up to ~20s for Connected. + const status = await waitForConnected(config, connName); + + // Create MCP server config (endpoint URL comes back on the PUT response). + let endpointUrl; + configName = generateName(displayName); + ({ endpointUrl } = await createMcpServerConfig(config, apiName, displayName, connName, location, meta.opId, configName)); + + // Endpoint URL can lag — poll the config a few times if missing. + for (let i = 0; !endpointUrl && i < 5; i++) { + await sleep(1000); + endpointUrl = await getMcpEndpointUrl(config, configName); + } + if (!endpointUrl) throw new Error(`MCP endpoint URL not available (connection status: ${status}).`); + + // Mint key and write the CLI entry, stamped with ARM provenance so the + // install can be recognised regardless of which connector namespace is + // active when state is next derived. + const key = await mintApiKey(config, configName); + const gw = gatewayId(config); + await writeMcpEntry(configName, endpointUrl, key, scope, { + gatewayId: gw, + mcpServerConfigId: `${gw}/mcpserverConfigs/${armSegment(configName)}`, + connectionId: `${gw}/connections/${armSegment(connName)}`, + apiName, + }); + + return { ok: true, configName, connName, endpointUrl, scope }; + } catch (error) { + const cleanups = []; + if (configName) { + cleanups.push(() => deleteMcpServerConfigs(config, [configName])); + } + cleanups.push(() => deleteConnection(config, connName)); + return throwAfterCleanup(error, cleanups); + } +} + +// --------------------------------------------------------------------------- +// Re-authenticate pipeline (reuse the EXISTING connection + config) +// --------------------------------------------------------------------------- + +// Re-run consent for a connector that's already installed, WITHOUT minting a new +// connection or a new mcpserverConfig. This is what the "Re-authenticate" button +// hits; wiring it to the plain install path is exactly what spawned duplicate +// configs. We resolve the selected install-state candidate (post phase-1 +// selection, that's the config the local session actually points at), re-consent +// its existing connection, and rebind THAT config locally. +// +// Falls back to a fresh installConnector only when there's genuinely nothing to +// re-auth against: no known connection, or the stored connection was deleted +// server-side (listConsentLinks 404s). In the 404 case we drop the orphaned +// config + local entry first so the fallback install can't leave a duplicate. +export async function reauthConnector(config, apiName, displayName, callbackBase, scope = "profile", capabilityToken = "") { + return reauthConnectorWithAttempts(config, apiName, displayName, callbackBase, scope, capabilityToken, new Set()); +} + +async function reauthConnectorWithAttempts(config, apiName, displayName, callbackBase, scope, capabilityToken, attemptedConfigNames) { + const state = await getInstalledState(config); + const selected = state[apiName]; + const candidates = selected?._candidates ?? (selected ? [selected] : []); + const entry = candidates.find((candidate) => !attemptedConfigNames.has(candidate.configName)); + const connName = entry?.connectionName; + + // Nothing installed to re-auth against — treat it as a first-time Connect. + if (!connName) { + return installConnector(config, apiName, displayName, callbackBase, scope, capabilityToken); + } + + const location = await getGatewayLocation(config); + const meta = await loadConnectorMeta(config, apiName, location, false); + const callbackUrl = oauthCallbackUrl(callbackBase, connName, capabilityToken); + const oauthParam = findOAuthParam(meta, callbackUrl); + + let consentUrl; + try { + consentUrl = await getConsentUrl(config, connName, callbackUrl, oauthParam); + } catch (err) { + // The stored connection is gone (deleted in the portal). Clean up the + // now-orphaned config + local entry, then fall through to a clean + // install so we don't strand a dead "Re-authenticate" tile. + if (err.status === 404) { + attemptedConfigNames.add(entry.configName); + const siblingUsesConnection = candidates.some( + (candidate) => candidate.configName !== entry.configName && candidate.connectionName === connName, + ); + await cleanupConnectorResources( + config, + apiName, + entry.configName ? [entry.configName] : [], + siblingUsesConnection ? [] : [connName], + ); + return reauthConnectorWithAttempts( + config, + apiName, + displayName, + callbackBase, + scope, + capabilityToken, + attemptedConfigNames, + ); + } + throw err; + } + + // Re-consent the existing connection; finish rebinds the SAME config. + // configName is carried through so the finish step never creates a new one. + if (consentUrl) { + return { needsConsent: true, consentUrl, connName, location, configName: entry.configName, reauth: true, freshConnection: false }; + } + + // Already consentable without a redirect — just rebind the existing config. + return finishReauth(config, apiName, displayName, connName, entry.configName, location, scope); +} + +// Finish a re-auth: rebind an EXISTING mcpserverConfig to the local CLI. Unlike +// finishInstall this never calls createMcpServerConfig, so a re-auth can't spawn +// a duplicate — it reuses configName, mints a fresh key, and rewrites the entry. +export async function finishReauth(config, apiName, displayName, connName, configName, location, scope = "profile") { + // Defensive: with no config to bind there's nothing to reuse — fall back to + // a normal finish (which creates one). Shouldn't happen on the reauth path. + if (!configName) { + return finishInstall(config, apiName, displayName, connName, location, scope); + } + + // Wait for the re-consented connection to converge (up to ~20s). + const status = await waitForConnected(config, connName); + + // Reuse the existing config's endpoint — poll a few times if it lags. + let endpointUrl = await getMcpEndpointUrl(config, configName); + for (let i = 0; !endpointUrl && i < 5; i++) { + await sleep(1000); + endpointUrl = await getMcpEndpointUrl(config, configName); + } + if (!endpointUrl) throw new Error(`MCP endpoint URL not available (connection status: ${status}).`); + + const key = await mintApiKey(config, configName); + const gw = gatewayId(config); + await writeMcpEntry(configName, endpointUrl, key, scope, { + gatewayId: gw, + mcpServerConfigId: `${gw}/mcpserverConfigs/${armSegment(configName)}`, + connectionId: `${gw}/connections/${armSegment(connName)}`, + apiName, + }); + + return { ok: true, configName, connName, endpointUrl, scope, reauth: true }; +} + +// --------------------------------------------------------------------------- +// Installed-state derivation (source of truth = the gateway + CLI config) +// --------------------------------------------------------------------------- + +export async function getInstalledState(config) { + const wsPath = s_workspaceRoot ? join(s_workspaceRoot, ".mcp.json") : null; + const [configsRes, connectionsRes, profileCfg, workspaceCfg] = await Promise.all([ + arm("GET", `${gatewayId(config)}/mcpserverConfigs?api-version=${API_VERSION}`), + arm("GET", `${gatewayId(config)}/connections?api-version=${API_VERSION}`), + readMcpConfigAt(PROFILE_MCP_PATH), + wsPath ? readMcpConfigAt(wsPath) : Promise.resolve({ mcpServers: {} }), + ]); + + const connByName = new Map(); + for (const c of connectionsRes.value ?? []) connByName.set(c.name, c); + + const profileKeys = new Set(Object.keys(profileCfg.mcpServers ?? {})); + const workspaceKeys = new Set(Object.keys(workspaceCfg.mcpServers ?? {})); + + return deriveInstalledState(configsRes.value ?? [], connByName, profileKeys, workspaceKeys, wsPath); +} + +// Pure derivation, split out so it can be unit-tested without live ARM. +// A single apiName can have MULTIPLE gateway configs (a portal-side add, a +// duplicate Connect, a re-auth that minted a fresh config). Collect every +// config per apiName, then pick ONE deterministically instead of letting ARM +// list order decide (last-wins) — that overwrite is what stranded a tile on +// "Re-authenticate" while a sibling config was actually Connected. +export function deriveInstalledState(configs, connByName, profileKeys, workspaceKeys, wsPath) { + const candidatesByApi = {}; + for (const cfg of configs ?? []) { + const connector = cfg.properties?.connectors?.[0]; + const apiName = connector?.name; + if (!apiName) continue; + const connName = connector?.connectionName; + const conn = connName ? connByName.get(connName) : null; + const connectionStatus = conn?.properties?.statuses?.[0]?.status ?? conn?.properties?.overallStatus ?? "Unknown"; + const inWorkspace = workspaceKeys.has(cfg.name); + const inProfile = profileKeys.has(cfg.name); + (candidatesByApi[apiName] ??= []).push({ + installed: true, + configName: cfg.name, + connectionName: connName || null, + connectionStatus, + inCli: inProfile || inWorkspace, + cliScope: inWorkspace ? "workspace" : (inProfile ? "profile" : null), + cliPath: inWorkspace ? wsPath : (inProfile ? PROFILE_MCP_PATH : null), + }); + } + + // Prefer the config the local session actually points at, and prefer a + // Connected one: inCli && Connected > inCli > Connected > any. Config name + // breaks ties so ARM list order cannot change the selected resource. Keeps the flat + // one-entry-per-apiName shape the renderer + tests expect. + const rank = (e) => (e.inCli ? 2 : 0) + (e.connectionStatus === "Connected" ? 1 : 0); + const byApi = {}; + for (const [apiName, list] of Object.entries(candidatesByApi)) { + list.sort((a, b) => rank(b) - rank(a) || a.configName.localeCompare(b.configName)); + const best = list[0]; + // Internal-only signal for logging; the renderer ignores unknown fields. + byApi[apiName] = list.length > 1 ? { ...best, _configCount: list.length, _candidates: list } : best; + } + return byApi; +} + +// --------------------------------------------------------------------------- +// Browser opener +// --------------------------------------------------------------------------- + +async function launchDetached(command, args) { + await new Promise((resolve, reject) => { + const child = spawn(command, args, { detached: true, stdio: "ignore" }); + child.once("error", reject); + child.once("spawn", () => { + child.unref(); + resolve(); + }); + }); +} + +export async function openInBrowser(url) { + // Only ever hand an http(s) URL to the OS shell — guards against the + // consent URL being anything that could be reinterpreted as a command. + let safe; + try { + const u = new URL(url); + if (u.protocol !== "http:" && u.protocol !== "https:") return; + safe = u.toString(); + } catch { + return; + } + const p = platform(); + if (p === "win32") { + // rundll32 hands the URL to the default protocol handler as a single + // literal argv with no shell parsing — avoids cmd.exe `start` metachar + // and quoting pitfalls. + await launchDetached(await resolveSystemExecutable("rundll32.exe"), ["url.dll,FileProtocolHandler", safe]); + } else if (p === "darwin") { + await launchDetached(await resolveSystemExecutable("open"), [safe]); + } else { + await launchDetached(await resolveSystemExecutable("xdg-open"), [safe]); + } +} + +// --------------------------------------------------------------------------- +// Config file opener +// --------------------------------------------------------------------------- + +// Hand a local file path to the OS so it opens in the user's default handler +// for that type (typically their editor for .json). Single literal argv on +// every platform — no shell, so a path with spaces or metachars is safe. +async function openPath(filePath) { + const p = platform(); + if (p === "win32") { + // FileProtocolHandler also accepts plain file paths and routes them to + // the registered default app, same no-shell guarantee as openInBrowser. + await launchDetached(await resolveSystemExecutable("rundll32.exe"), ["url.dll,FileProtocolHandler", filePath]); + } else if (p === "darwin") { + await launchDetached(await resolveSystemExecutable("open"), [filePath]); + } else { + await launchDetached(await resolveSystemExecutable("xdg-open"), [filePath]); + } +} + +// Open the MCP config this canvas writes to (the profile scope — +// ~/.copilot/mcp-config.json). Creates an empty, correctly-shaped config if +// none exists yet so the editor never opens a missing file. Returns the path +// either way so the UI can show where it lives even if the OS open is a no-op. +export async function openMcpConfigFile() { + const path = PROFILE_MCP_PATH; + try { + await fs.access(path); + } catch { + try { + await fs.mkdir(dirname(path), { recursive: true }); + await fs.writeFile(path, JSON.stringify({ mcpServers: {} }, null, 2) + "\n", { encoding: "utf8", mode: 0o600 }); + await fs.chmod(path, 0o600).catch(() => {}); + } catch (err) { + return { ok: false, path, error: err.message }; + } + } + await openPath(path); + return { ok: true, path }; +} diff --git a/extensions/connector-namespaces/install.reauth.test.mjs b/extensions/connector-namespaces/install.reauth.test.mjs new file mode 100644 index 00000000..50da0470 --- /dev/null +++ b/extensions/connector-namespaces/install.reauth.test.mjs @@ -0,0 +1,558 @@ +// Phase 2 regression: Re-authenticate must re-consent the EXISTING connection and +// mint NO new resources. +// +// Before the fix, the "Re-authenticate" button ran the full install path, so it +// created a fresh connection + a fresh mcpserverConfig on every click. A teammate +// saw a new Dynamics config appear on the namespace each time they re-authed, while +// the panel stayed stuck on "Re-authenticate". This test stubs ARM and proves +// reauthConnector adopts the local session's connection and issues ZERO PUTs. +// +// Run: node --test extensions/connector-namespaces/install.reauth.test.mjs + +import { test, after } from "node:test"; +import assert from "node:assert/strict"; +import { spawn } from "node:child_process"; +import { chmodSync, existsSync, mkdtempSync, mkdirSync, readFileSync, readdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs"; +import { delimiter, join } from "node:path"; +import { tmpdir } from "node:os"; + +// Isolate COPILOT_HOME before importing install.mjs because its paths are bound at +// module-eval time. Put a fake Azure CLI on PATH so getToken() stays offline, and +// seed a profile config so the local entry reads as inCli. +const TMP = mkdtempSync(join(tmpdir(), "cn-reauth-")); +process.env.COPILOT_HOME = TMP; +process.env.USERPROFILE = TMP; // homedir() on Windows +process.env.HOME = TMP; // homedir() on posix + +const binDir = join(TMP, "bin"); +mkdirSync(binDir, { recursive: true }); +const tokenJson = JSON.stringify({ accessToken: "fake-token", expires_on: Math.floor(Date.now() / 1000) + 3600 }); +writeFileSync(join(binDir, "az"), `#!/usr/bin/env node\nprocess.stdout.write(${JSON.stringify(tokenJson)});\n`); +chmodSync(join(binDir, "az"), 0o755); +writeFileSync(join(binDir, "az.cmd"), `@echo ${tokenJson}\r\n`); +process.env.PATH = `${binDir}${delimiter}${process.env.PATH || ""}`; + +const legacyAuthCache = join(TMP, "extensions", "connector-namespaces", "artifacts", "auth-cache.json"); +mkdirSync(join(TMP, "extensions", "connector-namespaces", "artifacts"), { recursive: true }); +writeFileSync(legacyAuthCache, JSON.stringify({ accessToken: "legacy", refreshToken: "legacy" })); + +writeFileSync( + join(TMP, "mcp-config.json"), + JSON.stringify({ mcpServers: { "docusign-bbb": { type: "http", url: "https://example/mcp" } } }), +); + +// Dynamic import AFTER the env is set. A static top-level import would be hoisted +// and evaluate install.mjs (binding the paths to the real home) before the env +// assignments run. +const { + deleteConnection, + finishInstall, + getInstalledState, + installConnector, + loadConnectorMeta, + reauthConnector, + removeMcpEntry, + uninstallConnector, +} = await import("./install.mjs"); + +after(() => { + try { + rmSync(TMP, { recursive: true, force: true }); + } catch { + /* best-effort temp cleanup */ + } +}); + +test("re-authenticate re-consents the existing connection and mints no new resources", async (t) => { + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "gw1" }; + + // Two configs for one apiName — the bug scenario. configA is a portal-added + // sibling that is NOT in the local CLI; configB is the one the local session + // points at. Both connections are Connected, so selection turns on inCli: + // deriveInstalledState must pick configB, and the re-consent must target conn-b. + const configA = { name: "docusign-aaa", properties: { connectors: [{ name: "docusign", connectionName: "conn-a" }] } }; + const configB = { name: "docusign-bbb", properties: { connectors: [{ name: "docusign", connectionName: "conn-b" }] } }; + const connA = { name: "conn-a", properties: { statuses: [{ status: "Connected" }] } }; + const connB = { name: "conn-b", properties: { statuses: [{ status: "Connected" }] } }; + + const calls = []; + const realFetch = globalThis.fetch; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + calls.push({ method, url }); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + + if (method === "POST" && url.includes("/listConsentLinks")) return ok({ value: [{ link: "https://consent.example/redir" }] }); + if (url.includes("/managedApis/") && !url.includes("export=true")) { + return ok({ properties: { connectionParameters: { token: { type: "oauthSetting" } } } }); + } + if (method === "GET" && /\/mcpserverConfigs\?/.test(url)) return ok({ value: [configA, configB] }); + if (method === "GET" && /\/connections\?/.test(url)) return ok({ value: [connA, connB] }); + if (method === "GET" && /\/connectorGateways\/[^/?]+\?/.test(url)) return ok({ location: "eastus" }); + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + }); + + const result = await reauthConnector(config, "docusign", "DocuSign", "https://cb/?c="); + assert.equal(existsSync(legacyAuthCache), false, "the legacy refresh-token cache must be removed without reading it"); + + // Adopts the existing connection, stops at consent, carries the selected config + // through so finish never mints a new one. + assert.equal(result.needsConsent, true); + assert.equal(result.reauth, true); + assert.equal(result.freshConnection, false); + assert.equal(result.connName, "conn-b"); // the inCli config's connection + assert.equal(result.configName, "docusign-bbb"); // never a fresh generateName() + + // The core guarantee: nothing was minted. createConnection and + // createMcpServerConfig are the only PUTs on the install path; re-auth issues none. + const puts = calls.filter((c) => c.method === "PUT"); + assert.deepEqual(puts, [], `expected zero PUTs, saw: ${puts.map((p) => p.url).join(", ")}`); + + // And it re-consented the SELECTED connection, not the portal sibling. + const consent = calls.find((c) => c.url.includes("/listConsentLinks")); + assert.ok(consent && consent.url.includes("/connections/conn-b/"), "consent must target conn-b"); + assert.ok( + !calls.some((c) => c.url.includes("/connections/conn-a/listConsentLinks")), + "must not touch the sibling connection conn-a", + ); + assert.ok(!calls.some((c) => c.url.includes("export=true")), "reauth must not request unused swagger"); +}); + +test("missing selected connection re-evaluates a valid duplicate before installing", async (t) => { + const configPath = join(TMP, "mcp-config.json"); + writeFileSync( + configPath, + JSON.stringify({ mcpServers: { "api-dead": { type: "http", url: "https://example.com/mcp" } } }), + ); + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "gw1" }; + const dead = { name: "api-dead", properties: { connectors: [{ name: "shared-api", connectionName: "conn-dead" }] } }; + const live = { name: "api-live", properties: { connectors: [{ name: "shared-api", connectionName: "conn-live" }] } }; + const calls = []; + const realFetch = globalThis.fetch; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + calls.push({ method, url }); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "GET" && /\/mcpserverConfigs\?/.test(url)) return ok({ value: [dead, live] }); + if (method === "GET" && /\/connections\?/.test(url)) { + return ok({ value: [ + { name: "conn-dead", properties: { statuses: [{ status: "Unknown" }] } }, + { name: "conn-live", properties: { statuses: [{ status: "Connected" }] } }, + ] }); + } + if (method === "GET" && /\/connectorGateways\/[^/?]+\?/.test(url)) return ok({ location: "eastus" }); + if (method === "GET" && url.includes("/managedApis/shared-api")) { + return ok({ properties: { connectionParameters: { token: { type: "oauthSetting" } } } }); + } + if (method === "POST" && url.includes("/connections/conn-dead/listConsentLinks")) { + return { ok: false, status: 404, text: async () => "gone" }; + } + if (method === "POST" && url.includes("/connections/conn-live/listConsentLinks")) { + return ok({ value: [{ link: "https://consent.example/live" }] }); + } + if (method === "DELETE" && url.includes("/mcpserverConfigs/api-dead")) return ok({}); + if (method === "GET" && url.includes("/mcpserverConfigs/api-dead")) { + return { ok: false, status: 404, text: async () => "gone" }; + } + if (method === "DELETE" && url.includes("/connections/conn-dead")) return ok({}); + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + writeFileSync(configPath, JSON.stringify({ mcpServers: {} })); + }); + + const result = await reauthConnector(config, "shared-api", "Shared API", "https://cb/?c="); + assert.equal(result.needsConsent, true); + assert.equal(result.configName, "api-live"); + assert.equal(result.connName, "conn-live"); + assert.ok(calls.some((call) => call.url.includes("/connections/conn-dead/listConsentLinks"))); + assert.ok(calls.some((call) => call.url.includes("/connections/conn-live/listConsentLinks"))); + assert.equal(calls.some((call) => call.method === "PUT"), false, "valid siblings must prevent a fresh install"); +}); + +test("cross-process MCP config writes preserve every entry", async () => { + const configPath = join(TMP, "mcp-config.json"); + writeFileSync(configPath, JSON.stringify({ mcpServers: {} })); + const installUrl = new URL("./install.mjs", import.meta.url).href; + const names = Array.from({ length: 8 }, (_, index) => `parallel-${index}`); + + const runWriter = (name) => new Promise((resolve, reject) => { + const metadata = { + gatewayId: "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Web/connectorGateways/gateway", + mcpServerConfigId: `/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Web/connectorGateways/gateway/mcpserverConfigs/${name}`, + connectionId: `/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Web/connectorGateways/gateway/connections/${name}`, + apiName: name, + }; + const script = [ + `import { writeMcpEntry } from ${JSON.stringify(installUrl)};`, + `await writeMcpEntry(${JSON.stringify(name)}, ${JSON.stringify(`https://example.com/${name}`)}, ${JSON.stringify(`key-${name}`)}, "profile", ${JSON.stringify(metadata)});`, + ].join("\n"); + const child = spawn(process.execPath, ["--input-type=module", "--eval", script], { + env: { ...process.env, COPILOT_HOME: TMP, HOME: TMP, USERPROFILE: TMP }, + stdio: ["ignore", "ignore", "pipe"], + }); + let stderr = ""; + child.stderr.on("data", (chunk) => { stderr += chunk; }); + child.once("error", reject); + child.once("exit", (code) => { + if (code === 0) resolve(); + else reject(new Error(`config writer exited ${code}: ${stderr}`)); + }); + }); + + await Promise.all(names.map(runWriter)); + const stored = JSON.parse(readFileSync(configPath, "utf8")).mcpServers; + assert.deepEqual(Object.keys(stored).sort(), [...names].sort()); + for (const name of names) { + assert.equal(stored[name].url, `https://example.com/${name}`); + assert.equal(stored[name].headers["X-API-Key"], `key-${name}`); + assert.deepEqual(Object.keys(stored[name]).sort(), ["_connectorNamespace", "headers", "url"]); + assert.equal(stored[name]._connectorNamespace.apiName, name); + assert.match(stored[name]._connectorNamespace.gatewayId, /connectorGateways\/gateway$/); + } + assert.equal(existsSync(`${configPath}.lock`), false); + + await Promise.all(names.map((name) => removeMcpEntry(name))); + assert.deepEqual(JSON.parse(readFileSync(configPath, "utf8")).mcpServers, {}); +}); + +test("connector metadata failures are evicted and retried", async (t) => { + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "gw1" }; + const realFetch = globalThis.fetch; + let calls = 0; + globalThis.fetch = async (urlArg) => { + const url = String(urlArg); + assert.ok(!url.includes("export=true"), "swagger must not be requested when it is not required"); + calls++; + if (calls === 1) return { ok: false, status: 400, text: async () => "temporary metadata failure" }; + return { + ok: true, + status: 200, + text: async () => JSON.stringify({ properties: { connectionParameters: {} } }), + }; + }; + t.after(() => { + globalThis.fetch = realFetch; + }); + + await assert.rejects(loadConnectorMeta(config, "retry-meta", "eastus", false), /metadata failure/); + const meta = await loadConnectorMeta(config, "retry-meta", "eastus", false); + assert.equal(calls, 2); + assert.deepEqual(meta.connectionParameters, {}); +}); + +test("uninstall surfaces connection deletion failures", async (t) => { + writeFileSync( + join(TMP, "mcp-config.json"), + JSON.stringify({ mcpServers: { "docusign-bbb": { type: "http", url: "https://example/mcp" } } }), + ); + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "gw1" }; + const remoteConfig = { name: "docusign-bbb", properties: { connectors: [{ name: "docusign", connectionName: "conn-b" }] } }; + const connection = { name: "conn-b", properties: { statuses: [{ status: "Connected" }] } }; + const realFetch = globalThis.fetch; + const operations = []; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + operations.push(`${method} ${url}`); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "GET" && /\/mcpserverConfigs\?/.test(url)) return ok({ value: [remoteConfig] }); + if (method === "GET" && /\/connections\?/.test(url)) return ok({ value: [connection] }); + if (method === "DELETE" && url.includes("/mcpserverConfigs/")) return ok({}); + if (method === "GET" && url.includes("/mcpserverConfigs/")) { + return { ok: false, status: 404, text: async () => "gone" }; + } + if (method === "DELETE" && url.includes("/connections/")) { + return { ok: false, status: 400, text: async () => "delete denied" }; + } + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + }); + + await assert.rejects(uninstallConnector(config, "docusign"), /delete denied/); + const configDelete = operations.findIndex((item) => item.startsWith("DELETE ") && item.includes("/mcpserverConfigs/")); + const connectionDelete = operations.findIndex((item) => item.startsWith("DELETE ") && item.includes("/connections/")); + assert.ok(configDelete !== -1 && configDelete < connectionDelete, "configs must be confirmed deleted before their connections"); + + const pendingCleanup = join(TMP, "extensions", "connector-namespaces", "artifacts", "pending-cleanup"); + assert.equal(readdirSync(pendingCleanup).filter((name) => name.endsWith(".json")).length, 1, "failed deletion must persist enough state to retry"); + + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "GET" && /\/mcpserverConfigs\?/.test(url)) return ok({ value: [] }); + if (method === "GET" && /\/connections\?/.test(url)) return ok({ value: [] }); + if (method === "DELETE") return ok({}); + if (method === "GET" && url.includes("/mcpserverConfigs/")) { + return { ok: false, status: 404, text: async () => "gone" }; + } + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + assert.deepEqual(await uninstallConnector(config, "docusign"), { ok: true, removed: true }); + assert.equal(readdirSync(pendingCleanup).filter((name) => name.endsWith(".json")).length, 0, "successful retry must clear the cleanup journal"); +}); + +test("uninstall surfaces convergence polling failures", async (t) => { + writeFileSync( + join(TMP, "mcp-config.json"), + JSON.stringify({ mcpServers: { "docusign-bbb": { type: "http", url: "https://example/mcp" } } }), + ); + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "gw1" }; + const remoteConfig = { name: "docusign-bbb", properties: { connectors: [{ name: "docusign", connectionName: "conn-b" }] } }; + const connection = { name: "conn-b", properties: { statuses: [{ status: "Connected" }] } }; + const realFetch = globalThis.fetch; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "GET" && /\/mcpserverConfigs\?/.test(url)) return ok({ value: [remoteConfig] }); + if (method === "GET" && url.includes("/mcpserverConfigs/")) { + return { ok: false, status: 400, text: async () => "poll denied" }; + } + if (method === "GET" && /\/connections\?/.test(url)) return ok({ value: [connection] }); + if (method === "DELETE") return ok({}); + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + }); + + await assert.rejects(uninstallConnector(config, "docusign"), /poll denied/); +}); + +test("concurrent failed uninstalls retain independent retry records", async (t) => { + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "concurrent-gw" }; + const configs = [ + { name: "alpha-config", properties: { connectors: [{ name: "alpha", connectionName: "alpha-conn" }] } }, + { name: "beta-config", properties: { connectors: [{ name: "beta", connectionName: "beta-conn" }] } }, + ]; + const connections = [ + { name: "alpha-conn", properties: { statuses: [{ status: "Connected" }] } }, + { name: "beta-conn", properties: { statuses: [{ status: "Connected" }] } }, + ]; + const realFetch = globalThis.fetch; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "GET" && /\/mcpserverConfigs\?/.test(url)) return ok({ value: configs }); + if (method === "GET" && /\/connections\?/.test(url)) return ok({ value: connections }); + if (method === "DELETE" && url.includes("/mcpserverConfigs/")) return ok({}); + if (method === "GET" && url.includes("/mcpserverConfigs/")) { + return { ok: false, status: 404, text: async () => "gone" }; + } + if (method === "DELETE" && url.includes("/connections/")) { + return { ok: false, status: 400, text: async () => "delete denied" }; + } + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + }); + + const results = await Promise.allSettled([ + uninstallConnector(config, "alpha"), + uninstallConnector(config, "beta"), + ]); + assert.deepEqual(results.map((result) => result.status), ["rejected", "rejected"]); + + const pendingCleanup = join(TMP, "extensions", "connector-namespaces", "artifacts", "pending-cleanup"); + const paths = readdirSync(pendingCleanup) + .filter((name) => name.endsWith(".json")) + .map((name) => join(pendingCleanup, name)); + const records = paths.map((path) => ({ path, ...JSON.parse(readFileSync(path, "utf8")) })) + .filter((record) => record.gatewayId.includes("/connectorGateways/concurrent-gw")); + assert.deepEqual(new Set(records.map((record) => record.apiName)), new Set(["alpha", "beta"])); + for (const record of records) unlinkSync(record.path); +}); + +test("local MCP config read failures block cleanup", async () => { + const configPath = join(TMP, "mcp-config.json"); + writeFileSync(configPath, "{invalid json"); + try { + await assert.rejects(removeMcpEntry("docusign-bbb"), SyntaxError); + } finally { + writeFileSync(configPath, JSON.stringify({ mcpServers: {} })); + } +}); + +test("installed state propagates local MCP config read failures", async (t) => { + const configPath = join(TMP, "mcp-config.json"); + writeFileSync(configPath, "{invalid json"); + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "state-fail-gw" }; + const realFetch = globalThis.fetch; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "GET" && /\/mcpserverConfigs\?/.test(url)) return ok({ value: [] }); + if (method === "GET" && /\/connections\?/.test(url)) return ok({ value: [] }); + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + writeFileSync(configPath, JSON.stringify({ mcpServers: {} })); + }); + + await assert.rejects(getInstalledState(config), SyntaxError); +}); + +test("missing-connection reauth journals cleanup and the next install retries it", async (t) => { + const configPath = join(TMP, "mcp-config.json"); + writeFileSync( + configPath, + JSON.stringify({ mcpServers: { "missing-config": { type: "http", url: "https://example/mcp" } } }), + ); + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "missing-conn-gw" }; + const remoteConfig = { + name: "missing-config", + properties: { connectors: [{ name: "missing-api", connectionName: "missing-conn" }] }, + }; + const realFetch = globalThis.fetch; + let retrying = false; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "DELETE" && url.includes("/mcpserverConfigs/")) return ok({}); + if (method === "GET" && url.includes("/mcpserverConfigs/missing-config")) { + return { ok: false, status: 404, text: async () => "gone" }; + } + if (method === "DELETE" && url.includes("/connections/missing-conn")) { + return { ok: false, status: 404, text: async () => "gone" }; + } + if (retrying && method === "GET" && url.includes("/managedApis/missing-api")) { + return { ok: false, status: 400, text: async () => "stop after cleanup" }; + } + if (method === "GET" && /\/mcpserverConfigs\?/.test(url)) return ok({ value: [remoteConfig] }); + if (method === "GET" && /\/connections\?/.test(url)) return ok({ value: [] }); + if (method === "GET" && /\/connectorGateways\/[^/?]+\?/.test(url)) return ok({ location: "eastus" }); + if (method === "GET" && url.includes("/managedApis/missing-api")) return ok({ properties: {} }); + if (method === "POST" && url.includes("/connections/missing-conn/listConsentLinks")) { + writeFileSync(configPath, "{invalid json"); + return { ok: false, status: 404, text: async () => "connection gone" }; + } + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + writeFileSync(configPath, JSON.stringify({ mcpServers: {} })); + }); + + await assert.rejects( + reauthConnector(config, "missing-api", "Missing API", "https://cb/?c="), + SyntaxError, + ); + + const pendingCleanup = join(TMP, "extensions", "connector-namespaces", "artifacts", "pending-cleanup"); + const matchingRecords = () => readdirSync(pendingCleanup) + .filter((name) => name.endsWith(".json")) + .map((name) => JSON.parse(readFileSync(join(pendingCleanup, name), "utf8"))) + .filter((record) => record.gatewayId.includes("/connectorGateways/missing-conn-gw") && record.apiName === "missing-api"); + assert.equal(matchingRecords().length, 1, "failed reauth cleanup must retain retry data"); + + writeFileSync( + configPath, + JSON.stringify({ mcpServers: { "missing-config": { type: "http", url: "https://example/mcp" } } }), + ); + retrying = true; + await assert.rejects( + installConnector(config, "missing-api", "Missing API", "https://cb/?c="), + /stop after cleanup/, + ); + assert.equal(matchingRecords().length, 0, "the next install must consume successful pending cleanup"); + const localConfig = JSON.parse(readFileSync(configPath, "utf8")); + assert.equal(localConfig.mcpServers["missing-config"], undefined, "pending cleanup must remove the stale local entry"); +}); + +test("fresh-connection rollback surfaces deletion failures", async (t) => { + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "gw1" }; + const realFetch = globalThis.fetch; + globalThis.fetch = async () => ({ ok: false, status: 400, text: async () => "rollback denied" }); + t.after(() => { + globalThis.fetch = realFetch; + }); + + await assert.rejects(deleteConnection(config, "fresh-conn"), /rollback denied/); +}); + +test("finish status failures roll back the fresh connection", async (t) => { + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "gw1" }; + const realFetch = globalThis.fetch; + const calls = []; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + calls.push({ method, url }); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "GET" && url.includes("/managedApis/") && url.includes("export=true")) { + return ok({ paths: { "/mcp": { post: { operationId: "op", tags: ["agentic"] } } } }); + } + if (method === "GET" && url.includes("/managedApis/")) return ok({ properties: {} }); + if (method === "GET" && url.includes("/connections/fresh-status?")) { + return { ok: false, status: 400, text: async () => "status denied" }; + } + if (method === "DELETE" && url.includes("/connections/fresh-status?")) return ok({}); + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + }); + + await assert.rejects( + finishInstall(config, "status-fail", "Status Fail", "fresh-status", "eastus"), + /status denied/, + ); + assert.ok(calls.some((call) => call.method === "DELETE" && call.url.includes("/connections/fresh-status?"))); +}); + +test("failed config cleanup preserves its referenced connection", async (t) => { + const config = { subscriptionId: "sub1", resourceGroup: "rg1", gatewayName: "gw1" }; + const realFetch = globalThis.fetch; + const calls = []; + globalThis.fetch = async (urlArg, opts = {}) => { + const url = String(urlArg); + const method = (opts.method || "GET").toUpperCase(); + calls.push({ method, url }); + const ok = (body) => ({ ok: true, status: 200, text: async () => JSON.stringify(body) }); + if (method === "GET" && url.includes("/managedApis/") && url.includes("export=true")) { + return ok({ paths: { "/mcp": { post: { operationId: "op", tags: ["agentic"] } } } }); + } + if (method === "GET" && url.includes("/managedApis/")) return ok({ properties: {} }); + if (method === "GET" && url.includes("/connections/fresh-config?")) { + return ok({ properties: { statuses: [{ status: "Connected" }] } }); + } + if (method === "PUT" && url.includes("/mcpserverConfigs/")) { + return ok({ properties: { mcpEndpointUrl: "https://example.com/mcp" } }); + } + if (method === "POST" && url.includes("/listApiKey?")) { + return { ok: false, status: 400, text: async () => "key denied" }; + } + if (method === "DELETE" && url.includes("/mcpserverConfigs/")) { + return { ok: false, status: 400, text: async () => "config cleanup denied" }; + } + if (method === "DELETE" && url.includes("/connections/")) return ok({}); + throw new Error(`unexpected ARM call: ${method} ${url}`); + }; + t.after(() => { + globalThis.fetch = realFetch; + }); + + await assert.rejects( + finishInstall(config, "cleanup-order", "Cleanup Order", "fresh-config", "eastus"), + /config cleanup denied/, + ); + assert.ok( + !calls.some((call) => call.method === "DELETE" && call.url.includes("/connections/")), + "a surviving config must keep its referenced connection", + ); +}); diff --git a/extensions/connector-namespaces/install.test.mjs b/extensions/connector-namespaces/install.test.mjs new file mode 100644 index 00000000..5e51de54 --- /dev/null +++ b/extensions/connector-namespaces/install.test.mjs @@ -0,0 +1,253 @@ +// Regression guards for install-state selection. +// +// Run: node --test extensions/connector-namespaces/install.test.mjs +// +// These exist because getInstalledState used to collapse N gateway configs for +// one apiName down to a single tile via ARM list order (last-wins). A portal +// add, a duplicate Connect, or a re-auth would mint a sibling config; whichever +// ARM happened to return last owned the tile, so a tile could show +// "Re-authenticate" while a different config for the same connector was already +// Connected. deriveInstalledState now picks deterministically: +// inCli && Connected > inCli > Connected > any, configName wins ties. + +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; + +import { deriveInstalledState, getConsentUrl, getConnectionStatus, getMcpEndpointUrl, waitForConnected } from "./install.mjs"; + +// removeLocalEntry does file I/O (getInstalledState reads ARM + mcp configs, +// removeMcpEntry edits them) and calls both as same-module functions, so there +// is no import seam to stub. The invariant that matters — the default "Remove" +// only unlinks the CLI entry and NEVER deletes the Azure resource — is a +// source contract, so we assert it against the function body the same way +// renderer.test.mjs guards its CSS/HTML strings. +function functionBody(source, name) { + const exported = source.indexOf(`export async function ${name}(`); + const start = exported !== -1 ? exported : source.indexOf(`async function ${name}(`); + if (start === -1) return null; + const open = source.indexOf("{", start); + if (open === -1) return null; + let depth = 0; + for (let i = open; i < source.length; i++) { + const ch = source[i]; + if (ch === "{") depth++; + else if (ch === "}") { + depth--; + if (depth === 0) return source.slice(open + 1, i); + } + } + return null; +} + +const installSource = readFileSync(fileURLToPath(new URL("./install.mjs", import.meta.url)), "utf8"); + +// Build a fake ARM mcpserverConfig list entry. +function cfg(name, apiName, connName) { + return { name, properties: { connectors: [{ name: apiName, connectionName: connName }] } }; +} + +// Build a connName -> connection map with a given status. +function conns(...entries) { + const m = new Map(); + for (const [connName, status] of entries) { + m.set(connName, { name: connName, properties: { statuses: [{ status }] } }); + } + return m; +} + +test("picks inCli+Connected over a not-inCli sibling that appears LAST (not last-wins)", () => { + // good config is FIRST; a broken sibling is LAST. Old last-wins would pick + // the last one — the fix must pick the good one regardless of order. + const configs = [ + cfg("good", "shared-api", "connGood"), + cfg("bad", "shared-api", "connBad"), + ]; + const connByName = conns(["connGood", "Connected"], ["connBad", "Unknown"]); + const profileKeys = new Set(["good"]); // only the good config is in the CLI + const state = deriveInstalledState(configs, connByName, profileKeys, new Set(), null); + + assert.equal(state["shared-api"].configName, "good"); + assert.equal(state["shared-api"].connectionName, "connGood"); + assert.equal(state["shared-api"].connectionStatus, "Connected"); + assert.equal(state["shared-api"].inCli, true); + assert.equal(state["shared-api"]._configCount, 2); + assert.deepEqual(state["shared-api"]._candidates.map((item) => item.configName), ["good", "bad"]); +}); + +test("inCli beats a Connected-but-not-inCli sibling", () => { + // A is the config the local session points at but not yet Connected; B is + // Connected on ARM but not in the CLI. Prefer A so remove/re-auth act on the + // resource the user's session actually uses. + const configs = [ + cfg("a-incli", "api", "connA"), + cfg("b-connected", "api", "connB"), + ]; + const connByName = conns(["connA", "Unknown"], ["connB", "Connected"]); + const state = deriveInstalledState(configs, connByName, new Set(["a-incli"]), new Set(), null); + + assert.equal(state["api"].configName, "a-incli"); + assert.equal(state["api"].inCli, true); +}); + +test("inCli && Connected beats inCli-only", () => { + const configs = [ + cfg("incli-unknown", "api", "connU"), + cfg("incli-connected", "api", "connC"), + ]; + const connByName = conns(["connU", "Unknown"], ["connC", "Connected"]); + const state = deriveInstalledState(configs, connByName, new Set(["incli-unknown", "incli-connected"]), new Set(), null); + + assert.equal(state["api"].configName, "incli-connected"); + assert.equal(state["api"].connectionStatus, "Connected"); +}); + +test("config name breaks equal-rank ties independently of ARM list order", () => { + const configs = [ + cfg("z-config", "api", "connZ"), + cfg("a-config", "api", "connA"), + ]; + const connByName = conns(["connZ", "Connected"], ["connA", "Connected"]); + const local = new Set(["z-config", "a-config"]); + + const forward = deriveInstalledState(configs, connByName, local, new Set(), null); + const reverse = deriveInstalledState([...configs].reverse(), connByName, local, new Set(), null); + + assert.equal(forward.api.configName, "a-config"); + assert.equal(reverse.api.configName, "a-config"); +}); + +test("connection convergence reports non-connected terminal results as failures", async () => { + const states = ["Connecting", "Error"]; + const delays = []; + await assert.rejects( + waitForConnected({}, "conn", { + maxPolls: 2, + getStatus: async () => states.shift(), + delay: async (ms) => delays.push(ms), + }), + /Connection ended in state "Error"/, + ); + assert.deepEqual(delays, [1000]); + assert.equal( + await waitForConnected({}, "conn", { + getStatus: async () => "Connected", + delay: async () => assert.fail("connected state must not sleep"), + }), + "Connected", + ); +}); + +test("single config passes through with no _configCount", () => { + const configs = [cfg("only", "api", "conn1")]; + const connByName = conns(["conn1", "Connected"]); + const state = deriveInstalledState(configs, connByName, new Set(["only"]), new Set(), null); + + assert.equal(state["api"].configName, "only"); + assert.equal(state["api"]._configCount, undefined); +}); + +test("workspace membership counts as inCli and sets scope/path", () => { + const configs = [cfg("ws", "api", "conn1")]; + const connByName = conns(["conn1", "Connected"]); + const state = deriveInstalledState(configs, connByName, new Set(), new Set(["ws"]), "/repo/.mcp.json"); + + assert.equal(state["api"].inCli, true); + assert.equal(state["api"].cliScope, "workspace"); + assert.equal(state["api"].cliPath, "/repo/.mcp.json"); +}); + +test("connectionStatus falls back to overallStatus then Unknown", () => { + const configs = [cfg("c1", "api1", "connOverall"), cfg("c2", "api2", "connMissing")]; + const connByName = new Map([ + ["connOverall", { name: "connOverall", properties: { overallStatus: "Connected" } }], + ]); + const state = deriveInstalledState(configs, connByName, new Set(), new Set(), null); + + assert.equal(state["api1"].connectionStatus, "Connected"); // from overallStatus + assert.equal(state["api2"].connectionStatus, "Unknown"); // no connection at all +}); + +test("configs with no connector are skipped", () => { + const configs = [ + { name: "broken", properties: { connectors: [] } }, + cfg("ok", "api", "conn1"), + ]; + const connByName = conns(["conn1", "Connected"]); + const state = deriveInstalledState(configs, connByName, new Set(["ok"]), new Set(), null); + + assert.equal(Object.keys(state).length, 1); + assert.equal(state["api"].configName, "ok"); +}); + +test("removeLocalEntry unlinks the local CLI entry via removeMcpEntry", () => { + const body = functionBody(installSource, "removeLocalEntry"); + assert.ok(body, "removeLocalEntry function not found in install.mjs"); + assert.match(body, /removeMcpEntry\s*\(/, "removeLocalEntry must call removeMcpEntry to drop the CLI entry"); + assert.match(body, /entry\._candidates/, "removeLocalEntry must process duplicate CLI configs"); + assert.match(body, /candidate\.inCli/, "removeLocalEntry must unlink every local candidate"); +}); + +test("uninstallConnector deletes every duplicate namespace config", () => { + const body = functionBody(installSource, "uninstallConnector"); + const cleanup = functionBody(installSource, "cleanupConnectorResources"); + assert.ok(body, "uninstallConnector function not found in install.mjs"); + assert.ok(cleanup, "cleanupConnectorResources function not found in install.mjs"); + assert.match(body, /entry\._candidates/, "namespace deletion must process duplicate configs"); + assert.match(body, /cleanupConnectorResources\s*\(/, "uninstall must delegate all collected candidates to shared cleanup"); + assert.match(cleanup, /deleteMcpServerConfigs\(config, configNames\)/); + assert.match(cleanup, /for \(const connectionName of connectionNames\)/); + assert.match(cleanup, /for \(const configName of configNames\)/); +}); + +test("removeLocalEntry never deletes the namespace resource (no armDelete)", () => { + const body = functionBody(installSource, "removeLocalEntry"); + assert.ok(body, "removeLocalEntry function not found in install.mjs"); + // The default Remove must stay local-only. If someone routes it through + // uninstallConnector or adds an ARM delete, this fails — which is the point. + assert.doesNotMatch(body, /armDelete\s*\(/, "removeLocalEntry must not call armDelete"); + assert.doesNotMatch(body, /uninstallConnector\s*\(/, "removeLocalEntry must not delegate to uninstallConnector"); +}); + +// --- ARM path-injection guard (client-reachable read sinks) --- +// +// finishInstall/finishReauth feed client-supplied body.connName / body.configName +// into getConsentUrl, getConnectionStatus, and getMcpEndpointUrl, which build ARM +// URLs. Those names must pass through armSegment() so a traversal / query payload +// can't escape the intended resource path (SSRF / path injection). armSegment +// throws synchronously while the URL is built, before any token or network call, +// so these run fully offline and deterministic. A valid config is used so the +// gatewayId() wrap doesn't throw first — only the bad NAME should reject. +const validConfig = { subscriptionId: "s", resourceGroup: "r", gatewayName: "g" }; +const badNames = ["../../evil", "evil/../../secret", "x?injected=1"]; + +test("getConnectionStatus rejects traversal/injection connName before any ARM call", async () => { + for (const bad of badNames) { + await assert.rejects( + () => getConnectionStatus(validConfig, bad), + /Invalid ARM resource identifier/, + `getConnectionStatus should reject connName ${JSON.stringify(bad)}`, + ); + } +}); + +test("getConsentUrl rejects traversal/injection connName before any ARM call", async () => { + for (const bad of badNames) { + await assert.rejects( + () => getConsentUrl(validConfig, bad, "http://127.0.0.1:0/auth/callback/x"), + /Invalid ARM resource identifier/, + `getConsentUrl should reject connName ${JSON.stringify(bad)}`, + ); + } +}); + +test("getMcpEndpointUrl rejects traversal/injection configName before any ARM call", async () => { + for (const bad of badNames) { + await assert.rejects( + () => getMcpEndpointUrl(validConfig, bad), + /Invalid ARM resource identifier/, + `getMcpEndpointUrl should reject configName ${JSON.stringify(bad)}`, + ); + } +}); diff --git a/extensions/connector-namespaces/mcp-http-probe.test.mjs b/extensions/connector-namespaces/mcp-http-probe.test.mjs new file mode 100644 index 00000000..009f1086 --- /dev/null +++ b/extensions/connector-namespaces/mcp-http-probe.test.mjs @@ -0,0 +1,58 @@ +import assert from "node:assert/strict"; +import { createServer } from "node:http"; +import test from "node:test"; +import { probe } from "./test/mcp-probe.mjs"; + +test("native HTTP probe carries API key and MCP session through an SSE handshake", async (t) => { + const apiKeys = []; + const sessionIds = []; + const methods = []; + const server = createServer(async (req, res) => { + const chunks = []; + for await (const chunk of req) chunks.push(chunk); + const message = JSON.parse(Buffer.concat(chunks).toString("utf8")); + apiKeys.push(req.headers["x-api-key"]); + sessionIds.push(req.headers["mcp-session-id"] || null); + methods.push(message.method); + + if (message.method === "notifications/initialized") { + res.writeHead(202); + res.end(); + return; + } + + let result; + if (message.method === "initialize") { + res.setHeader("Mcp-Session-Id", "session-1"); + result = { + protocolVersion: "2025-06-18", + serverInfo: { name: "test-server", version: "1.0.0" }, + capabilities: { tools: {} }, + }; + } else if (message.method === "tools/list") { + result = { tools: [{ name: "ListTeams", inputSchema: { type: "object" } }] }; + } else { + result = { content: [{ type: "text", text: "ok" }] }; + } + + res.setHeader("Content-Type", "text/event-stream"); + res.end(`event: message\ndata: ${JSON.stringify({ jsonrpc: "2.0", id: message.id, result })}\n\n`); + }); + await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); + t.after(() => new Promise((resolve) => server.close(resolve))); + + const { port } = server.address(); + const result = await probe({ + apiName: "WorkIQTeams", + displayName: "WorkIQ Teams", + url: `http://127.0.0.1:${port}/mcp`, + key: "secret", + }); + + assert.equal(result.ok, true); + assert.equal(result.toolCount, 1); + assert.equal(result.toolCalled, "ListTeams"); + assert.deepEqual(methods, ["initialize", "notifications/initialized", "tools/list", "tools/call"]); + assert.deepEqual(apiKeys, ["secret", "secret", "secret", "secret"]); + assert.deepEqual(sessionIds, [null, "session-1", "session-1", "session-1"]); +}); diff --git a/extensions/connector-namespaces/package.json b/extensions/connector-namespaces/package.json new file mode 100644 index 00000000..ac0c28b0 --- /dev/null +++ b/extensions/connector-namespaces/package.json @@ -0,0 +1,19 @@ +{ + "name": "connector-namespaces", + "version": "1.1.0", + "type": "module", + "main": "extension.mjs", + "description": "Browse, connect, and open MCP connectors from your Azure Connector Namespace in Sandbox.", + "keywords": [ + "azure", + "connector-namespace", + "mcp", + "mcp-connectors", + "model-context-protocol", + "tool-discovery" + ], + "license": "MIT", + "dependencies": { + "@github/copilot-sdk": "1.0.6" + } +} diff --git a/extensions/connector-namespaces/preview/.gitignore b/extensions/connector-namespaces/preview/.gitignore new file mode 100644 index 00000000..0bac4c45 --- /dev/null +++ b/extensions/connector-namespaces/preview/.gitignore @@ -0,0 +1,2 @@ +# Screenshot evidence is throwaway, regenerated on demand by shots.mjs. +shots/ diff --git a/extensions/connector-namespaces/preview/README.md b/extensions/connector-namespaces/preview/README.md new file mode 100644 index 00000000..14b839b1 --- /dev/null +++ b/extensions/connector-namespaces/preview/README.md @@ -0,0 +1,112 @@ +# connector-namespaces preview harness + +A standalone way to **see** every canvas state without launching the Copilot +app. It imports the real, pure renderer functions from `../renderer.mjs` and +serves each state on a fixed loopback port, with every `/api/*` endpoint stubbed +so you can force the states that keep regressing (the connecting spinner and the +"Restart your Copilot session…" banner). + +This exists because those two bugs have each shipped multiple times: + +- the sign-in spinner freezing (an unscoped `animation:none` leaking out of the + reduced-motion block), and +- the restart-banner dismiss button doing nothing (a CSS specificity bug that + let `.restart-banner{display:flex}` beat `[hidden]`). + +Both are static CSS facts, so the **deterministic gate is `../renderer.test.mjs`** +(run with `node --test`). This harness is the human-visual layer on top of it: +load a state in a browser, or capture screenshots with `agent-browser`. + +## Run the preview server + +```sh +node extensions/connector-namespaces/preview/server.mjs +``` + +It binds to `http://127.0.0.1:7331`. Open that URL in any browser. The server is +a plain HTTP process (not the JSON-RPC extension provider), so it logs every hit +to stdout — that's expected and fine here. + +### State routes + +| URL | State | +| --- | --- | +| `/` or `/catalog` | Configured catalog (mock gateway + connectors) | +| `/setup` | First-run gateway picker (`renderSetupHtml`) | +| `/error` | Error screen (`renderErrorHtml`) | + +### State-forcing query flags (on the catalog route) + +The catalog page hydrates from `/api/state` on load, so loading one of these +sets the state the very next `/api/state` returns: + +| Flag | Effect | +| --- | --- | +| `/?restart=1` | `/api/state` returns `pendingRestart:true` → restart banner visible on load | +| `/?installed=1` | One connector shows as already installed/connected | + +Flags combine, e.g. `/?installed=1&restart=1`. + +> The active state is a single module-level flag (last catalog load wins). It's a +> single-user preview, so just load the page you want, then it's sticky until the +> next catalog load. + +### Stubbed endpoints + +`/api/state`, `/api/gateways`, `/api/select-gateway`, `/api/install` (returns +`needsConsent` to force the connecting spinner), `/api/finish-install`, +`/api/ack-restart` (the dismiss action), `/oauth-status` (stays pending so the +modal spinner keeps animating), `/api/uninstall`, `/api/rollback-connection`, +and `/api/open-url` (a deliberate **no-op** here — it must never actually launch +a browser tab). + +## Capture screenshots (optional) + +The screenshot driver uses [`agent-browser`](https://www.npmjs.com/package/agent-browser), +the same headless-Chromium verification tool that `arikbidny/ralph-copilot-cli` +uses. It is **not** required — if it isn't installed the driver prints an install +hint and exits 0. + +Install it once: + +```sh +npm i -g agent-browser && agent-browser install +``` + +Then, with the server running in another terminal: + +```sh +node extensions/connector-namespaces/preview/shots.mjs +``` + +Screenshots are written to `preview/shots/`: + +- `catalog.png`, `catalog-restart-banner.png`, `catalog-installed.png`, + `setup.png`, `error.png` — the static states. +- `connecting-spinner.png` — after clicking **Connect**; verify the `.si-spin` + ring is mid-rotation, not frozen. +- `banner-before-dismiss.png` / `banner-after-dismiss.png` — verify the banner is + present in the first and **gone** in the second. + +`preview/shots/` is throwaway visual evidence; it is not committed. + +## Files + +| File | Purpose | +| --- | --- | +| `server.mjs` | Standalone preview server (fixed port 7331) | +| `fixtures.mjs` | Deterministic mock subscriptions / gateways / catalog / state | +| `shots.mjs` | `agent-browser` screenshot driver (degrades gracefully) | + +## Relationship to the test guard + +`shots.mjs` proves a state *looks* right today and is handy when chasing a new +bug. It cannot prove an animation is *running* from a single frame. The +regression gate that actually blocks the recurring bugs is the CSS-structure +assertion in `../renderer.test.mjs`: + +```sh +node --test extensions/connector-namespaces/renderer.test.mjs +``` + +Keep that green; use this harness to eyeball changes. diff --git a/extensions/connector-namespaces/preview/fixtures.mjs b/extensions/connector-namespaces/preview/fixtures.mjs new file mode 100644 index 00000000..0fce100b --- /dev/null +++ b/extensions/connector-namespaces/preview/fixtures.mjs @@ -0,0 +1,117 @@ +// Deterministic fixtures for the standalone canvas preview server. +// +// These mirror the exact response shapes the inline client script in +// renderer.mjs expects, so the preview server can drive every canvas state +// (setup / catalog / error / connecting-spinner / restart-banner) with no +// Copilot app, no ARM, and no real OAuth. Keep these shapes in sync with the +// fetch() handlers in renderer.mjs if those response contracts change. + +import { CATEGORY } from "../categories.mjs"; + +export const subscriptions = [ + { id: "00000000-0000-0000-0000-000000000001", name: "Contoso Production" }, + { id: "11111111-1111-1111-1111-111111111111", name: "Contoso Dev/Test" }, +]; + +// /api/gateways?subscriptionId=... -> { gateways: [{ id, name, location }], hasMore } +// The client splits id on "/" and reads the segment after "resourceGroups", +// so the id must contain a resourceGroups segment. +export const gateways = [ + { + id: "/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/rg-connectors/providers/Microsoft.ConnectorNamespaces/connectorNamespaces/contoso-ns", + name: "contoso-ns", + location: "eastus", + }, + { + id: "/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/rg-shared/providers/Microsoft.ConnectorNamespaces/connectorNamespaces/shared-ns", + name: "shared-ns", + location: "westus2", + }, +]; + +// Active namespace shown in the catalog header (config.gatewayName / resourceGroup). +export const config = { + subscriptionId: "00000000-0000-0000-0000-000000000001", + gatewayName: "contoso-ns", + resourceGroup: "rg-connectors", +}; + +// Catalog tiles. Shape per item: { category, displayName, apiName, description, +// iconUri?, brandColor? }. At least one item must be connectable so the +// connect -> spinner flow can be exercised. +// +// The renderer routes items by category: exactly `category === CATEGORY.microsoft` +// lands in the Microsoft section, everything else in Partners. Keep a mix of +// both here so the preview exercises the full 3-section layout (My MCPs / +// Microsoft / Partners) rather than dumping every tile into one section. +export const catalog = [ + { + category: CATEGORY.microsoft, + displayName: "Microsoft Teams", + apiName: "teams", + description: "Send messages, manage chats and channels.", + brandColor: "#5059c9", + }, + { + category: CATEGORY.microsoft, + displayName: "Outlook Mail", + apiName: "outlook", + description: "Read, send, and organize email.", + brandColor: "#0a66c2", + }, + { + category: CATEGORY.microsoft, + displayName: "SharePoint", + apiName: "sharepoint", + description: "Browse sites, lists, and documents.", + brandColor: "#038387", + }, + { + category: CATEGORY.partner, + displayName: "GitHub", + apiName: "github", + description: "Manage repos, issues, and pull requests.", + brandColor: "#24292e", + }, + { + category: CATEGORY.partner, + displayName: "Stripe", + apiName: "stripe", + description: "Payments, customers, and invoices.", + brandColor: "#635bff", + }, +]; + +// /api/state -> { state: { apiName: InstallState }, pendingRestart } +// InstallState: { installed, connectionStatus, inCli, cliPath?, cliScope? } +// Default state: nothing installed, no pending restart. The catalog renders +// every tile with a "Connect" button. +export const stateEmpty = { + state: {}, + pendingRestart: false, +}; + +// One connector already added (shows "Added" + Remove), restart pending so the +// banner is visible on load. Drives both the "added" tile and the banner state. +export const stateInstalledRestart = { + state: { + sharepoint: { + installed: true, + connectionStatus: "Connected", + inCli: true, + cliPath: "~/.copilot/mcp-config.json", + cliScope: "profile", + }, + }, + pendingRestart: true, +}; + +// Install response that forces the connecting flow. needsConsent keeps the +// sign-in modal (with the .si-spin spinner) open; /oauth-status then stays +// pending so the spinner keeps animating for a screenshot. +export const installNeedsConsent = { + needsConsent: true, + connName: "preview-conn", + consentUrl: "http://127.0.0.1:7331/fake-consent", + location: "eastus", +}; diff --git a/extensions/connector-namespaces/preview/server.mjs b/extensions/connector-namespaces/preview/server.mjs new file mode 100644 index 00000000..d56a14c6 --- /dev/null +++ b/extensions/connector-namespaces/preview/server.mjs @@ -0,0 +1,151 @@ +// Standalone preview server for the connector-namespaces connector catalog. +// +// Renders every canvas state with no Copilot app, no ARM, and no real OAuth by +// importing the *pure* HTML builders from renderer.mjs and stubbing every +// /api/* endpoint the inline client script calls. Point any browser (or the +// agent-browser driver in shots.mjs) at it to see exactly what ships. +// +// Run: node extensions/connector-namespaces/preview/server.mjs +// Then open http://127.0.0.1:7331/ (catalog), /setup, /error. +// +// This process is NOT the JSON-RPC extension provider, so console.log here is +// fine and intentional — it is how you watch which stubbed endpoints get hit. + +import { createServer } from "node:http"; + +import { + renderCatalogHtml, + renderSetupHtml, + renderErrorHtml, +} from "../renderer.mjs"; +import * as fixtures from "./fixtures.mjs"; + +const HOST = "127.0.0.1"; +const PORT = 7331; +const INSTANCE = "preview"; + +// Whatever /api/state should report next. The catalog route updates this from +// its query flags so a page load can force the banner / "added" tile on, and a +// real Connect click flips pendingRestart on via showRestartBanner(). +let activeState = fixtures.stateEmpty; + +function selectState(query) { + const restart = query.get("restart") === "1"; + const installed = query.get("installed") === "1"; + if (restart && installed) return fixtures.stateInstalledRestart; + if (installed) return { state: fixtures.stateInstalledRestart.state, pendingRestart: false }; + if (restart) return { state: {}, pendingRestart: true }; + return fixtures.stateEmpty; +} + +function sendHtml(res, body) { + res.setHeader("Content-Type", "text/html; charset=utf-8"); + res.end(body); +} + +function sendJson(res, obj, status = 200) { + res.statusCode = status; + res.setHeader("Content-Type", "application/json"); + res.end(JSON.stringify(obj)); +} + +async function readBody(req) { + const chunks = []; + for await (const chunk of req) chunks.push(chunk); + if (!chunks.length) return {}; + try { + return JSON.parse(Buffer.concat(chunks).toString("utf8")); + } catch { + return {}; + } +} + +const server = createServer(async (req, res) => { + const url = new URL(req.url, `http://${HOST}:${PORT}`); + const path = url.pathname; + const q = url.searchParams; + // Strip CR/LF/tab so a crafted request line can't forge extra log entries. + console.log(`${req.method} ${req.url}`.replace(/[\r\n\t]/g, " ")); + + // --- Page routes --------------------------------------------------------- + if (req.method === "GET" && (path === "/" || path === "/catalog")) { + activeState = selectState(q); + return sendHtml( + res, + renderCatalogHtml(INSTANCE, fixtures.catalog, { + filter: q.get("filter") || "", + category: q.get("category") || "all", + source: q.get("source") || "", + config: fixtures.config, + }), + ); + } + if (req.method === "GET" && path === "/setup") { + return sendHtml(res, renderSetupHtml(fixtures.subscriptions)); + } + if (req.method === "GET" && path === "/error") { + return sendHtml(res, renderErrorHtml(q.get("message") || "Something went wrong loading connectors.")); + } + if (req.method === "GET" && path === "/fake-consent") { + return sendHtml(res, "ConsentFake Microsoft consent page (preview). Close this tab."); + } + + // --- Stubbed API endpoints ---------------------------------------------- + if (req.method === "GET" && path === "/api/state") { + return sendJson(res, activeState); + } + if (req.method === "GET" && path === "/api/gateways") { + return sendJson(res, { gateways: fixtures.gateways, hasMore: false }); + } + if (req.method === "GET" && path === "/oauth-status") { + // Stay pending forever so the connecting spinner keeps animating for a + // screenshot. Flip to { done: true } if you want the full success flow. + return sendJson(res, { done: false }); + } + + if (req.method === "POST") { + await readBody(req); + switch (path) { + case "/api/select-gateway": + return sendJson(res, { ok: true }); + case "/api/install": + return sendJson(res, fixtures.installNeedsConsent); + case "/api/finish-install": + activeState = { ...activeState, pendingRestart: true }; + return sendJson(res, { ok: true }); + case "/api/ack-restart": + activeState = { ...activeState, pendingRestart: false }; + return sendJson(res, { ok: true }); + case "/api/uninstall": + return sendJson(res, { ok: true }); + case "/api/open-url": + // Preview no-op: do NOT actually launch a browser tab. + return sendJson(res, { ok: true }); + case "/api/rollback-connection": + return sendJson(res, { ok: true }); + default: + return sendJson(res, { error: `unstubbed POST ${path}` }, 404); + } + } + + res.statusCode = 404; + res.end("not found"); +}); + +server.on("error", (err) => { + if (err.code === "EADDRINUSE") { + console.error(`Port ${PORT} is already in use. Stop the other process or change PORT in server.mjs.`); + process.exit(1); + } + throw err; +}); + +server.listen(PORT, HOST, () => { + console.log(`canvas preview server: http://${HOST}:${PORT}/`); + console.log(" / catalog (empty state)"); + console.log(" /?restart=1 catalog with restart banner visible"); + console.log(" /?installed=1 catalog with one connector added"); + console.log(" /setup namespace picker"); + console.log(" /error error state"); + console.log("Press Ctrl+C to stop."); +}); diff --git a/extensions/connector-namespaces/preview/shots.mjs b/extensions/connector-namespaces/preview/shots.mjs new file mode 100644 index 00000000..aab8f17b --- /dev/null +++ b/extensions/connector-namespaces/preview/shots.mjs @@ -0,0 +1,96 @@ +// agent-browser screenshot driver for the canvas preview server. +// +// Captures every canvas state to ./shots/ and drives the two interaction flows +// that keep regressing: +// 1. catalog -> click Connect -> sign-in modal with the spinning .si-spin +// 2. restart banner visible -> click dismiss -> banner gone +// +// Requires the preview server to be running: +// node extensions/connector-namespaces/preview/server.mjs +// And agent-browser installed: +// npm i -g agent-browser && agent-browser install +// +// If agent-browser is not installed, this script prints how to install it and +// exits 0 (so it never breaks an unattended run). This is a visual-evidence +// helper; the deterministic regression gate is renderer.test.mjs. + +import { spawnSync } from "node:child_process"; +import { mkdirSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const SHOTS = join(HERE, "shots"); +const BASE = "http://127.0.0.1:7331"; + +function hasAgentBrowser() { + const probe = spawnSync("agent-browser", ["--version"], { encoding: "utf8", shell: true }); + return probe.status === 0; +} + +function ab(args) { + const r = spawnSync("agent-browser", args, { encoding: "utf8", shell: true }); + if (r.status !== 0) { + console.error(`agent-browser ${args.join(" ")} failed:\n${r.stderr || r.stdout}`); + } + return r; +} + +function serverUp() { + // Node 18+ has global fetch. Confirm the preview server is reachable. + return fetch(`${BASE}/api/state`).then(() => true).catch(() => false); +} + +async function main() { + if (!hasAgentBrowser()) { + console.log("agent-browser is not installed -> skipping screenshots."); + console.log("Install it with: npm i -g agent-browser && agent-browser install"); + console.log("Then re-run: node extensions/connector-namespaces/preview/shots.mjs"); + process.exit(0); + } + + if (!(await serverUp())) { + console.error("preview server is not reachable at " + BASE); + console.error("start it first: node extensions/connector-namespaces/preview/server.mjs"); + process.exit(1); + } + + mkdirSync(SHOTS, { recursive: true }); + + // Static states. + const states = [ + ["catalog", `${BASE}/`], + ["catalog-restart-banner", `${BASE}/?restart=1`], + ["catalog-installed", `${BASE}/?installed=1`], + ["setup", `${BASE}/setup`], + ["error", `${BASE}/error`], + ]; + for (const [name, target] of states) { + ab(["open", target]); + ab(["screenshot", join(SHOTS, `${name}.png`)]); + console.log(`captured ${name}`); + } + + // Flow 1: connect -> connecting spinner. The preview /api/install returns + // needsConsent and /oauth-status stays pending, so the .si-spin modal + // spinner keeps animating. Best-effort selector; adjust if markup changes. + ab(["open", `${BASE}/`]); + ab(["click", ".item-add[data-api]"]); + ab(["screenshot", join(SHOTS, "connecting-spinner.png")]); + console.log("captured connecting-spinner (verify the spinner is mid-rotation)"); + + // Flow 2: banner -> dismiss -> gone. Screenshot before and after the click + // so a frozen/broken dismiss button is visible as a diff. + ab(["open", `${BASE}/?restart=1`]); + ab(["screenshot", join(SHOTS, "banner-before-dismiss.png")]); + ab(["click", ".restart-banner .rb-dismiss"]); + ab(["screenshot", join(SHOTS, "banner-after-dismiss.png")]); + console.log("captured banner-before-dismiss / banner-after-dismiss (after should have no banner)"); + + console.log(`\nshots written to ${SHOTS}`); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/extensions/connector-namespaces/renderer.mjs b/extensions/connector-namespaces/renderer.mjs new file mode 100644 index 00000000..e4ddf609 --- /dev/null +++ b/extensions/connector-namespaces/renderer.mjs @@ -0,0 +1,1563 @@ +// Renderers for the connector namespace picker and connector catalog pages. +// Styled to match the reference connector extension UI. + +import { CATEGORY } from "./categories.mjs"; +import { buildSandboxUrl } from "./sandbox.mjs"; + +const CONNECT_ICON = ''; + +// Official Azure Connector Namespace mark — a gray viewfinder frame wrapping +// two interlocking blue-gradient chain links. Path + gradient data is lifted +// verbatim from the portal's ConnectorNamespaceIcon brand asset. idSuffix keeps +// the gradient element IDs unique when the mark renders more than once per page. +export function brandMark(size = 28, idSuffix = "m") { + const g0 = `cn-g0-${idSuffix}`; + const g1 = `cn-g1-${idSuffix}`; + return ``; +} + +export function baseStyles() { + return ``; +} + +// --------------------------------------------------------------------------- +// Setup / Namespace Picker +// --------------------------------------------------------------------------- + +export function renderSetupHtml(subscriptions, notice = "", capabilityToken = "") { + const subOptions = subscriptions.map((s) => + `` + ).join(""); + + return ` + +Select Connector Namespace${baseStyles()} + +
+

${brandMark(30, "setup")}Select a Connector Namespace

+
Choose which connector namespace to browse. This choice is saved for future sessions.
+
+${notice ? `
${esc(notice)}
` : ""} +
+ +
+
+ + +
+ +
+
Select a subscription to see available connector namespaces.
+
+`; +} + +// --------------------------------------------------------------------------- +// Catalog +// --------------------------------------------------------------------------- + +const CSS_HEX_COLOR = /^#[0-9a-fA-F]{6}$/; + +function iconBackgroundStyle(brandColor) { + const color = String(brandColor || "").trim(); + return CSS_HEX_COLOR.test(color) ? ` style="background:${color}22"` : ""; +} + +export function renderCatalogHtml(instanceId, catalog, { filter, category, source, config }, capabilityToken = "") { + const renderItem = (c) => { + // Items carry their home grid so hydrateState can move them into + // "My MCPs" when added and back to Microsoft/Partner on remove. + const home = c.category === CATEGORY.microsoft ? "microsoft" : "partner"; + const icon = c.iconUri + ? `
` + : `
${esc(c.displayName.charAt(0))}
`; + // Button state is hydrated client-side from /api/state on load. + const btn = ``; + const haystack = esc((c.displayName + " " + (c.description || "")).toLowerCase()); + const sandboxUrl = esc(buildSandboxUrl(config, c.apiName)); + return `
${icon}
${esc(c.displayName)}
${esc(c.description)}
${btn}
`; + }; + + const byName = (a, b) => a.displayName.localeCompare(b.displayName); + const microsoft = catalog.filter((c) => c.category === CATEGORY.microsoft).sort(byName); + const partner = catalog.filter((c) => c.category !== CATEGORY.microsoft).sort(byName); + + const section = (key, title, rows, { collapsed, hidden }) => { + const cls = ["section", "collapsible"]; + if (collapsed) cls.push("collapsed"); + if (hidden) cls.push("is-hidden"); + const n = rows.length; + return `
` + + `` + + `
${rows.map(renderItem).join("")}
` + + `
`; + }; + + // Server paints the first-run layout: My MCPs hidden+empty (filled by + // hydrateState), Microsoft expanded so there's something to browse, Partner + // collapsed. updateSections() flips to the steady layout on the first hydrate + // if anything is already added. + let sectionsHtml = + section("mine", "My MCPs", [], { collapsed: false, hidden: true }) + + section("microsoft", "Microsoft", microsoft, { collapsed: false, hidden: microsoft.length === 0 }) + + section("partner", "Partners", partner, { collapsed: true, hidden: partner.length === 0 }); + + if (!catalog.length) { + sectionsHtml = `
No connectors available.
`; + } + + return ` + +Connectors${baseStyles()} + +
+
+

${brandMark(24, "cat")}Connectors

+
+
Namespace ${esc(config.gatewayName)} · RG ${esc(config.resourceGroup)}
+
+ + + +
+
+
+ + + + +
+ +${sectionsHtml} + +`; +} + +// --------------------------------------------------------------------------- +// Error +// --------------------------------------------------------------------------- + +export function renderErrorHtml(message) { + return ` +Error${baseStyles()} +

Error

+
${esc(message)}
+`; +} + +// --------------------------------------------------------------------------- +function esc(s) { + return String(s ?? "").replace(/[&<>"']/g, (c) => ({"&":"&","<":"<",">":">",'"':""","'":"'"}[c])); +} diff --git a/extensions/connector-namespaces/renderer.test.mjs b/extensions/connector-namespaces/renderer.test.mjs new file mode 100644 index 00000000..d0c464e4 --- /dev/null +++ b/extensions/connector-namespaces/renderer.test.mjs @@ -0,0 +1,393 @@ +// Regression guards for the connector-catalog renderer. +// +// Run: node --test extensions/connector-namespaces/renderer.test.mjs +// +// These tests exist because two UX bugs kept coming back: +// 1. A `@media (prefers-reduced-motion: reduce)` rule froze functional +// loaders without a visible fallback. Reduced motion now stops the +// animation while forcing each loader into a visible static busy state; +// nearby text continues to communicate progress. +// 2. The "Restart your Copilot session" banner ignoring Dismiss. The real +// root cause was CSS specificity: `.restart-banner{display:flex}` is an +// author rule with the same (0,1,0) specificity as the UA +// `[hidden]{display:none}` rule, so it overrode the hidden attribute and +// `restartBanner.hidden=true` did nothing. The fix is a global +// `[hidden]{display:none !important}` reset. A client-side +// `restartDismissed` flag also keeps a late hydrateState() from re-showing +// it. The guards below fail if either the CSS reset or the JS gate +// disappears. + +import { test } from "node:test"; +import assert from "node:assert/strict"; + +import { baseStyles, renderCatalogHtml, renderSetupHtml } from "./renderer.mjs"; +import { renderCreateNamespaceHtml } from "./createPage.mjs"; +import { CATEGORY } from "./categories.mjs"; + +// Pull the balanced body of the prefers-reduced-motion media block out of a +// stylesheet string (non-greedy regex can't handle the nested rule braces). +// CSS comments are stripped so the guards test declarations rather than prose. +function reducedMotionBlock(css) { + const start = css.indexOf("@media (prefers-reduced-motion: reduce)"); + if (start === -1) return null; + const open = css.indexOf("{", start); + if (open === -1) return null; + let depth = 0; + for (let i = open; i < css.length; i++) { + if (css[i] === "{") depth++; + else if (css[i] === "}" && --depth === 0) { + return css.slice(open + 1, i).replace(/\/\*[\s\S]*?\*\//g, ""); + } + } + return null; +} + +function catalogHtml() { + return renderCatalogHtml("test-instance", [], { + filter: "", + category: "all", + source: "", + config: { subscriptionId: "sub", gatewayName: "ns", resourceGroup: "rg" }, + }); +} + +test("setup subscription label names its select", () => { + const html = renderSetupHtml([], "", "token"); + assert.match(html, /