Skip to content

Add flightcheck developer guide (AGENTS.md) - #38

Closed
Graham McMynn (GrahamMcMynn) wants to merge 37 commits into
main2from
users/grahamc/flightcheck-developer-guidance
Closed

Add flightcheck developer guide (AGENTS.md)#38
Graham McMynn (GrahamMcMynn) wants to merge 37 commits into
main2from
users/grahamc/flightcheck-developer-guidance

Conversation

@GrahamMcMynn

Copy link
Copy Markdown
Collaborator

Summary

Adds a developer guide scoped to the flightcheck tool at \scripts/flightcheck/AGENTS.md. This documents the knowledge needed to efficiently add new checks without trial-and-error against live APIs.

Motivation

While implementing CONFIG-013 (PR #37), significant time was spent:

  • Trying the wrong API (Dataverse \�otcomponents.data\ is YAML config, not status)
  • Discovering the Island Gateway API exists and is the correct source for runtime state
  • Finding the required \x-cci-*\ headers via an external repo
  • Learning that BAP env ID Dataverse env ID

This guide captures those learnings so the next check can be implemented correctly on the first attempt.

Contents

  • Architecture Overview table mapping API layers to clients, auth scopes, and available data
  • Island Gateway API Reference — endpoint, headers, env ID discovery, response structure
  • Dataverse \�otcomponents\ Entity key gotchas (YAML not JSON, no \msdyn_\ prefix, statecode crawl status)
  • Design Principles no misleading results, fail loudly, no fabricated URLs
  • Adding a New Check step-by-step checklist including guidance for when a new API is needed

saengland and others added 30 commits April 8, 2026 13:26
- Add standard Microsoft MIT license (closes #1)
- Allow LICENSE and SECURITY.md through .gitignore allowlist
…fd-c784-48eb-b13c-715927704369

Adding Microsoft SECURITY.MD
- Add componenttype 19 (Test Case) support to extraction pipeline
- setup.py: evaluations/ folder, parentbotcomponentid tracking, snapshot section, evaluationCount in config
- fetch_and_setup.py: include _parentbotcomponentid_value in REST query
- push.py: two-pass CREATE (parent EvaluationSet first, then children with ParentBotComponentId@odata.bind), child-before-parent DELETE ordering, mspva_{uuid} schema naming
- Restructure skills: evaluate/ -> evaluations/create/, add evaluations/update/ and evaluations/delete/
- Update copilot-instructions.md routing table
- Add structured ISU auth debugging reference doc with error-to-config lookup tables
- Create troubleshoot skill for diagnosing connectivity/auth failures
- Wire up agent routing with trigger phrases for common error strings
- Cross-link from workday.md and known-issues-limitations.md
- Add scripts/discover.py for agent discovery via REST API + MSAL auth
- Rewrite step1b.md: replace ~250 lines of MCP tool juggling with simple script calls
- Remove MCP server start as prerequisite for discovery (step1.md)
- Make MCP server start a blocking step 4 in setup (step2.md)
- Add 4th checklist item: MCP server started
- Rename checklist step 1 from 'Dataverse MCP connected' to 'Dataverse configured'

Fixes setup failures on lesser-capable models (Haiku, GPT-4o-mini) that
could not reliably load deferred MCP tools or navigate branching recovery logic.
- Add ServiceNow MCP server (src/mcp/servicenow/) with Table API client,
  ITSM, HRSD, CMDB, catalog, user, and OAuth/OIDC tools
- Add /connect skill with auth-specific step files:
  step1 (instance info + MCP setup), step2-oauth2 (automated OAuth app
  creation), step3-oauth2/step3-basic (extension pack install), step4 (verify)
- Automate OAuth2 setup: pre-generate client secret, create app registry
  via MCP, set token lifespans, set redirect URL by PP region
- Add connect.prompt.md for /connect command
- Update copilot-instructions.md with connect skill routing + triggers
- Use vscode_askQuestions for onboarding and connect question flows
- Add no-leak rule to all step files (no internal variable names in chat)
- New shared azure/ skills: login.md (device code flow), app-registration.md (6-step Entra app setup)
- New servicenow/step2-entra.md: orchestrates Azure login + app reg + ServiceNow OIDC config
- New servicenow/step3-entra.md: extension pack install with Entra creds (3 fields)
- Modified step1.md: removed Entra downgrade gate, added entra routing branch
…e), fix oidc_provider oidc_provider_configuration field name
…st-class section with full steps, reorder auth methods
…ntro to explain we're pulling new ServiceNow components
- New step2-graph.md: OIDC provider, integration user, roles, ACL setup via temp Scripted REST API
- New step3-graph.md: M365 Admin Center + Copilot Studio knowledge source walkthrough
- Modified step1.md: connector type question (Actions/Knowledge/Both), routing for graph path
- New call_api tool in server.py: generic REST call using existing MCP auth session
- Reference docs: servicenow-knowledge-deployment.md, servicenow-knowledge-troubleshooting.md, servicenow-connector-setup-scripts.md
…ding flows

Phase 1 - Consent gates:
- app-registration.md: consent before Entra app creation (B.2) and config (B.3-B.6)
- step2-entra.md: consent before SNOW user creation (2.3) and OIDC setup (2.4)
- step2-oauth2.md: consent before OAuth app creation (2.3)
- step2-graph.md: comprehensive consent before Graph Connector setup (2.3-2.8)

Phase 2 - Progress narration:
- All progress messages annotated with 'do NOT wait for user response'
- Timing estimates added to discovery, extraction, and re-extraction steps
- Summary tables added after multi-step sequences

Phase 4 - Rollback and cleanup:
- app-registration.md: B.8 cleanup section with az ad app delete
- step2-entra.md: 2.8 cleanup for test user and OIDC entity
- step2-graph.md: 2.8e fixed to run on failure; 2.10 full cleanup reference
- Incremental config saves after each environment mutation
- Add step2-certificate.md: full certificate auth setup (two Entra apps,
  OIDC provider, system user, self-signed cert generation)
- Add step3-certificate.md: extension pack install with certificate fields,
  auto-open File Explorer for PFX upload, ITSM field name clarification
- Update step1.md (connect router): add reconfigure/reconnect options when
  ServiceNow is already connected, support PRE_SELECTED_INTEGRATION arg
- Update servicenow/step1.md: add certificate option to auth question and
  routing table
- Update SKILL.md: add integration arg passthrough, complete routing table
  with all auth-specific step files
- Update servicenow-hrsd-itsm.md: clarify HRMS plugin activation and OIDC
  table create behavior
…tall

- Add Workday MCP server (SOAP, RaaS, worker data, connection testing)
- Add /connect workday flow (step1: gather info, step2: admin setup, step3: verify + extension pack)
- Verify-first pattern: run API checks before portal tasks, skip pre-configured items
- Two API client paths: SAML Bearer Grant for Entra SSO, Auth Code Grant for Basic
- Extension pack install: connections, env vars, cloud flows, topic redirect
- Entra app role assignment check before connection creation
- Update SKILL.md with Workday routing and key principles
- Update README with ServiceNow and Workday integration docs
Replace real tenant/domain references (microsoft_dpt6, EmployeeHub.onmicrosoft.com)
with generic placeholders to avoid GitHub secret scanner false positives.
Key changes:
- Entra SSO is now mandatory (not optional) — OAuthUser connection uses runtimeSource:invoker
- Three connections require three different auth types (Basic/Basic/Entra SSO)
- Step 1: Auto-detects existing state (Entra app, extension pack, RaaS report) via Azure CLI + Dataverse MCP
- Step 2: Removed flawed pre-flight that tested with MCP admin creds instead of ISU creds. Idempotent ISU creation. Never skip domain permissions. Full permission list including Worker Data: Compensation
- Step 3: Explicit connection creation table with naming guidance and auto-fill warning. Topic redirect auto-pushed via push.py. 7-point post-install verification. End-to-end test prompts
- SKILL.md: Updated routing and key principles
- copilot-instructions.md: Added SSO requirement and 3-connection-types rule
Port ESS Pre-flight Validator into the kit as a Python-native skill.
Runs 41+ automated checks across 8 categories: prerequisites, environment,
authentication, external systems, Workday deep validation (17 SOAP workflow
tests), multi-agent local file validation, and publishing readiness.

New files:
- scripts/flightcheck/ — Python CLI + check modules (Graph, PP Admin, Workday SOAP, local files)
- src/skills/flightcheck/SKILL.md — conversational skill with HTML report + auto-fix offer
- .github/prompts/flightcheck.prompt.md — /flightcheck command
- src/reference/ess-docs/flightcheck/ — validation matrix, remediation guide, permissions, report template

Integration:
- /setup Step 5 (optional) — offers readiness check after agent extraction
- /menu — added /flightcheck command
- /troubleshoot — cross-link to suggest flightcheck first
- /connect workday — post-install suggestion to verify with flightcheck

Features:
- Multi-agent: scans all agents under my/agents/
- HTML report: auto-opens in browser, archived to history/
- Workday creds: reads base URL + tenant from .vscode/mcp.json, prompts for ISU password (never saved)
- Graceful degradation: runs whatever permissions allow, skips the rest
- Remediation links: clickable portal/docs links in every result
setup.py now maintains an agents[] array in my/config.json alongside
the backward-compatible agent field. Each /setup run adds the agent to
the array and sets activeAgent. Existing scripts (push, checkpoint,
fetch_and_setup) and all 15 skill files continue reading agent.* with
zero changes. FlightCheck banner shows all discovered agents.
- Add CONTRIBUTING.md with Microsoft CLA boilerplate
- Add CODE_OF_CONDUCT.md referencing Microsoft Open Source Code of Conduct
- Add SUPPORT.md with GitHub Issues guidance
- Add copyright headers to all 26 Python source files
- Update .gitignore allowlist for new boilerplate files
- Update README.md: replace 'Microsoft Internal' license with MIT, add Trademarks section, update Contributing section to link CONTRIBUTING.md and CLA
- Add .github/workflows/codeql.yml for CodeQL security scanning (Python)
- Add .github/workflows/ci.yml for lint and syntax check
- Add .github/dependabot.yml for weekly Python and GitHub Actions updates
- Scrub: replace internal Workday tenant 'microsoft_dpt6' with 'contoso_impl' in connect docs
- Add .github/ISSUE_TEMPLATE/bug_report.yml (structured bug report form)
- Add .github/ISSUE_TEMPLATE/feature_request.yml (feature request form)
- Add .github/ISSUE_TEMPLATE/question.yml (question/help form)
- Add .github/ISSUE_TEMPLATE/config.yml (disable blank issues, link to MSRC for security)
- Add .github/PULL_REQUEST_TEMPLATE.md (PR checklist with CLA reminder)
- Add .github/labels.yml (canonical label set documentation)

Labels also applied to repo via gh CLI (16 total).
…r non-production samples-style repos. Closes ADO 7314650.
saengland and others added 6 commits April 29, 2026 15:59
…CONTRIBUTING.md (closes ADO 7313407, 7313408)
…UTING.md; add Supported/Unsupported scenarios to README. Closes ADO 7313434, 7313435, 7313437, 7313438.
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Documents the API architecture, Island Gateway reference, Dataverse
entity gotchas, design principles, and checklist for adding new checks.
Scoped to scripts/flightcheck/ so it's discoverable when working on
the flightcheck tool specifically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@johnguy0 John Nguyen (johnguy0) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc is genuinely useful — it captures the gotchas you spent CONFIG-013 hours on, and that's exactly the kind of thing that pays for itself the next time someone adds a check. Two structural things worth tightening before merge:

  1. The "Dataverse = configured, Gateway = working" framing in the Architecture Overview doesn't match what the kit actually does today. Configured state in this kit comes from local YAML files (scripts/flightcheck/checks/local_files.py), not from Dataverse. If a future check author follows this guide literally, we'll get a duplicate Dataverse query for something already validated locally — two sources of truth that can disagree.

  2. The "attached to runner" pattern is documented but the shape of runner isn't declared anywhere. New contributors have to read cli.py to know what's on it. Either enumerate the attributes here (runner.config, runner.env_url, runner.dv_token, runner.env_id, runner.graph, runner.pp_admin, runner.pva) or — better — declare them as typed Optional fields on FlightCheckRunner in runner.py so they're discoverable from the type.

The "No misleading results" principle is the most valuable thing in this doc. Don't lose it in the cleanup. Inline nits on file paths.

Comment thread scripts/flightcheck/AGENTS.md Outdated
Comment thread scripts/flightcheck/AGENTS.md Outdated
Comment thread scripts/flightcheck/AGENTS.md

@johnguy0 John Nguyen (johnguy0) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing security-relevant in this PR. Worth noting for the record:

  • The shared MSAL token cache at my/.token_cache.bin is referenced as a contributor pattern. Already covered by my/** in .gitignore, so no leak risk.
  • 96ff4394-9197-43aa-b393-6a41652e21f8 is the public Power Virtual Agents 1P app ID, not a secret.
  • No untrusted input flowing anywhere. No new dependencies.

Deferring to other personas.

@johnguy0 John Nguyen (johnguy0) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc-only PR, no perf angle. The closest thing is the documented "Read all bot components" call which has no pagination, but that's a faithful description of how the Island Gateway endpoint actually behaves — not something this doc introduced. Deferring.

@johnguy0 John Nguyen (johnguy0) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid reference material — exactly the kind of doc that pays for itself the next time. Two things worth tightening so a contributor can actually act on the steps:

  1. Status taxonomy is under-specified. Principle 1 only mentions SKIPPED vs PASSED, but the runner exposes five statuses (SKIPPED, NOT_CONFIGURED, WARNING, FAILED, ERROR) and existing checks split between them in ways this doc doesn't capture. Inline comment with the decision tree.

  2. "Adding a New Check" assumes you know the CheckResult shape. Steps 3–5 say "add a check function" without showing one. Drop in a 5-line minimal example so a contributor doesn't have to grep around — that's the trial-and-error this doc is meant to prevent. Inline.

Comment thread scripts/flightcheck/AGENTS.md Outdated
Comment thread scripts/flightcheck/AGENTS.md
Comment thread scripts/flightcheck/AGENTS.md
- Clarify auth.py path (lives at scripts/auth.py, imported via sys.path)
- Rewrite data layer framing as three-way split: Local YAML / Dataverse / Island Gateway
- Fix componenttype values (9=Topic, 12=Variable, not 1/68)
- Add full status decision tree (PASSED/FAILED/WARNING/SKIPPED/NOT_CONFIGURED/ERROR)
- Add runner attributes table with types and descriptions
- Add minimal code example showing CheckResult construction
- Soften  list to 'common kinds include' (API may return others)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@johnguy0 John Nguyen (johnguy0) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I re-reviewed the delta since 91e4784. The earlier feedback is addressed. One new docs accuracy issue remains in the runner attributes table because it documents a client that is not present or wired. Not ready yet.

| `runner.env_id` | `str` | Power Platform (BAP) environment ID |
| `runner.graph` | `GraphClient \| None` | Microsoft Graph client |
| `runner.pp_admin` | `PowerPlatformAdminClient \| None` | BAP admin client |
| `runner.pva` | `PVAClient \| None` | Island Gateway client |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runner.pva is not wired today: cli.py only attaches graph and pp_admin, and this branch has no pva_client.py. Remove this row or add the client and runner wiring before using it in the guide.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graham McMynn (@GrahamMcMynn) - confirmed: this branch has no pva_client.py (it lands in PR #37) and cli.py here only wires runner.graph + runner.pp_admin. There's a second doc-accuracy bug in the same table while we're here: runner.pp_admin is documented as PowerPlatformAdminClient, but the actual class in pp_admin_client.py is PPAdminClient.

Suggested fix:

 | `runner.graph` | `GraphClient \| None` | Microsoft Graph client |
-| `runner.pp_admin` | `PowerPlatformAdminClient \| None` | BAP admin client |
-| `runner.pva` | `PVAClient \| None` | Island Gateway client |
+| `runner.pp_admin` | `PPAdminClient \| None` | BAP admin client |
 | `runner.config` | `dict` | Parsed `my/config.json` |

And the matching reference at line 126:

-   same structure as `graph_client.py` / `pp_admin_client.py` / `pva_client.py`
+   same structure as `graph_client.py` / `pp_admin_client.py`

Add runner.pva and the pva_client.py reference back when PR #37 merges (or in the same merge if they go in together).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will not address this comment. The issue is I need to merge #37 first.

@saengland saengland left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed AGENTS.md as the contract for future check authors. The structure (architecture, runner attributes, design principles, checklist) is right, but it documents the world that exists in PR #37, not the world that exists on main, and the security section has a critical gap. 5 findings:

# Sev Issue
1 HIGH pva_client.py referenced as if it exists on main; only lives in PR #37
2 HIGH runner.pva: PVAClient | None documented but cli.py never sets it
3 HIGH Zero security guidance for the bug classes round-8 of PR #29 just fixed (defusedxml, retry adapter, CWE-209 scrubbing, HTTPS validation on operator URLs)
4 MEDIUM Checklist step 4 doesn''t actually tell authors how to wire a new scope (FULL_SCOPE / SCOPE_MAP in cli.py)
5 LOW 12 em-dash chars throughout - kit convention is ASCII only

#1, #2, #3 are blockers. The security section gap is the biggest one - this guide will be the first thing the next check author reads, and it should encode the lessons we just paid for.

| Dataverse | `../auth.py` | `{env_url}/user_impersonation` | Bot components (topics, variables, knowledge source *config*), template configs, solution metadata, statecode (enabled/disabled) |
| Microsoft Graph | `graph_client.py` | `https://graph.microsoft.com/.default` | Licenses, user roles, Entra app registrations, CA policies |
| Power Platform Admin (BAP) | `pp_admin_client.py` | `https://service.powerapps.com//.default` | Environments, cloud flows, connections, DLP policies |
| Island Gateway (Copilot Studio) | `pva_client.py` | `96ff4394-9197-43aa-b393-6a41652e21f8/.default` | Live bot component status, model config, knowledge source *runtime state* |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HIGH - Architecture table documents pva_client.py (Island Gateway client) as if it exists, but the file is not on main or in this PR's diff - it lives only on PR #37 (users/grahamc/260504UpdateFlightCheckerForNewChecks). A future check author following this guide before PR #37 merges will look for a file that isn't there. The same dangling reference also appears at lines 63-64 (See pva_client.py _discover_gateway() for the implementation pattern) and line 126 (lists pva_client.py as one of the existing client patterns to follow).

Fix: either (a) make PR #38 dependent on PR #37 and rebase it onto pr-37 so pva_client.py lands first, or (b) drop the Island Gateway row from the table and remove every pva_client.py / _discover_gateway reference (lines 16, 41-81, 63-64, 126) and add it back in a follow-up PR after PR #37 merges. Until then the only valid clients to document are auth.py, graph_client.py, and pp_admin_client.py.

| `runner.env_id` | `str` | Power Platform (BAP) environment ID |
| `runner.graph` | `GraphClient \| None` | Microsoft Graph client |
| `runner.pp_admin` | `PowerPlatformAdminClient \| None` | BAP admin client |
| `runner.pva` | `PVAClient \| None` | Island Gateway client |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HIGH - Runner attributes table claims runner.pva: PVAClient | None is available to check functions, but cli.py (lines 162-167 on main) only sets runner.config, runner.env_url, runner.dv_token, runner.env_id, runner.graph, runner.pp_admin. There is no runner.pva. The example at line 163 (# ... possibly using runner.graph / runner.pva / etc. ...) propagates the same error.

A check author who writes if not runner.pva: will hit AttributeError, not the documented None sentinel.

Fix: remove the runner.pva row from the table and the runner.pva mention from the example comment until the attribute is actually attached in cli.py (which happens in PR #37). After PR #37 merges, also document that tenant_id is implicitly needed by any new client following the existing MSAL pattern but is currently not exposed as a runner attribute - so authors must accept it as a separate arg or compute it from env_url.

- **`statecode`/`statuscode`** are standard Dataverse record status (Active=0/1),
NOT the runtime crawl/index status.

## Design Principles

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HIGH - The Design Principles section (lines 99-141) has zero security guidance for the exact bug classes that landed in PR #29 round 8 (commits 97e9708, cb22c88):

  1. xml.etree instead of defusedxml for any XML parsing -> XXE
  2. No urllib3.util.retry.Retry adapter on requests.Session for transient 5xx/429 against BAP/Graph -> intermittent flake
  3. Raw exception text echoed into CheckResult.result -> CWE-209 leak of bearer tokens / SAS URLs / PII when an upstream API fails
  4. No scheme validation on operator-provided URLs (e.g., dataverseEndpoint from my/config.json) -> http:// or file:// could be accepted

Future check authors will repeat these because the guide doesn't warn them. This guide is the first thing the next contributor reads.

Fix: add a ## Security Requirements section after Design Principles with four bullets:

  1. XML parsing: Use defusedxml.ElementTree not xml.etree for any XML payload (Dataverse SOAP, federation metadata). Catch both ET.ParseError AND defusedxml.common.DefusedXmlException so attack-path payloads (EntitiesForbidden, ExternalReferenceForbidden, DTDForbidden, NotSupportedError) fall through to a structured result instead of an unhandled traceback.
  2. HTTP retry: Mount a urllib3.util.retry.Retry(total=3, backoff_factor=1, status_forcelist=[429,500,502,503,504], allowed_methods=GET/HEAD/OPTIONS only, respect_retry_after_header=True) adapter on a module-level requests.Session. Do NOT include POST/PUT/DELETE in allowed_methods - replays of mutating verbs on transient 5xx are unsafe.
  3. CWE-209 scrubbing: Never put raw exception text or error_description into CheckResult.result or CheckResult.remediation. Bearer tokens, SAS URLs, and tenant IDs leak through requests.HTTPError.response.text and MSAL error_description. Echo only the error code and HTTP status; log full detail to stderr only.
  4. URL validation: When accepting a URL from my/config.json or any operator-provided source, validate urlparse(url).scheme == "https" before sending bearer tokens to it. See auth._validate_https_url and pp_admin_client.derive_environment_id for the pattern.

2. If a new client is needed, create it following existing patterns and add it
to the table above
3. Add the check function to the appropriate module in `checks/`
4. Wire it into `_check_single_agent()` (for per-agent checks) or the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM - Checklist step 4 says "Wire it into _check_single_agent() (for per-agent checks) or the appropriate scope runner" but never tells the author HOW to wire a brand-new scope. The actual mechanism is: import the function in cli.py, add a tuple (category_name, function) to FULL_SCOPE, and add an entry to SCOPE_MAP if the check should also be runnable in isolation via --scope <name>. Without that, the runner.register(...) call never happens for the new check and it silently never executes.

Fix: replace step 4 with two explicit steps:

4. For per-agent checks (each agent under `my/agents/`), call your check from `_check_single_agent()` in `checks/local_files.py`.
5. For a new scope category, in `scripts/flightcheck/cli.py`:
   a. Import the check: `from flightcheck.checks.<module> import run_<name>_checks`
   b. Append `("<Category Name>", run_<name>_checks)` to `FULL_SCOPE`.
   c. If the scope should also run in isolation, add `"<scope_name>": [("<Category Name>", run_<name>_checks)]` to `SCOPE_MAP`.
   d. The runner picks it up via `runner.register(category, fn)`; no further wiring needed.

@@ -0,0 +1,202 @@
# FlightCheck — Developer Guide

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOW - Document uses Unicode em-dash (U+2014) in 12 places: lines 1, 22, 33, 87, 105, 107, 108, 109, 111, 113, 115, 180. Rest of the kit's docs and source comments use ASCII hyphen. Mixed usage is a churn signal in git grep and breaks the kit's ASCII-only convention (Outlook COM mojibake history - same root cause when authors copy from rendered markdown into other surfaces).

Fix: replace every with - (or -- if you want to preserve the visual weight). PowerShell from repo root:

(Get-Content scripts/flightcheck/AGENTS.md -Raw).Replace([char]0x2014, '-') | Set-Content scripts/flightcheck/AGENTS.md -NoNewline -Encoding utf8

@saengland
saengland changed the base branch from main to main2 May 7, 2026 20:23
@saengland saengland closed this May 7, 2026
@saengland

Copy link
Copy Markdown
Collaborator

Heads-up Graham McMynn (@GrahamMcMynn) Srikanth Deshpande (@srideshpande): retargeted this PR from main -> main2.

main2 is becoming the new default branch (the SFI-cleared post-rename history). main is being deprecated. All the PR #1-#10 stack and the rebrand have already landed on main2, and the existing main history will not survive the cutover.

Action needed on your side:

  1. Rebase your branch on main2 (git fetch origin && git rebase origin/main2)
  2. Resolve any conflicts (likely minimal - the trees diverged at file-layout level)
  3. Force-push to your feature branch

Once rebased, the existing review comments stay attached and CI re-runs. If the rebase is messy, ping me and I'll help.

@saengland

Copy link
Copy Markdown
Collaborator

Reopened as #58 against main. The previous review (this PR) is preserved here for context.

@saengland
saengland deleted the users/grahamc/flightcheck-developer-guidance branch May 11, 2026 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants