Skip to content

loader: screen the model against runtime-declared supported attributes - #926

Closed
ndeloof wants to merge 2 commits into
compose-spec:mainfrom
ndeloof:supported-attributes
Closed

ndeloof wants to merge 2 commits into
compose-spec:mainfrom
ndeloof:supported-attributes

Conversation

@ndeloof

@ndeloof ndeloof commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

The Compose Specification makes the runtime responsible for warning about attributes it parses but ignores (docker/compose#13150). Instead of each runtime hand-enumerating what it does not implement, the loader can screen the merged model against a declaration of what it does:

  • Options.SupportedAttributes takes a set of tree.Path patterns; every attribute of the canonical, pre-normalization model (what the user actually wrote) matching none of them is reported through Options.UnsupportedAttribute (default: a logrus warning). Extension keys (x-*) are never reported; an undeclared subtree is reported once at its root.
  • tree.Matcher gives tree.Path pattern sets a first-class matching API: exact Matches — declaring a path accepts that node only, so removing one leaf from a declared set reliably surfaces it — plus MayContain for walkers that must know when a declared attribute lives deeper.
  • schema.AttributePaths derives the complete attribute-path inventory from the embedded JSON schema (pattern-keyed mappings as *, sequence items as [], $ref cycles terminated, ^x- pattern properties excluded — recorded as wildcards they would blanket-accept every undeclared sibling). A runtime builds its declaration by removing what it does not implement from the full specification, so every newly-specified attribute stays reported until deliberately wired in.

Example — a runtime declaring schema.AttributePaths() minus the swarm-only subtrees, loading the docker/compose#13149 file:

WARN compose.yaml: attribute services.app.deploy.update_config is not supported and will be ignored
WARN compose.yaml: attribute services.app.configs.[].uid is not supported and will be ignored

🤖 Generated with Claude Code

Entries set by the COMPOSE_FILE environment variable used to be resolved
to absolute paths with a bare os.Stat check, so an empty or directory
entry made the loader fail later with a cryptic OS-level error such as
"read <pwd>: is a directory" (an empty entry resolves to the working
directory).

Validate each entry when it is selected: it must be stdin ("-"), a
remote resource supported by a registered ResourceLoader, or a regular
local file. Errors now state how the file was selected:

    compose file "" set by COMPOSE_FILE environment variable is invalid: /home/user is a directory

Config paths selected implicitly (COMPOSE_FILE, default file discovery)
are also tracked so read errors are decorated the same way, while
explicitly selected files (-f) keep a plain "compose file X is invalid"
prefix.

See docker/compose#13649

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
The Compose Specification makes the runtime responsible for warning
about attributes it parses but ignores (docker/compose#13150). Instead
of each runtime hand-enumerating what it does NOT implement, the loader
can screen the merged model against a declaration of what it DOES:

- Options.SupportedAttributes takes a set of tree.Path patterns; every
  attribute of the canonical, pre-normalization model (what the user
  actually wrote) matching none of them is reported through
  Options.UnsupportedAttribute (default: a logrus warning). Extension
  keys (x-*) are never reported; an undeclared subtree is reported once
  at its root.

- tree.Matcher gives Path pattern sets a first-class matching API:
  exact Matches — declaring a path accepts that node only, so removing
  one leaf from a declared set reliably surfaces it — plus MayContain
  for walkers that must know when a declared attribute lives deeper.

- schema.AttributePaths derives the complete attribute-path inventory
  from the embedded JSON schema (pattern-keyed mappings as '*',
  sequence items as '[]', $ref cycles terminated, '^x-' pattern
  properties excluded: recording them as wildcards would blanket-accept
  every undeclared sibling). A runtime builds its declaration by
  removing what it does not implement from the full specification, so
  every newly-specified attribute stays reported until deliberately
  wired in.

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
@ndeloof

ndeloof commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

will be combined with #927

@ndeloof

ndeloof commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #927, merged as cda1852 with both halves combined: the deny patterns with value predicates from the original #927 plus the schema-derived fail-closed allowlist from this PR (landed into it via glours#2). Same walk, same batch report.

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