Skip to content

feat: add key/value allowlisting to OperationContext#181

Merged
arorashivam96 merged 3 commits into
mainfrom
feat/context-allowlisting
May 22, 2026
Merged

feat: add key/value allowlisting to OperationContext#181
arorashivam96 merged 3 commits into
mainfrom
feat/context-allowlisting

Conversation

@arorashivam96

Copy link
Copy Markdown
Contributor

Summary

  • Adds key/value allowlisting to OperationContext.__post_init__ so that only known keys (app, skill, agent) and their respective allowlisted values are accepted
  • Prevents PII from entering the User-Agent header even from standalone callers outside the plugin (e.g., --context "ssn=123-45-6789" is now rejected at the SDK layer)

What's validated

Key Validation Example valid Example rejected
app Must match <name>/<version> format dataverse-skills/1.5.0 noslash
skill Must be one of 7 known skills dv-data not-a-skill
agent Must be one of 5 known agents claude-code not-an-agent
Unknown keys Rejected outright ssn=123-45-6789

Changes

File Change
src/.../core/config.py Added _ALLOWED_KEYS, _ALLOWED_SKILLS, _ALLOWED_AGENTS, _APP_PATTERN; key/value validation loop in __post_init__
tests/unit/test_operation_context.py 6 new tests: unknown key, unknown skill, unknown agent, PII in valid format, invalid app format

Test plan

  • pytest tests/unit/test_operation_context.py -v — 25 passed
  • pytest tests/unit/ -v — 1394 passed, 0 regressions
  • black src tests --check — clean

🤖 Generated with Claude Code

Validate that operation_context keys are from {app, skill, agent} and
values match their respective allowlists. Unknown keys like 'ssn' or
'name' are rejected with ValueError. This prevents PII from entering
the User-Agent header even from standalone callers outside the plugin.

- skill values must be in the 7 known Dataverse skills
- agent values must be in {claude-code, copilot, cursor, codex, unknown}
- app values must match <name>/<version> format

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 20:17
@arorashivam96 arorashivam96 requested a review from a team as a code owner May 13, 2026 20:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a closed allowlist for OperationContext.user_agent_context so only the keys app, skill, and agent are accepted, with values for skill and agent constrained to known identifier sets and app constrained to a <name>/<version> pattern. This hardens the SDK against PII leaking into the User-Agent header from standalone callers, on top of the existing structural validation.

Changes:

  • Introduces _ALLOWED_KEYS, _ALLOWED_SKILLS, _ALLOWED_AGENTS, and _APP_PATTERN constants in core/config.py.
  • Adds a per-pair allowlist validation loop in OperationContext.__post_init__ plus updated docstring.
  • Adds 5 negative unit tests covering unknown keys, unknown skill, unknown agent, PII-shaped input, and malformed app values.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/PowerPlatform/Dataverse/core/config.py Adds allowlist constants, app-value regex, validation loop, and updates docstring/raises notes.
tests/unit/test_operation_context.py Adds 5 tests asserting ValueError for unknown keys/values and invalid app format.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

arorashivam96 and others added 2 commits May 18, 2026 18:02
MCP proxy is skill-agnostic per call — the CLI subprocess doesn't know
which skill triggered the request. Adding "unknown" to the skill
allowlist enables consistent 3-key context (app/skill/agent) across all
channels instead of omitting skill for MCP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@arorashivam96 arorashivam96 merged commit b954f51 into main May 22, 2026
9 checks passed
@arorashivam96 arorashivam96 deleted the feat/context-allowlisting branch May 22, 2026 02:26
abelmilash-msft pushed a commit that referenced this pull request May 24, 2026
Sync side was updated to use the new CreateEntities API in PR #183.
The async client has its own copy of _create_entity and _create_table,
so we need to mirror those changes manually:

- _AsyncODataClient._create_entity(): URL EntityDefinitions -> CreateEntities,
  payload wrapped in Entities[0] array with @odata.type ComplexEntityMetadata
- _AsyncODataClient._create_table(): pass complex=True to _attribute_payload
  calls so attribute metadata uses the Complex*Metadata variants required
  by CreateEntities

The shared base (_odata_base.py) changes from PR #183 — including the
_attribute_payload(complex=...) parameter and Complex*Metadata output —
flow into the async client automatically via inheritance.

Also picks up PR #181 (OperationContext key/value allowlisting) via
the same main merge.

Tests: 2187 pass, black clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
abelmilash-msft added a commit that referenced this pull request May 29, 2026
Release changelog and version bump for v1.0.0.

## Changes
- Converted `[Unreleased]` to `[1.0.0] - 2026-05-25` in `CHANGELOG.md`
- Incorporated all PRs merged since `v0.1.0b10`: async client (#171),
shorter imports (#165), OperationContext allowlisting (#181),
CreateEntities API (#183), migration tool fixes (#184), SQL guardrails /
error handling / float precision (#185), `QueryResult.__aiter__` (#187),
Python 3.10/3.11 fix (#188)
- Bumped `version` in `pyproject.toml` from `0.1.0b11` → `1.0.0`

---------

Co-authored-by: Abel Milash <abelmilash@microsoft.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants