portage-ucp 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 826f590ea83ab80febf6e461f60d1eb580d7ebf460a419bafb81d0f713525e81
4
- data.tar.gz: eb98a54978daf0904de0121101e98e597a67cd38dabd7440dd3813449b384635
3
+ metadata.gz: 7615fe9307cfc4a996c1f1842bcad557e4b2f67b336516d0dc767f5cbfb88c7b
4
+ data.tar.gz: b220392e3d403db32f750805fb18ec008b8c7c23a55f6f15ce0a6cddc71be8ff
5
5
  SHA512:
6
- metadata.gz: fcb26f95ac6d46b622f3495b945f76549d4c7525c25fbe0552c3485659395e35e1e0330fe212052f253ba79680d498e9de0b179d91c9bee17a4f2796ec33c50c
7
- data.tar.gz: 4726bf3de6e45993612ea7a2c4bfd57ef418ad1a7c1d1a17efdffa90d20991df0fe9f623548f81065383b31aa99fd7210c2512d7994f6521a4bb6cfcfc494c1c
6
+ metadata.gz: 9664fd1f78821b3afeac62b2fd9cd09971e9daa279aa65e4f1de44ebe7989ccc5d180e7efc0fe9b9ab6b4ca0320a851dd045aae5f736e44bcb64a237b4ac948e
7
+ data.tar.gz: 1f2bc7debcc1afb3f54fa4e6072391c76f3347df24e462488db69ab33e67c92fca6129dc6d1b18442e503a7d53f3b2ca2f5f284061e88cf9c4793e42f02ea6b9
data/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to this project are documented here. Format loosely follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.0.0/); this project is
5
5
  pre-1.0, so APIs may still shift between minor versions.
6
6
 
7
+ ## [0.8.0] - 2026-09-17
8
+
9
+ - **Breaking:** `Manifest#to_h` now emits the shape live UCP stores actually
10
+ serve (confirmed against Shopify's `2026-08-25` rollout) instead of the
11
+ flat one this gem invented: everything nests under a top-level `ucp`
12
+ object, `ucp_version` becomes `version`, and `capabilities` is keyed by
13
+ capability name (`{"dev.ucp.shopping.catalog" => [{version: ...}]}`)
14
+ rather than an array of `{name:, version:}` hashes. When a signer is
15
+ configured the signature still covers the manifest body and rides inside
16
+ the `ucp` object. Anything reading a Portage-served manifest by the old
17
+ top-level keys needs updating — `Rack::ManifestEndpoint`'s own
18
+ advertised-payment check and `skills/serve-via-ucp`'s `verify.sh` both
19
+ did, and are fixed here.
20
+
7
21
  ## [0.7.1] - 2026-09-16
8
22
 
9
23
  - No behavior change — 0.7.0 was built and pushed with `gem build` run from
@@ -31,24 +31,31 @@ module Portage
31
31
  @services = services
32
32
  end
33
33
 
34
+ # Nests everything under a "ucp" envelope, and keys `capabilities` by
35
+ # capability name (matching what live Shopify UCP rollouts — Casper,
36
+ # Allbirds, Glossier, and 34+ others — actually serve as of manifest
37
+ # "version": "2026-08-25"; see docs/well-known-ucp.md and
38
+ # portage-ucp-client's Client.discover, which this shape now matches).
34
39
  def to_h
35
- payload = {
36
- ucp_version: UCP_VERSION,
40
+ ucp = {
41
+ version: UCP_VERSION,
37
42
  business: @business,
38
43
  services: @services,
39
- capabilities: @registry.advertised(@adapter).map do |capability|
40
- { name: capability.name, version: capability.version }
41
- end,
44
+ capabilities: capability_hash,
42
45
  payment_handlers: @payment_handlers,
43
46
  signing_keys: @signing_keys
44
47
  }
45
- return payload unless @signer
48
+ ucp = ucp.merge(signature: sign(ucp)) if @signer
46
49
 
47
- payload.merge(signature: sign(payload))
50
+ { ucp: ucp }
48
51
  end
49
52
 
50
53
  private
51
54
 
55
+ def capability_hash
56
+ @registry.advertised(@adapter).to_h { |capability| [capability.name, [{ version: capability.version }]] }
57
+ end
58
+
52
59
  def sign(payload)
53
60
  canonical = JSON.generate(payload)
54
61
  { kid: @signer.kid, value: Base64.strict_encode64(@signer.sign(canonical)) }
@@ -32,7 +32,7 @@ module Portage
32
32
  def payment_handlers_over_plaintext?(payload, request)
33
33
  return false if @allow_insecure || request.ssl?
34
34
 
35
- !Array(payload[:payment_handlers]).empty?
35
+ !Array(payload.dig(:ucp, :payment_handlers)).empty?
36
36
  end
37
37
 
38
38
  def not_found
@@ -1,5 +1,5 @@
1
1
  module Portage
2
2
  module Ucp
3
- VERSION = "0.7.1".freeze
3
+ VERSION = "0.8.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: portage-ucp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Whitbread
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2026-09-16 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: base64
@@ -138,7 +137,6 @@ dependencies:
138
137
  version: '0.9'
139
138
  description: 'Protocol-only core gem: Adapter contract, capability registry, manifest
140
139
  builder, and an MCP server wrapper. No commerce-backend deps.'
141
- email:
142
140
  executables:
143
141
  - portage-ucp-check
144
142
  extensions: []
@@ -293,7 +291,6 @@ metadata:
293
291
  source_code_uri: https://github.com/tomtom87/Portage/tree/main/portage-ucp
294
292
  changelog_uri: https://github.com/tomtom87/Portage/blob/main/portage-ucp/CHANGELOG.md
295
293
  rubygems_mfa_required: 'true'
296
- post_install_message:
297
294
  rdoc_options: []
298
295
  require_paths:
299
296
  - lib
@@ -308,8 +305,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
308
305
  - !ruby/object:Gem::Version
309
306
  version: '0'
310
307
  requirements: []
311
- rubygems_version: 3.5.22
312
- signing_key:
308
+ rubygems_version: 4.0.21
313
309
  specification_version: 4
314
310
  summary: Expose a commerce backend to AI shopping agents over MCP and UCP
315
311
  test_files: []