Skip to content

[Med] fix(policy): respect Rule.appliesTo in lint() to prevent false-positive errors#714

Open
katnisscalls99 wants to merge 1 commit into
profullstack:masterfrom
katnisscalls99:fix/policy-linter-appliesto-filter
Open

[Med] fix(policy): respect Rule.appliesTo in lint() to prevent false-positive errors#714
katnisscalls99 wants to merge 1 commit into
profullstack:masterfrom
katnisscalls99:fix/policy-linter-appliesto-filter

Conversation

@katnisscalls99
Copy link
Copy Markdown

Rule declares an appliesTo?: TargetKind[] field documented as 'empty = applies to every target kind'. Two rules (bundleId, iconSizes) set it to ['mobile', 'tv', 'wearable']. But lint() called r.run(ctx) for every rule unconditionally, ignoring appliesTo entirely.

Result: a manifest with a 'web' or 'api' target that incidentally carries a config.bundleId field (a legitimate pattern for internal naming, telemetry ids, etc.) receives hard 'error' findings from the mobile/bundle-id rule, causing CI gates to fail for non-applicable checks.

Confirmed via grep: appliesTo is referenced in rule.ts (interface), bundle-id.ts, and icon-sizes.ts — never in linter.ts.

Fix: before running rules, collect the set of target kinds present in the manifest and filter to rules whose appliesTo overlaps that set (or is empty/undefined, meaning universal). Adds no overhead for the common single-kind case.

Severity: Medium

…ve errors

Rule declares an appliesTo?: TargetKind[] field documented as
"empty = applies to every target kind". Two rules (bundleId, iconSizes)
set it to ['mobile', 'tv', 'wearable']. But lint() called r.run(ctx)
for every rule unconditionally, ignoring appliesTo entirely.

Result: a manifest with a 'web' or 'api' target that incidentally carries
a config.bundleId field (a legitimate pattern for internal naming,
telemetry ids, etc.) receives hard 'error' findings from the
mobile/bundle-id rule, causing CI gates to fail for non-applicable checks.

Confirmed via grep: appliesTo is referenced in rule.ts (interface),
bundle-id.ts, and icon-sizes.ts — never in linter.ts.

Fix: before running rules, collect the set of target kinds present in
the manifest and filter to rules whose appliesTo overlaps that set (or
is empty/undefined, meaning universal). Adds no overhead for the common
single-kind case.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 6, 2026

Greptile Summary

This PR adds an appliesTo-aware filter in lint() to prevent mobile-only rules (bundleId, iconSizes) from firing on web/api manifests. The intent is correct, but the implementation reads t.kind from manifest target entries, which do not carry a kind field.

  • ctx.manifest.targets is Record<string, TargetSpec> — the spec only holds use, enabled, config, and distribute. The kind property lives on the Target<Config> adapter interface, not on the manifest. manifestKinds will always be Set{undefined}, so every rule with a non-empty appliesTo is filtered out for all manifests, silently disabling bundleId and iconSizes checks even for genuine mobile/TV/wearable targets.
  • No tests are present for the new filtering behavior, making it harder to catch the regression at review time.

Confidence Score: 3/5

The change introduces a regression where mobile/TV/wearable manifests silently skip the bundleId and iconSizes checks that are specifically designed for them — merging as-is would leave those rules permanently inactive.

The filter reads t.kind from TargetSpec, but TargetSpec has no kind property, so every lookup yields undefined. The result is that all rules with appliesTo constraints are dropped for every manifest, not just web/api ones, defeating the purpose of those rules for their intended target types.

packages/policy/src/linter.ts — the new manifestKinds collection block needs to use a source that actually carries kind information.

Important Files Changed

Filename Overview
packages/policy/src/linter.ts Introduces appliesTo filtering in lint(), but reads t.kind from TargetSpec which has no kind field — manifestKinds is always Set{undefined}, silently skipping all scoped rules (bundleId, iconSizes) for every manifest including mobile/TV targets.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[lint called with ctx and rules] --> B[Extract manifestKinds\nfrom ctx.manifest.targets]
    B --> C{t.kind exists\non TargetSpec?}
    C -- "NO (TargetSpec has no kind)\nt.kind === undefined" --> D[manifestKinds = Set of undefined]
    C -- "YES (intended)" --> E[manifestKinds = Set of real TargetKind values]
    D --> F[filter: r.appliesTo.some\nk => manifestKinds.has k]
    E --> F
    F -- "k is 'mobile' etc.\nSet has only undefined\n→ always false" --> G[bundleId and iconSizes\nfiltered OUT for ALL manifests]
    F -- "k matches real kind\n→ true for mobile targets" --> H[bundleId and iconSizes\nrun for mobile manifests only]
    G --> I["❌ Mobile manifests: no\nbundleId/iconSizes check\n(regression)"]
    H --> J["✅ Web/api manifests: no\nfalse positives\n(desired)"]
    I --> K[Promise.all on applicable rules]
    J --> K
    K --> L[Return LintResult]
Loading

Reviews (1): Last reviewed commit: "fix(policy): respect Rule.appliesTo in l..." | Re-trigger Greptile

Comment on lines +24 to +29
const manifestKinds = new Set(
Object.values(ctx.manifest.targets ?? {}).map((t) => t.kind),
);
const applicable = rules.filter(
(r) => !r.appliesTo || r.appliesTo.length === 0 || r.appliesTo.some((k) => manifestKinds.has(k)),
);
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.

P1 t.kind does not exist on TargetSpec — manifestKinds will always be Set{undefined}

ctx.manifest.targets is typed as Record<string, TargetSpec> (see manifest.ts line 57). TargetSpec is inferred from targetSpecSchema and has only use, enabled, config, and distribute fields — there is no kind property. The kind field belongs to the Target<Config> adapter interface in target.ts, not to the manifest spec.

As a result, Object.values(...).map((t) => t.kind) produces [undefined, undefined, ...] at runtime (and is a TypeScript compilation error under strict mode). manifestKinds will be Set { undefined }, and r.appliesTo.some((k) => manifestKinds.has(k)) will always be false, meaning every rule that declares an appliesTo constraint — including bundleId and iconSizes — will be silently skipped for all manifests, not just web/api ones. Mobile and TV manifests that carry a malformed bundleId will receive no errors, which is the opposite of the intent.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

8 similar comments
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: git fetch upstream master && git rebase upstream/master.

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.

1 participant