Skip to content

fix: replace Pattern.Includes with Contains and Overlaps - #644

Open
joe0BAB wants to merge 2 commits into
mainfrom
fix/include-check
Open

fix: replace Pattern.Includes with Contains and Overlaps#644
joe0BAB wants to merge 2 commits into
mainfrom
fix/include-check

Conversation

@joe0BAB

@joe0BAB joe0BAB commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Pattern.Includes reused the ID matcher and treated a wildcard in the candidate pattern as matching anything, so it implemented neither containment nor overlap: it reported overlapping-but-not-contained patterns as included (docker/proj1/** claimed to include docker/*/mcp/*), was asymmetric, and gave different answers for spellings with equal match sets (a/a/** vs a/a/**/**).

Two changes:

Replace Includes with Contains and Overlaps. Each relation is decided by a two-row DP over canonicalized wildcard tokens (runs of */** collapse; a lone ** becomes */** since IDs are never empty):

  • p.Contains(other) — p matches every ID that other matches: the containment Includes documented all along, with the same operand order.
  • p.Overlaps(other) — p and other match at least one ID in common: symmetric, and spelling-insensitive by construction.

Both run in O(n*m) time and were verified against a brute-force set oracle on all 115,600 pattern pairs of up to 4 components. The ID matcher drops the candidate-side * special case it only carried for Includes.

Remove Filter. It reduced two patterns to the contained one and returned false for overlapping-but-not-contained pairs, silently dropping providers whose namespace merely overlaps a query. No signature-compatible definition is exact, because the intersection of two patterns is not always expressible as a single pattern; it is removed until a caller needs a well-defined replacement.

@joe0BAB
joe0BAB marked this pull request as ready for review September 10, 2026 12:14

@docker-agent docker-agent 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.

Assessment: 🟢 APPROVE

Comment thread x/secrets/pattern.go
Comment thread x/secrets/pattern.go Outdated
Comment thread x/secrets/pattern.go Outdated
Comment thread x/secrets/pattern.go Outdated
Comment thread x/secrets/pattern_test.go

@Benehiko Benehiko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

mostly just godocs

I think we need to make sure it's super clear to a user using this what it means to use p.Overlaps or p.Contains

Comment thread x/secrets/pattern_test.go Outdated
Comment on lines +98 to +99
// identically (the old Includes was spelling-sensitive and
// answered true for a/a/** but false for a/a/**/**).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

encoding history

Comment thread x/secrets/pattern.go Outdated
Comment on lines +216 to +217
// dp[j] == "p[i:] and q[j:] match a common suffix"; row i needs only row
// i+1 (prev).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this comment made no sense to me.

Comment thread x/secrets/pattern.go Outdated
Comment on lines +229 to +230
// The gap either ends, or absorbs the other side's next
// component.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same here

Comment thread x/secrets/pattern_test.go Outdated
{"bar/**", "foo/**", false}, // first components conflict
{"foo/*/baz", "foo/bar/**", true},
// Overlap without containment in either direction.
{"docker/*/mcp/*", "docker/proj1/**", true}, // both match docker/proj1/mcp/x

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

comment here is redundant

Comment thread x/secrets/pattern_test.go Outdated
{"foo/*/baz", "foo/bar/**", true},
// Overlap without containment in either direction.
{"docker/*/mcp/*", "docker/proj1/**", true}, // both match docker/proj1/mcp/x
{"foo/foo/foo/**", "foo/foo/**/foo", true}, // both match foo/foo/foo

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same here - the test shows they both match

Comment thread x/secrets/pattern.go Outdated
Comment thread x/secrets/pattern.go
Comment on lines +91 to +99
// Overlaps reports whether the pattern and [other] match at least one
// ID in common:
//
// p.Overlaps(other) ⇔ matches(p) ∩ matches(other) ≠ ∅
//
// Symmetric; implied by containment, not the converse: docker/*/mcp/*
// and docker/proj1/** overlap yet neither contains the other. O(n*m)
// time, O(m) space, for component counts n and m.
Overlaps(other Pattern) bool

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think Overlaps needs a bit more explaining or better godocs. Difficult to understand the concept of

docker/*/mcp/* and docker/proj1/** overlap yet neither contains the other.

Comment thread x/secrets/pattern.go Outdated
Comment thread x/secrets/pattern.go Outdated
// or '**' in q.
func covers(p, q []token) bool {
np, nq := len(p), len(q)
// dp[j] == "p[i:] includes q[j:]"; row i needs only row i+1 (prev).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

don't know what this comment is about

Comment thread x/secrets/pattern.go Outdated
Includes reused the ID matcher and treated a wildcard in the candidate
pattern like a component that matches anything, so it implemented
neither containment nor overlap: overlapping-but-not-contained patterns
were reported as included (`docker/proj1/**` claimed to include
`docker/*/mcp/*`), the relation was asymmetric, and spellings with
equal match sets (`a/a/**` vs `a/a/**/**`) got different answers.

Split it into the two relations callers actually need, each decided by
a two-row DP over canonicalized wildcard tokens (runs of `*`/`**`
collapse, a pure `**` becomes `*/**` since identifiers are never
empty):

- `p.Contains(other)`: p matches every ID that other matches — the
  containment Includes documented all along, with the same operand
  order.
- `p.Overlaps(other)`: p and other match at least one ID in common;
  symmetric, and spelling-insensitive by construction.

Both run in `O(n*m)` time and were verified against a brute-force set
oracle on all 115,600 pattern pairs of up to 4 components. The ID
matcher drops the candidate-side `*` special case it only carried for
Includes, and Filter keeps its one-contains-the-other behavior with
corrected docs.

Signed-off-by: Johannes Großmann <grossmann.johannes@t-online.de>
Filter reduced two patterns to the contained one and returned false for
overlapping-but-not-contained pairs, silently dropping providers whose
namespace merely overlaps a query. No signature-compatible definition is
exact, because the intersection of two patterns is not always expressible
as a single pattern. Remove it until a caller needs a well-defined
replacement.

Signed-off-by: Johannes Großmann <grossmann.johannes@t-online.de>
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