Skip to content

fix: tolerate auth-filtered projections instead of crashing on pull - #299

Merged
Ruari-Phipps merged 2 commits into
mainfrom
fix/auth-filtered-projection-guards
Sep 1, 2026
Merged

fix: tolerate auth-filtered projections instead of crashing on pull#299
Ruari-Phipps merged 2 commits into
mainfrom
fix/auth-filtered-projection-guards

Conversation

@Ruari-Phipps

Copy link
Copy Markdown
Collaborator

Summary

The API filters projections per permission slice: a user without read access to a slice
gets a skeleton carrying only identity fields, with the substantive fields stripped.
Every from_projection now detects an auth-filtered or absent slice and drops that
resource type for the pull instead of crashing or building resources from the skeleton.

First of two PRs replacing #288 (stacked on #298; the follow-up adds slim reference
mappings so references to withheld resources still resolve to names).

Motivation

Pulling as a restricted reader fails today. All 162 pull failed errors on adk-service
in the last 30 days trace to auth-filtered slices:

  • 116 × KeyError on name / actions / description — unguarded field access on
    skeleton entities.
  • 46 × Duplicate resource file path found / File not found for resource — filtered
    keyphrase-boosting and phrase-filter slices parsed with empty names, collapsing every
    entry onto one file path.

Changes

  • Every from_projection guards its slice: an absent slice or one where any entity is
    missing a field the API always sends for readable data is treated as withheld, logged
    at debug level, and yields no resources.
  • Guards test field presence, never truthiness, so falsy-but-readable values (empty
    content, active=False) are not mistaken for filtered ones. Sentinel fields are
    chosen per slice where the obvious field is optional in the API schema (e.g. variant
    attributes guard on type, not archived; variants on isDefault, not name).
  • Functions check their three slices independently ("functions" gates special and global
    functions, "jupiter_flows" gates transition functions) — losing one permission must not
    hide the others.
  • New slim_projection_test.py with a skeleton-projection fixture built from the fields
    each slice always sends, asserting no registered resource type raises and nothing
    half-built survives.

Test strategy

  • Added/updated unit tests
  • Manual CLI testing (poly <command>)
  • Tested against a live Agent Studio project
  • N/A (docs, config, or trivial change)

Checklist

  • ruff check . and ruff format --check . pass
  • pytest passes (1443 passed, 153 subtests)
  • No breaking changes to the poly CLI interface (or migration path documented)
  • Commit messages follow conventional commits

Ruari-Phipps and others added 2 commits September 1, 2026 11:27
When an entire multi-resource YAML type is absent from the incoming
projection, its per-resource deletions were batched into the file cache
and then discarded when the pull returned - the pruned file never
reached disk. The leftover cache entry was also stamped with the file's
pre-write mtime, so the staleness check treated it as fresh and every
later read in the process saw a file state that was not on disk. The
visible symptom was a pull that had to be run twice before poly diff
came back clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The API filters projections per permission slice: a user without read
access to a slice gets a skeleton carrying only identity fields, with
the substantive fields stripped. Pulling as a restricted reader either
crashed on a missing field (KeyError on name/actions/description) or
built resources from the skeleton - empty-named keyphrases and phrase
filters collapsing onto one file path and failing the duplicate-path
check.

Every from_projection now detects an auth-filtered or absent slice and
drops that resource type for the pull, logging at debug level. Guards
test field presence, never truthiness, so falsy-but-readable values
(empty content, active=False) are not mistaken for filtered ones.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Base (fix/multi-resource-yaml-cache-flush) PR Change
76.6% 76.7% +0.1% ✅

Changed file coverage

File Coverage Change
poly/resources/function.py 82.0% +0.3% ✅
poly/resources/pronunciation.py 82.3% -0.6% ⚠️
poly/resources/handoff.py 82.3% -0.9% ⚠️
poly/resources/variant_attributes.py 83.6% -1.9% ⚠️
poly/resources/transcript_correction.py 84.5% -2.3% ⚠️
poly/resources/entities.py 88.0% +0.6% ✅
poly/resources/keyphrase_boosting.py 88.4% -2.1% ⚠️
poly/resources/phrase_filter.py 88.8% -1.3% ⚠️
poly/resources/flows.py 89.1% +0.2% ✅
poly/resources/experimental_config.py 89.6% -2.4% ⚠️
poly/resources/languages.py 89.6% +2.3% ✅
poly/resources/documents.py 90.4% +0.6% ✅
poly/resources/asr_settings.py 90.5% +0.5% ✅
poly/resources/sms.py 90.7% +2.7% ✅
poly/resources/channel_settings.py 91.0% +2.6% ✅
poly/resources/api_integration.py 91.9% -1.2% ⚠️
poly/resources/test_suite.py 93.2% +0.1% ✅
poly/resources/agent_settings.py 93.7% -0.6% ⚠️
poly/resources/translations.py 93.9% -0.7% ⚠️
poly/resources/safety_filters.py 95.7% +0.2% ✅
poly/resources/topic.py 96.5% +0.3% ✅
poly/resources/variable.py 96.9% +1.2% ✅

Base automatically changed from fix/multi-resource-yaml-cache-flush to main September 1, 2026 11:01
@Ruari-Phipps
Ruari-Phipps merged commit 37f9d39 into main Sep 1, 2026
6 checks passed
@Ruari-Phipps
Ruari-Phipps deleted the fix/auth-filtered-projection-guards branch September 1, 2026 14:31
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.

2 participants