20/09/26 at 16:15:19 by Ran Yahalom
- Made Section 5.3.4 authoritative over the Section 5.1.1
pending/confirmcell, soconfirmfrompendingis legal only in manual confirmation mode and an auto-mode booking that is not alreadyconfirmedMUST be rejected withinvalid_transition. That closes the contradiction that would otherwise let a platform confirm an unpaid UCP-Native leftover sitting inpending - Marked REST
POST /bookings/{booking_id}/confirmand MCPusp_bookings_confirmasbusiness_only, stripping platformUSP-Agent/_metaand booking-scoped credentials, because a scoped credential that can confirm would still grant a free appointment on that unpaid leftover - Added flow vector
105-confirmation-mode-guardand a coherence check for thebusiness_onlyaccess class so the cell cannot drift untested again
20/09/26 at 14:50:25 by Ran Yahalom
- Withdrew the Section 7.5 cancel-checkout terminal-state invariant, the
cancellation.reason_codefield with itscheckout_abandonedvalue, thecanceled_atcross-read stability requirement, the buyer-notification suppression rule, the Section 5.2 note on the missing terminal path, and flow vector105-cancel-checkout-abandoned-booking. The hazard they addressed rested on the claim that a booking leftpendingby an abandoned checkout stays confirmable, and Section 5.3.4 restrictsconfirmto business-initiated manual-mode approval, so the claim does not hold as stated - Removed the pre-existing clause requiring
cancel_checkoutto transition the pending booking tocanceled, because it cited derivation rule 2 as its authority when that rule governs only the checkout-scoped summary, and because it forced a terminal transition the protocol has no established need for - Stated explicitly that Section 7.5 places no requirement on
Booking.statusfor a booking that never reachedconfirmed, so the silence is not read as an implicit requirement now that the transition clause is gone - Kept the derivation rule 2 clarification that the rule constrains
BookingContext.booking_statusonly, since the conflation it corrects was a genuine ambiguity independent of the withdrawn invariant - Kept the cancel-response shape rule forbidding
booking_status: pendingon a canceled checkout and permitting omission of thebookingobject, since that describes the agreed response contract and is unaffected by the withdrawal
20/09/26 at 14:21:09 by Ran Yahalom
- Corrected the Section 7.5 cancel-checkout invariant to say Section 5.1.1 "requires or permits" accepting
confirm,reschedule, orupdate, becausereschedulefrompendingisSHOULDrather thanYesand the previous wording claimed a requirement the cited table does not make; mirrored insite-docs/deployment-modes/ucp-native.md - Added a wrong answer to flow vector
105-cancel-checkout-abandoned-bookingfor keying the terminal state on USPpendinginstead of the specific backing state the abandoned checkout left behind, because a status mapping that folds several backing states intopendingwould also match a paid manual-confirmation booking awaiting merchant approval, which derivation rule 1 makespendingand which must never be reported canceled
20/09/26 at 14:06:21 by Ran Yahalom
- Rewrote the Section 7.5 cancel-checkout requirement as a mechanism-agnostic invariant on the USP booking resource observed through
GET /bookings/{booking_id}, so a business must not leave that booking in a state from which Section 5.1.1 requires acceptingconfirm, without prescribing how the internal record is stored - Clarified that derivation rule 2 constrains only the checkout-scoped
BookingContext.booking_statussummary, resolving the ambiguity that previously cited that rule while naming the booking record - Added
cancellation.reason_code(open vocabulary, well-known valuecheckout_abandoned) and requiredreason_code: checkout_abandonedwithcanceled_by: systemwhen a booking is terminalized because its checkout was canceled and never reachedconfirmed, so platforms can distinguish abandonment from a confirmed-appointment cancellation on the agent-facing wire - Required
canceled_atstability across reads so derive-and-stamp-now cannot report a different cancellation instant on everyGET - Made buyer-facing cancellation-notice suppression normative for the never-confirmed case while keeping the
booking.canceledwebhook a SHOULD - Forbade
booking_status: pendingon a canceled checkout and permitted omitting thebookingobject on the cancel response - Documented the silent-abandonment terminal-path gap in Section 5.2 when
expires_atis omitted and no explicitcancel_checkoutruns - Added flow vector
105-cancel-checkout-abandoned-bookingand mirrored the cancel rules insite-docs/deployment-modes/ucp-native.mdandsite-docs/specification/booking.md
16/09/26 at 23:23:45 by Ran Yahalom
- Removed an accidentally committed Python bytecode cache from the policy-scoping change so generated local artifacts are not shipped with the specification
14/09/26 at 07:30:00 by Maor Yehuda
- Stated that the UCP-Native
config.authorizationpolicy governs every privileged USP operation whichever endpoint carries it, not only the USP endpoint its binding declares, because a booking created through thepaid_bookingsextension travels onPOST /checkout-sessions— a UCP URL — and nothing said which published policy authorised a proof there - Prohibited publishing a USP policy on a UCP binding such as
dev.ucp.shopping, and forbade a platform reading the absence ofconfig.authorizationon a UCP binding as "no authentication required", since the namespace rule that keeps USP declarations underdev.usp-protocol.*is exactly what makes that absence uninformative rather than permissive - Recorded why the rule is needed: Section 7.2 already says Section 10.1.6 applies to UCP-Native checkout and booking-extension operations, while a policy scoped to "the USP endpoint that binding declares" left those operations unauthorised by anything in the profile — so a fail-closed client had to either refuse a conformant business or send a proof it could not justify
- Mirrored both rules in
site-docs/deployment-modes/ucp-native.md
11/09/26 at 16:35:48 by Ran Yahalom
- Dropped the Section 3.6.3 claim that
start_intervalrestatesbooking_window.slot_interval, because the ruler tick is per bitmap entry and can differ from the live-slot policy, so consumers that substituted the policy decoded the wrong starts - Stated that
coverage,density, andsoonnessare comparable only within one vertical and within one entry's grid, extending the existing "not comparable across registries, requests, snapshots, or scoring instants" rule, because density is a fraction of that entry's ownslot_countand mixed-vertical comparison ranked class and course calendars against appointment grids - Mirrored both rules in
site-docs/specification/service-catalog.md,site-docs/specification/discovery-registry.md,schemas/catalog.json, andschemas/registry.jsonRankSignals, so the published site and the canonical schemas do not keep the old equivalence or the old comparability bound - Extended
tools/usp_check.pyavailability contract fragments so a later edit cannot restore the restatement sentence or drop the vertical and grid comparability language
11/09/26 at 15:50:47 by Ran Yahalom
- Corrected Section 7.6.1, which claimed UCP checkout cannot express a deposit with a remainder owed at service time. Verified against the current UCP specification: the payment terms extension
dev.ucp.common.payment.termsmodels exactly that, and carries the accepted term onto the order so the outstanding amount stays machine-readable. The claim was true only of the UCP version the specification still pinned, and read as a protocol limitation rather than a stale dependency. - Rewrote Section 7.6.1 so all three payment timings are specified for UCP-Native Mode, with a capability column stating what each one requires beyond base checkout.
deposit_requiredneeds only the UCP payment terms extension;at_serviceadditionally needs the new USP extension below. The fail-closed rule is retained but now keys on whether the business declared the required capabilities, rather than on the timing being unspecified. - Added Section 11.3, the Pay-at-Service Settlement Extension (
dev.usp-protocol.services.pay_at_service), withschemas/pay_at_service.json. UCP payment terms can disclose that money falls due after completion but assumes a stored instrument will be charged for it, requiring that instrument to be capable of every schedule on the selected term. A buyer paying cash at the counter supplies no instrument, so a checkout that will never charge anything had no specified completion path. The extension adds one declaration that a named term is settled offline, which is what lets a business offer the term with no payment handler and a platform complete with no instrument instead of inferring it from an absence. - Constrained the extension so a platform that does not implement it still behaves correctly: the
at_servicetiming class is notimmediate, and UCP already defines an unrecognized timing class as not due at completion, so an unaware platform concludes the payment is outstanding rather than taken. - Required
due_aton every pay-at-service schedule even though UCP makes it optional. UCP tells businesses to omit it when the date depends on a future event; a booked slot is a time known at checkout, so requiring it lets a platform set a reminder rather than parse prose. - Gave
at_servicetwo conforming paths in UCP-Native Mode rather than one. An earlier draft of this change required a checkout for it, which would have put checkout infrastructure in front of precisely the cash-only businesses least equipped to run one. The direct path (no checkout, same steps as a free booking) is now normative and extended to Section 7.6, and the checkout path with the settlement extension is required only when a checkout is actually used, which is what a mixed cart needs. - Clarified in Sections 2.2.1 and 2.2.2 that "checkout-free" describes payment rather than the checkout object, since pay-at-service may optionally run through a zero-collection checkout. Without this a reader would conclude from
status: not_requiredandamount_due: 0that nothing is owed, when the obligation lives on the payment term. - Bumped every UCP version pin from 2026-01-11 to 2026-08-25 across the specification, site-docs, the demo merchant profile, and the home page. A profile declaring the payment terms extension at 2026-08-25 alongside a core version of 2026-01-11 would have been incoherent. Verified first that the UCP checkout status values the specification cites informationally are unchanged in the newer version.
- Repaired every UCP documentation link, all of which had gone stale: the checkout specification moved under
shopping/, the REST binding page moved again toshopping/checkout/rest/, the checkout JSON Schema moved underlatest/, and the shopping OpenAPI document moved fromschemas/toservices/. Two of the four were returning 404 rather than redirecting. - Registered
pay-at-service-settlement-extensionas a canonical specification fragment intools/usp_check.pyand added the matching anchor to the site-docs specification index, so the capability's profilespecURL resolves on the published site rather than pointing at a fragment that does not exist. - Synced site-docs: the UCP-Native profile examples (which CI asserts match Section 7.2 byte for byte), the payment timings section, a new extensions page section for the settlement extension, and the core-concepts commerce-mode table.
- Added the two conditional capability entries to the Section 7.2 example profile with a note that they are required only for the timings that need them, so the example does not read as making them mandatory.
11/09/26 at 14:37:14 by Ran Yahalom
- Rebuilt Section 9.4 as three disjoint error families (business outcome, protocol error, ESP frame code) with a total code matrix, because
site-docs/errors/had registered RFC 9457 ProblemtypeURIs for codes the spec classified as HTTP 200 business outcomes, so a conforming client could not tell from the spec whether to readmessages[]or a Problem body - Replaced the unscoped "
booking_not_foundreturns 200" rule with a per-operation rule keyed on where the identifier appears: path-addressed operations return 404, body-identified batch operations report unknown ids inmessages[]. The previous blanket rule contradicted the OpenAPI binding, which was already correct - Declared the JSON-RPC number a coarse bucket and
data.codethe authoritative, mandatory discriminator, which resolves the conflict between the spec's per-code -32001..-32009 assignment and OpenRPC's single -32600, and also unblocks future codes now that the -32001..-32009 range is fully allocated - Added
hold_limit_exceededto the matrix and made Section 10.1.2 require it. The code existed only as an orphan site-docs page while the section mandating concurrent hold limits named no code, leaving platforms unable to distinguish "you already hold this slot" from generic rate limiting - Standardized feed pagination on
next_cursoras an opaque token over(modified_at, id)ascending withidas the deterministic tie-break, and removed the claim that the cursor is a timestamp string. Without a tie-break, records sharing amodified_atcould be skipped or repeated across pages - Made the Section 7.5 atomicity guarantee operable as six numbered rules (check before charge, never leave a charge without a booking, no partial state on failure, idempotent retry after an unknown outcome, hold disposition on failure, reconciliation). "No partial state changes are permitted" was unfalsifiable and silent on the case that actually occurs: the PSP charge succeeds and the booking write fails
- Split hold-expiry failures into
hold_expiredwhen the slot is still bookable andslot_unavailablewhen it is not. Requiringslot_unavailablefor both told platforms to discard a slot that was still free - Added Section 4.2.1 requiring atomic hold-to-booking conversion, with a failure matrix and the rule that
party_sizeMUST NOT exceed the hold'sspots. The relationship between the two capacity counters was previously undefined, so a booking could claim spots that were never reserved - Required reschedule to acquire the new slot before releasing the original, since the unordered "original slot is released and the new slot is occupied" permitted an implementation that leaves the buyer with no booking at all
- Added Section 5.1.1, a per-operation booking state transition table plus
invalid_transition. The lifecycle diagram showed which statuses follow which but never which operation is legal from a given status, and a stale "MUST return a 409" in the reschedule section contradicted the 200-plus-messages[]business-outcome rule - Rescoped the Section 7.2 profile requirement to USP-owned capability keys and removed USP's assertion about what makes a UCP profile valid overall. USP has no authority to define UCP profile validity, and a consumer that cannot resolve the checkout capability now fails closed for checkout-backed services rather than rejecting the whole profile
- Added Section 7.6.1 forbidding UCP-Native businesses from advertising
at_serviceordeposit_required, neither of which has a specified payment path in that mode. Letting a platform improvise produces a booking that looks confirmed to the buyer while the business has no record of how it will be paid - Renamed the Section 2.2 commerce modes to No payment / Pay at service / Pay at booking / Deposit at booking, because two of them were called "Standalone", which collided with the Standalone deployment mode and made an ordinary configuration read as a contradiction
- Extended Section 10.1.3 with platform-side privacy requirements (log minimization, redaction in error echoes, cache bounds, no secondary use, limited onward transfer). All three prior bullets constrained only the business, while the platform holds the same data across many buyers
- Added
schemas/esp.jsondefining all twelve ESP messages, so Section 9.5.3's requirement to validate every frame against "the expected JSON-RPC schema" now names a schema that exists; six delegation messages previously had no documented wire shape anywhere - Encoded the Section 3.11 service-validity prose as machine-checkable
if/thenandoneOfconstraints inschemas/catalog.json, addedcapacity.waitlisttoavailability.jsonso thewaitlistslot state has the flag it is keyed off, addeddelivery_addresstopaid_bookings.jsonso UCP-Native checkouts can carryat_buyer_locationaddresses, and constrainedcanceled_byto an enum - Added the four missing MCP feed-subscription methods to
openrpc/usp-mcp.jsonand Section 9.2.1, establishing 31 REST to 31 MCP parity, and downgraded the A2A mapping to informative and partial with an explicit non-parity list, since it covers 12 of 31 operations and was presented as complete - Added three flow test vectors under
tests/vectors/flow/for hold expiry mid-checkout, a concurrent-hold race, and DST-spanning slots. Each records the plausible wrong answers and what they cost, because a spec can say "atomic" and "use instants" and be read as agreement by two implementations that behave differently - Added a
coherencesubcommand totools/usp_check.pyand wired it into CI. It catches the three drifts that read as healthy prose: a field table naming a field its schema dropped, an operation added to one binding only, and a binding emitting an error code the matrix never defined - Fixed the MCP business-outcome path to
result.structuredContent.messages[]in all three places it was wrong, and corrected the UCP checkout example toorder: { id }rather than a root-levelorder_id, which agents would otherwise read as a real UCP field
10/09/26 at 12:22:00 by Maor Yehuda
- Added a
SHOULDin section 5.3.6 requiring a business whosebooking_scoped_credentiallifetime is derived from the slot to re-issue on the reschedule response, because a credential'sexpires_atis fixed at creation against the slot the booking occupied then and rescheduling does not move it — so rescheduling beyond that window strands the platform with a booking it can no longer read, reschedule or cancel before the appointment happens, holding only a proof of possession and no way to obtain a fresh credential - Stated that the previous credential MAY be left to expire on its own rather than being revoked, so an agent still in flight with the old value is not cut off mid-operation; section 5.6 already permits several live credentials per booking
- Mirrored both in
site-docs/specification/booking.mdso the published site does not omit a rule that silently breaks long-range reschedules
30/08/26 at 12:58:11 by Ran Yahalom
- Trimmed availability-hint and registry-ranking prose to the interoperability boundary: sections 3.6 and 6.3 now carry wire shapes, semantic guarantees, and response-state rules only, because projection procedures, scoring formulas, horizons, weights, dominance arithmetic, and worked ranking walkthroughs are registry-specific implementation detail that does not belong in normative protocol text
- Consolidated the former 6.3.2-6.3.4 subsections into one "Availability Ranking Context and Response Signals" section that states the advisory request shapes, the observable guarantees a client can rely on, and a response-state table separating unknown (
hint_usable: falsewith null values) from known non-overlap (coverage: 0), so agents stop inferring unavailability from a registry that simply had no structured evidence - Made
slot_bitmapsoptional insideAvailabilityHintinschemas/catalog.jsonand the prose, since a producer that never sampled a grid previously had to drop the natural-language summary as well; a summary-only hint is now valid and yields the unknown response state - Required all five
RankSignalsmembers whenever the object is emitted inschemas/registry.json, because a partially populated object made unknown and known-empty indistinguishable for clients re-ordering a page - Mirrored the same boundary in
site-docs/specification/service-catalog.mdandsite-docs/specification/discovery-registry.mdso the published site does not describe an algorithm the specification no longer states - Simplified the playground availability fixture to one structured hint and added a summary-only hint, so the fixtures exercise both hint forms now that structured rulers are optional
- Rewrote
tools/availability_ranking_checks.pyand the availability check intools/usp_check.pyto assert the public contract (bitmap decoding and index bounds, index-to-time mapping across offsets, the exclusivevalid_untilcutout, age-neutral usability, and every response state) and to fail if registry-specific ranking material reappears in public sources - Aligned the section 4 caching tier with the validity model instead of a fixed 1-6 hour window, which contradicted the producer-declared
valid_untilcutout
29/08/26 at 21:13:04 by Ran Yahalom
- Added approved design and implementation plans plus a bitmap mental model and end-to-end data flow, because registry implementers need to understand why Roaring sets are used and how their operations produce coverage, density, and soonness
- Expanded intent projection into complete worked groups for grid boundaries, unions, occupancy, duration selection, invalid hints, flag modes, freshness, horizon arithmetic, and pagination, correcting the before-origin soonness calculation and making every intermediate ranking value derivable
- Restored the service-catalog and discovery-registry site pages as full implementer-facing mirrors, because the previous summaries omitted wire decoding details, ranking rationale, dominance and refresh rules, and most planned edge cases
- Added data-driven projection vectors, known-empty and all-open checks, validity-boundary assertions, and tutorial coverage sentinels, so calculations and public documentation cannot silently regress or become abbreviated again
- Reordered the implementation tutorial from bitmap construction through ranking output and corrected its links to targets that will exist after publication, so producer, registry, and agent owners can follow one verified reading path
29/08/26 at 17:17:50 by Ran Yahalom
- Added
AvailabilitySlotBitmap, non-emptyslot_bitmaps, optionalvalid_until, and registryDesiredServiceTimePreference,RankSignals,desired_service_time_ranges, andprefer_sooner_availability_slotsin canonical schemas, because discovery ranking needs one portable bitmap contract and disclosed rank ingredients without duplicating shapes in bindings - Wrote normative specification sections 3.6.2-3.6.6 and 6.3.2-6.3.4 (projection, scoring, freshness cutout, dominance invariant, edge-case matrix) and fixed the
AvailabilitySlotBitmapanchor slug, so implementers can derive the same coverage, density, and soonness results from the prose - Extended OpenRPC
usp_registry_search_serviceswith the new request parameters and thinDesiredServiceTimePreference/RankSignalscomponent references, because MCP callers need the same ranking inputs as REST without inline schema duplication - Adapted the playground Swedish massage fixture to Back Massage with the verified two-duration Roaring32 hint, removed summary-only hints elsewhere, and added
tools/availability_ranking_checks.pyplususp_check.pyschema, projection, scoring, rejection, and dominance assertions (withpyroaringinrequirements-dev.txt), so fixtures and CI enforce the bitmap ranking contract - Removed the dead
site-docs/migration.mdallowlist entry fromcheck_authority, because the migration page is already gone and v2 has no published predecessor on the site
29/08/26 at 17:14:49 by Ran Yahalom
- Expanded
site-docs/specification/service-catalog.mdwith availability bitmap subsections (what gets published through The JSON), updated field tables, removed 6-hour decay language, and replaced summary-only hint examples withslot_bitmaps, so the published catalog docs match the normative bitmap ranking model - Added availability ranking sections to
site-docs/specification/discovery-registry.md(search request usage, reading it back, intent projection edge cases), plusdesired_service_time_ranges,prefer_sooner_availability_slots, andrank_signalson search examples, so registry discovery docs stay aligned with bitmap-based reranking - Updated
site-docs/specification/availability.mdcaching tier text to referencevalid_untilinstead of 1-6 hour hint TTL, because freshness is now a usability cutout rather than continuous score decay - Removed invalid summary-only
availability_hintobjects fromsite-docs/playground/scenarios/services.json(unknown availability is omitted), pending the main playground fixture update with the back-massage bitmap example - Deleted
site-docs/migration.mdand removed its MkDocs nav entry, because v2 has no published predecessor to migrate from on the site
26/08/26 at 16:04:32 by Ran Yahalom
- Added specification §7.5.1 (merchant policy parity and eligibility, UCP overlay), because Track S required a UCP-first decision on mandatory acceptances, eligibility, and recurring scope without inventing parallel USP wire types
- Clarified that §10.1.4 buyer consent is privacy-only and that mandatory checkboxes use UCP checkout escalation or USP
requires_action, so implementers do not overload consent categories for merchant policy gates - Mirrored the overlay in
site-docs/deployment-modes/ucp-native.md,site-docs/specification/service-catalog.md(service policies, links), andsite-docs/roadmap.md(recurring enrollment out of the current release), keeping the published site aligned with the normative text
26/08/26 at 13:35:53 by Ran Yahalom
- Completed the §7.2 free-service-only UCP profile example with the same
businessidentity object as the paid example, becausebusiness_schemarequiresbusinessand the published free-service fence could not be copied as a valid document - Added a
usp_check.py schemasinstance check that extracts §7.2ucpdocuments, validates them againstbusiness_schema, and requires the UCP-Native site-docs profile examples to match, so those published examples cannot drift from the canonical schema or from each other
26/08/26 at 09:22:12 by Ran Yahalom
- Conditioned §9.2.3 signature verification on emitted webhook payloads so that section cannot be read as requiring outbound webhooks after the REST and MCP checklists became outbound-only MUSTs
- Restated
confirmation_modeon the service-catalog site page with the advertisedexpires_atcancellation rule, because the shortened "approval within 24 hours" line no longer matched the booking-expiry advertisement condition - Restated standalone payment-action expiry to match §8.5.4: the payment clock is independent of Booking
expires_at, and a payment action deadline SHOULD not outlive an advertised booking deadline or an existing hold
26/08/26 at 08:24:38 by Ran Yahalom
- Conditioned §5.2 booking-expiry MUSTs on advertising
expires_at, because those rules exist to release inventory held for unconfirmed bookings and a business that does not hold capacity has nothing to release - Documented omitting
expires_atas a conformant wire shape when nothing is held, while a business that holds unconfirmed slot capacity MUST include the field and any advertised deadline remains a hard MUST (cancel, remain retrievable, release any hold) - Aligned §3.10 confirmation_mode and §8.5.4 payment-action alignment with that advertisement rule, left payment-action expiry independent of Booking
expires_at, updatedschemas/booking.jsonplussite-docs/specification/booking.md, and left OpenAPI/OpenRPC as thin$refs
26/08/26 at 08:22:05 by Ran Yahalom
- Defined registry business and service category filters as exact category-ID matches, because display-label ambiguity made equivalent searches behave differently across operations
- Added round-trippable category IDs to registry results while preserving service category display text separately, so callers can reuse emitted tokens without guessing
- Reused the canonical registry category-ID schema from both REST and MCP bindings, preventing transport descriptions from drifting
26/08/26 at 08:21:37 by Ran Yahalom
- Conditioned REST §9.1.5 item 7 and MCP §9.2.4 item 7 so webhook signing (and MCP JSON-RPC webhook notifications) are required only when the implementation emits webhooks or advertises outbound webhook delivery, because an otherwise valid binding that does not send webhooks could not satisfy those checklist MUSTs as previously written
- Left §10.1.1 signing rules unchanged so payloads that are emitted remain mandatory to sign
- Mirrored the same conditions on
site-docs/transport/rest.mdandsite-docs/transport/mcp.md, and aligned the MCP page's MUST/SHOULD lists with current §9.2.4, so the published site matches the normative checklists
24/08/26 at 12:00:00 by Daniel Jaffe
- Widened the four
propertyNamespatterns onbusiness_schemaandplatform_schema(servicesandcapabilitieson each) inschemas/usp.json, because^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)+$admits no hyphen and therefore rejecteddev.usp-protocol.services.catalog— the §7.2 example profile did not validate against the specification's own canonical schema, and perAGENTS.mdauthority order (schemas/*.jsonover prose) a conforming validator rejected the profile the specification tells implementers to publish - Fixed the underscore as well, which was never rename fallout: the old pattern also rejected
dev.usp-protocol.services.paid_bookingsanddev.ucp.common.identity_linking, so it had been narrower than the namespace it describes since before the2026-08-20cutover - Added
check_namespace_key_patternstotools/usp_check.py schemas, asserting that every reserveddev.usp-protocol.*name and the third-party names the specification's examples carry satisfy everypropertyNamespattern gating a capability or service key map, so the next namespace change cannot silently leave a pattern behind; the reserved-name list moved to a module constant now that the authority and schemas checks both read it - Kept the patterns otherwise unchanged: two labels minimum, lowercase first character per label, no leading or trailing hyphen or underscore in a label, and no empty label
24/08/26 at 00:00:00 by Maor Yehuda
- Required §10.1.6 verifiers to reject a proof whose header JWK declares a
crvother than the one the acceptedalgrequires, and forbade treating two thumbprints differing only incrvas distinct principals, because the [RFC 7638] thumbprint coverscrvwhile JOSE libraries in wide use accept anOKPkey labelledEd25519,Ed448,X25519orX448without checkingxagainst it — so one key's own bytes re-labelled produce a differentjktthat still verifies, and since the thumbprint is the platform identifier that hands one key several identities and lets a principal already rejected by the trust-on-first-use binding re-bind as a first contact - Folded the curve into step 5 of the normative verification order rather than adding a step, because
algis already checked there and the two are one decision about the same header - Added vector
011-crv-substitution(K1's own bytes labelledcrv: X448, genuine signature,pop_proof_invalid) and cited it inspecification.md, following the006model of a rejection case a plausible implementation would accept — a library strict enough to refuse at parse passes it too, since the outcome is the same rejection - Defined
[RFC 8037]in the reference block, since Section 3.1's prohibition on signing withX25519/X448key-agreement keys is now cited
23/08/26 at 16:20:16 by Ran Yahalom
- Fixed §10.1.6 identity binding so trust-on-first-use is keyed by principal, not by profile URI, because the previous MUST rejected any principal that did not match the one recorded for a URI and would lock out every later instance of a shared platform profile after the first caller
- Left the converse case (a different key presenting an already-seen URI) as optional flag-or-rate-limit only, because a single keyless profile document is deliberately shared across a population of personal agents and that presentation is the normal case, not impersonation
- Aligned the §9.2.2 MCP restatement and
site-docs/security.mdplus REST/MCP transport pages with the same direction so the site and the MCP "bound to" sentence cannot be read as URI-to-principal rejection
23/08/26 at 14:19:48 by Ran Yahalom
- Added non-normative §9.7 Observability join recommending optional
USP-Correlation-Id/_meta.usp.correlation_idpropagation across money-path hops, because Track S (#160) needs a single vendor-neutral join convention without making observability a USP conformance gate - Placed the recommendation once under Transport Bindings with per-binding carriage (REST/A2A HTTP header, MCP
_meta, ESPcorrelation_id) and explicit "omitting this is conformant" language, matching how idempotency and profile already pair REST headers with MCP fields - Documented optional overlays in
openapi/usp-rest.jsonandopenrpc/usp-mcp.json, mirrored the join onsite-docs/transport/pages, and listedUSP-Correlation-Idunder future IANA registration so machine-readable bindings stay aligned with the advisory spec text
23/08/26 at 14:10:26 by Ran Yahalom
- Rewrote UCP-Native payment-handler prose in
specification.mdandsite-docs/deployment-modes/ucp-native.mdas protocol rules only (checkoutavailable_instrumentsauthority,handler_idmatching), and removed the site-docs GitHub issue link plus Stripe/CLI/402 probing from normative text, because those were implementation details and tracker references rather than USP requirements. Stripe handler JSON remains in examples only
23/08/26 at 12:11:15 by Ran Yahalom
- Added a human-confirmation requirement to
specification.md§8.5: an agent MAY facilitate a paid Standalone booking, but the buyer MUST authorize the charge on a trusted, deterministic surface unless a negotiated mechanism supplies AP2-equivalent cryptographic proof of authorization. Standalone Mode previously had no such rule, so a conforming implementation could charge a buyer with no human confirmation, while UCP-Native inherits UCP checkout's trusted-UI rule through the capabilitydev.usp-protocol.services.paid_bookingsextends. The addition is parity with UCP, states no vendor or product, adds no wire field, and leaves §7 unchanged - Defined what counts as a trusted, deterministic surface (business-hosted
continue_urlpage, a checkout system or payment provider confirmation surface, or a deterministic platform component) so the requirement is testable without USP prescribing which party renders it - Clarified §8.5.4 that "programmatically" describes charge mechanics rather than buyer authorization, and changed §8.6.3 from "the buyer MAY complete payment on the business-hosted page" to a statement that the page is the trusted surface for the redirect path, because both readings otherwise contradicted the new §8.5 rule
- Mirrored the rule in
site-docs/deployment-modes/standalone.md(Payment Integration, embedded flow, redirect flow) and added a Standalone security-checklist row insite-docs/security.mdmarked inherited for UCP-Native, so the site does not describe agent-completable payment after the spec forbids it
23/08/26 at 03:37:56 by Ran Yahalom
- Replaced placeholder Stripe UCP handler examples (
com.stripe.agentic_commerce.shared_payment_token,stripe_spt_demo_h1,shared_payment_tokeninstrument) with the publishedcom.stripe.paymentshandler (2026-06-25) inspecification.md§7.2, §7.4, and §7.7.2, because Stripe's handler schema is now available and issue #108 requires real wire shapes instead of pre-schema placeholders - Added normative prose that UCP-Native platforms MUST read
network_idfrom checkoutavailable_instruments(type: "link",config.network_id) and that Link Agent Wallet submitsstripe_payment_tokenon instrumenttype: "link", demotinglink-cli mpp decodeand merchant HTTP 402 probing to fallback/Standalone-only paths so agent docs stop treating merchant probe as the default SPT acquisition route - Mirrored the same handler mapping and payment-handler guidance in
site-docs/deployment-modes/ucp-native.mdanddocs/ucp-native-demo-merchant-profile.example.jsonso the published site and copyable demo profile stay aligned with the normative spec
23/08/26 at 02:28:29 by Ran Yahalom
- Removed
plans/,docs/website-deployment.md,render.yaml, and.github/workflows/mirror-to-public.ymlfrom the public tree so the published repo is protocol material rather than private sprint plans, private Render preview config, a dormant private-to-public force-push job, or Pages DNS operator notes - Updated
docs/ucp-native-demo-merchant-profile.example.jsonto match specification §7.2 (includingholds: trueon availability and the §7.2accepted_mechanismsset) while keepingucp.keysdual-published with thesigning_keystransition alias, because that file is the copyable paid UCP-Native profile and had drifted from the normative example - Aligned the site-docs UCP-Native full and free-service profile examples with §7.2 (
spec/schemaon every capability, pluspayment_handlerson the paid profile) so the website does not publish a thinner or invalid profile than the specification - Dropped the
website-deployment.mdexception fromtools/usp_check.pyauthority allowlists because that file no longer exists - Switched
.github/workflows/ci.ymlto GitHub-hostedubuntu-latestand removed the repository-name skip, so public pull requests get the same schema, ref, vector, site-build, and authority checks without naming a private repository or requesting self-hosted runners
20/08/26 at 12:52:55 by Ran Yahalom
- Released the breaking
2026-08-20hard cutover from the unownedusp.devauthority tousp-protocol.dev, including thedev.usp-protocol.*capability namespace, canonical specification fragments, migration guidance, reserved-name registry, and synchronized schemas, bindings, examples, playground fixtures, and site documentation - Published every schema at its
$idpath, both thin bindings under/schemas, and human-readable kebab-case problem types under/errors, because protocol identifiers must resolve from the authority origin instead of pointing at missing resources - Added artifact-aware local, CI, Pages, and fallback builds plus authority conformance checks for origin binding, namespace names, stale identifiers, canonical paths, binding references, problem pages, and playground mirrors so future releases cannot silently reintroduce identifier or publication drift
- Documented GitHub Pages compatibility limits and the remaining owner-operated
usp.liveredirect and downstream same-release coordination, so repository-complete work is distinct from external cutover operations
19/08/26 at 20:44:05 by Ran Yahalom
- Added
site-docs/CNAMEto version control so future MkDocs publishes retain the liveusp-protocol.devGitHub Pages custom-domain binding instead of silently dropping it
19/08/26 at 20:28:14 by Ran Yahalom
- Removed
docs/dtc_charter_nomination.mdfrom the tree. That document was a UCP governance submission draft and does not belong in the public protocol repository
19/08/26 at 19:48:21 by Ran Yahalom
- Settled the protocol version advertised by the website and playground on the current draft
2026-08-14fromspecification.md. Site-docs, homepage examples, JSON-LD, LLM index files, social-card SVG, and playground scenario mirrors had been left on superseded2026-02-21, so the published site contradicted the spec it is supposed to describe - Updated the Standalone
supported_versionsexample in bothspecification.mdandsite-docs/deployment-modes/standalone.mdso the current version is2026-08-14and the advertised prior version is2026-02-21. The previous2026-06-01/2026-02-09pair was not a real USP release pairing - Pointed site-docs links that targeted
../specification.mdand repo-relativeschemas//openapi//openrpc/files at the public GitHub copies instead, because those paths are outside MkDocsdocs_dirand produced broken links on the published site - Replaced private
wix-private/universal-scheduling-protocol-specartifact URLs inllms.txtandllms-full.txtwithwix/universal-scheduling-protocol, matchingmkdocs.ymlrepo_url - Aligned playground profile
spec/schemaURIs with the shapes in the specification (https://usp.dev/specification#3-service-catalogandhttps://usp.dev/schemas/services/...), and corrected playground envelopes that still useddev.usp.services.booking(singular) and array-formcapabilities
19/08/26 at 19:35:46 by Ran Yahalom
- Gave the UCP-Native tab of the homepage "See it in action" section its own capability sub-tabs (Discovery, Availability, Checkout) in
overrides/home.html. Previously only the Standalone tab exposed sub-tabs, so UCP-Native looked like a single flat example and hid the fact that catalog, availability/holds and checkout are distinct capabilities in that mode too - Corrected the UCP-Native examples while rebuilding them: the profile response now nests
servicesandcapabilitiesunderucp(they were siblings of it), and the checkout request now carriesbookingas a top-level member rather than inside a line item, matchingsite-docs/deployment-modes/ucp-native.mdand the paid-bookings extension schema - Fixed the response envelope in the Standalone catalog example, which used a
capabilitiesarray of{name, version}objects instead of the specified object keyed by capability name, so the homepage no longer contradicts the spec - Renamed the CSS class
standalone-tab-panetomode-tab-paneand dropped the#action-tab-ucp-nativerow-layout overrides insite-docs/stylesheets/extra.css, because both deployment-mode panes now share the same sub-tab layout and the id-specific rules would have forced the sub-tab container into a two-column row
19/08/26 at 19:21:12 by Ran Yahalom
- Stopped using
actions/upload-pages-artifactin.github/workflows/pages.ymlbecause that composite nestsuses: actions/upload-artifact@v4(a moving tag), and Wix org policy rejects nested unpinned actions at job setup even when the parent is SHA-pinned - Pack
site/as a tar in the workflow and upload it withactions/upload-artifactpinned toea165f8d65b6e75b540449e92b4886f43607fa02(v4.6.2) under artifact namegithub-pages, soactions/deploy-pagesstill receives the required Pages artifact without a nested tag - Documented that
actions/deploy-pagesv4.0.5 is a Node action with no nesteduses:, and updateddocs/website-deployment.mdso operators know why the official Pages upload composite cannot be used under SHA-pin policy
19/08/26 at 19:13:52 by Ran Yahalom
- Merged
origin/masterintochore/pages-branch-deployand resolved conflicts inCHANGE_LOG.md,docs/website-deployment.md, andscripts/publish-pages.sh, so the PR can merge without dropping SHA-pinned Actions auto-publish or the liveusp-protocol.devdomain notes - Kept both changelog stories (SHA pins plus custom-domain/live HTTPS notes, and the earlier
gh-pagespublish path from master) without duplicating headings, because each records a distinct operator-facing change
19/08/26 at 19:00:14 by Ran Yahalom
- Pinned every GitHub Actions
uses:inpages.yml,ci.yml, andmirror-to-public.ymlto full-length commit SHAs (checkout v4.4.0, setup-python v5.6.0, upload-pages-artifact v3.0.1, deploy-pages v4.0.5), because Wix org policy now requires SHA pins and tag-style refs such as@v4fail that check - Updated
docs/website-deployment.mdand comments inscripts/publish-pages.shso they describe auto-publish via.github/workflows/pages.ymlwhen Pages Source is GitHub Actions, and treatnpm run publish:pagesas fallback only, because Actions is enabled and a branch deploy fights the workflow once that source is live
19/08/26 at 18:10:41 by Ran Yahalom
- Aligned website-facing draft labels (homepage banner, spec overview, roadmap status, JSON-LD, llms.txt, social card) with
specification.mdversion2026-08-14, because the live hero still advertised supersededv2026-02-21 - Updated
docs/website-deployment.mdto record thathttps://usp-protocol.devreturns 200,www301s to apex, and Enforce HTTPS is on, so operators do not treat the GitHub Pages http:// banner as a remaining DNS/TLS blocker
19/08/26 at 17:47:16 by Ran Yahalom
- Recorded AC-S3e option B:
usp-protocol.devis the canonical host for the full MkDocs site and published artifacts, withusp.liveto redirect later, so cutover messaging andsite_urlmatch the chosen hosting model instead of a split authority/docs setup - Pointed MkDocs
site_url,llms.txt,llms-full.txt,robots.txt,humans.txt, and the social-card watermark athttps://usp-protocol.dev, and addedsite-docs/CNAME, so GitHub Pages canonical URLs and the nextgh-deploykeep the custom domain instead of advertisingusp.live - Documented the domain, DNS A/CNAME targets, and Enforce HTTPS step in
docs/website-deployment.mdand the publish script output, so operators do not drop the Pages custom-domain binding on republish
18/08/26 at 17:17:41 by Ran Yahalom
- Published the MkDocs site to a new
gh-pagesbranch and pointed GitHub Pages at it (branch source,/ (root)), so the website is live at https://wix.github.io/universal-scheduling-protocol/. GitHub Actions is disabled for this repository by the organisation, so.github/workflows/pages.ymlcannot run; serving pre-built HTML with a.nojekyllmarker publishes the site without waiting for an org policy change - Added
scripts/publish-pages.shand thepublish:pagesnpm script wrappingmkdocs gh-deploy, because with no workflow available the build-and-publish step has to be run deliberately and should be one reproducible command rather than remembered flags - Documented the hosting model in
docs/website-deployment.md, including how to switch to the existingpages.ymlworkflow once Actions is enabled, and theCNAME-in-site-docs/requirement so a future custom domain survives the branch overwrite that each publish performs - Removed the root
PLAN.md, an internal multitask planning artifact that described private repository permissions and organisation ruleset details and should never have been visible in a public repository
15/08/26 at 21:07:15 by Ran Yahalom
- Reconciled
plans/V2_PRODUCTION_PLAN.mdagainst the current GitHub issue set, the landed USP2026-08-14specification and thelinkusp-cliagent. The plan was written 2026-08-05 and had drifted far enough that it described decisions as pending that had already been made and listed issues that no longer exist in v2 - a plan that misreports the state of the work is worse than no plan, because the launch-blocking set is read off it - Rewrote §1a and the V2-X1 / V2-X6 entries around the landed
platform_key_popdesign (§10.1.6, PR #200) instead of framing #9 as an open decision. Added the two authority tiers (privileged_platform/privileged_scoped), the ephemeral-key proof-of-possession model,cnf.jkt-boundbooking_scoped_credentials, andconfig.authorizationpolicy publication. Recorded the sequencing consequence that matters operationally: the shipped client enforcesrequiredby default and so refuses privileged calls against a business publishing no policy, making client and server a mutual release gate - Marked #42 and #134 as completed and kept them in the plan, since they were closed as fixed; noted that #134's retained credential is the client half of V2-X6, so the server half is still outstanding rather than the whole item being done
- Removed #125 (closed - no concept of "onboarding to the USP agent" in the current design) and #196 (closed as duplicate of #132) from the plan, and stripped the stale
v2labels from #196 and #204 so label-scoped reporting stops counting work that is tracked elsewhere - Re-scoped #124 on GitHub and dropped it from the plan: its platform-profile content duplicated #114 and was stale under the now-keyless profile model, its vault content died with #125, and its v2-relevant remainder is #136. Rewrote the body as per-repo/owner AC checklists covering only Standalone mode and moved the label
v2→v>2, because v2 is UCP-Native only - Integrated the
v2issues added after the plan was written (#197, #201, #205) into a new §3.2a, and added #201 to the launch-blocking set - hand-written models silently droppedBooking.revisionand disabled §5.6 conditional writes end to end, and the name-only conformance sweep cannot catch a recurrence - Split the engineering halves out of the legal issue #197 into #206 (honor merchant opt-out across admission, eviction and serving) and #207 (exclude non-indexed provider sites, opt-in only, failing closed), both assigned to the registry owner. An opt-out that nothing enforces is not an opt-out, and the non-indexed rule needs the inverse default from the ordinary gate. Flagged #197 item 3 (booking-experience parity) as substantial engineering still sitting unsplit inside a legal issue
- Replaced the two-week schedule with a dependency-ordering section and deleted the "open decisions needed from the owner" block, recording each resolution instead. Dates churned faster than the plan could track, and every listed decision is now made: auth mechanism, V2-X6 mechanism, #40 (in v2, remedy chosen at implementation time), #125 (closed) and #156 (do the namespace migration in v2, while nothing is live to break)
- Updated the derived sections for consistency - table of contents, issue counts, §7 labelling actions with a full reconciliation table - and verified every internal anchor still resolves
- Removed the plan-local
V2-*identifier scheme entirely, replacing every occurrence with a hyperlinked GitHub issue number, and deleted Appendix A which existed only to map between the two. Carrying two identifiers for the same item made the plan hard to read and meant every cross-reference had to be resolved through a lookup table - Added an Assignee column to every per-issue table in sections 3 and 4, populated from the live GitHub assignees rather than the track-owner defaults the plan previously assumed. These had diverged: the registry issues (#168-#176, #149) are assigned to
danieljaffe1, not the track owner named in §2, and several cross-cutting issues have two assignees. The grouped mandated-exclusions table is left without the column because its rows cover multiple issues at once
15/08/26 at 09:24:11 by Ran Yahalom
- Switched
.github/workflows/ci.ymltoruns-on: self-hosted. GitHub-hosted runners are not permitted in this organisation, anddevex-gha-authoritydoes not merely warn - it cancels the job, which is why thecheckrun on #200 reported a failure after one second without executing a single step. The validation tooling itself was never broken - Avoided naming the forbidden runner label even in the explanatory comment, in case the policy check greps the workflow file rather than parsing it - otherwise the comment explaining the rule would trip the rule
- Narrowed the
pushtrigger tomaster. Listening to bothpushandpull_requestunqualified ran the whole job twice for every commit on a PR branch, which is what produced the two separatecientries in the checks list
15/08/26 at 06:47:19 by Ran Yahalom
- Added an optional opaque
revisiontoBookingandWaitlistEntry, closing a gap the proof-of-possession work assumed was already filled: a bookingrevisiondid not exist anywhere in the repository, and neither didETag,If-Match, or any other conditional-request machinery. Abooking_scoped_credentialauthorizes a resource rather than a session and MAY be re-issued to the same key, so two agents - or one agent on two devices - can legitimately hold a valid credential for the same booking. Without a concurrency control the second write silently overwrote the first and neither caller learned anything was lost - Specified conditional writes in a new §5.6 and carried the precondition the same way idempotency is already carried:
If-Matchon REST,_meta.usp.if_matchon MCP - mirroring the existingIdempotency-Key/_meta.usp.idempotency_keypair rather than inventing a second convention for the same problem - Chose
412 Precondition Failedover reusing409, and said why in the text:409is already bound in this specification to idempotency-key conflicts, and collapsing the two would leave a platform unable to distinguish "your key was reused with different parameters" from "someone else edited this booking" - two failures with different remedies - Pinned the
Idempotency-KeyxIf-Matchordering as a MUST, which is a genuine correctness hole rather than a detail: an idempotent replay returns the stored response without re-evaluating the precondition. The caller's revision was current when the original request succeeded and that request changed it, so re-checking on replay would reject a call that had already been applied - converting a merely dropped response into a permanent failure - Made
revisionoptional, so the change is non-breaking and needs no version bump: adding a required response member would make every existing business non-conformant. Its presence in a response is itself the advertisement that conditional writes are supported, which is exactly the contract of an absent HTTPETag, so no capability flag was invented for it - Required the value to be opaque and to change on every modification, and warned against deriving it from
updated_atalone - two modifications inside one timestamp tick produce the same value and defeat the check silently - Scoped this to bookings and waitlist entries, the same pair §10.1.6 requires per-resource authorization for, and excluded holds deliberately: a hold has no update operation, only release, and releasing an already-released hold is idempotent, so there is no lost update to prevent. Because
usp_availability_releaseshares the MCP metadata wrapper that now carriesif_match, the field's description states that a business MUST ignore it there rather than leaving the ambiguity unaddressed - Documented
revisionin the §5.2 and waitlist field tables, not only in the schemas. A member that exists only inschemas/is precisely the defect just corrected in §8.2.3, where §9.1.4 pointed at a field table that documented nothing - Recorded that
_meta.usp.if_matchfalls inside theusp_pproof digest, which strips only_meta.usp.authorization, so on MCP the precondition is tamper-evident against an intermediary while the RESTIf-Matchheader is not - the same asymmetry that already applies to method arguments - Noted in §9.4 that allocating
-32002exhausts the USP JSON-RPC range:-32001through-32009are now all assigned, and a future protocol error needs either a new range or adata.codediscriminator, which is already the established pattern for the signature and proof-of-possession codes
15/08/26 at 05:08:33 by Ran Yahalom
- Corrected
site-docs/deployment-modes/ucp-native.md, which told UCP-Native implementers the opposite of the specification and is the highest-impact item here: its reading guidance listed only "Skip Sections 9.6 and 10.2" and omitted the entire "do not skip §10.1.6" carve-out, so a business following the published docs would have skipped the section that makes privileged-operation authentication mandatory. Also refreshed the stale Authentication row, which still read "UCP OAuth 2.0 support" after the specification broadened it to "UCP OAuth 2.0 / signature support" - Fixed
docs/ucp-native-demo-merchant-profile.example.json, which violated the rule it exists to demonstrate:signing_keyssat at the document root as a top-level sibling ofucpin a UCP profile - exactly what §10.1.6 forbids USP from doing. Moved it underucpas the UCP-canonicalkeyswith the transition alias dual-published, and added theconfig.authorizationpolicy the binding had entirely lacked. This file is what implementers copy, so a defect here propagates - Refreshed 133 stale
2026-02-09example literals across the specification, site docs, the OpenAPI examples, and the demo profile, while preserving the 7 that name a specific historical version on purpose - thesupported_versionsmap, thedev.usp.services.booking@2026-02-09pin illustrating pin syntax, and the roadmap history rows. The distinction is made by matching what a line says, not by counting occurrences - Added the missing
usp_services_lookuprow to the §9.2.1 method-mapping table, which listed 26 rows for 27 methods. The method is normative in REST and present in the MCP binding, so the omission made the table quietly wrong rather than merely incomplete - Deleted the duplicated link-definition block at the end of the specification. Every reference definition appeared twice; the second copy is now removed
- Replaced the inline
POST /registry/businessesrequest body inopenapi/usp-rest.jsonwith a thin$reftoschemas/registry.json$defs/RegistrationRequest, the duplication CLAUDE.md rule 3 forbids. The two copies were verified byte-equivalent first, so this deduplicates before they drift rather than after - Added the
requiresobject toschemas/paid_bookings.json, which §1 says extension schemas SHOULD declare - Fixed six pre-existing broken internal anchors, each resolved by locating the section whose heading actually matches rather than by guessing from the section number -
#1123-paid-bookingspointed at a calendar schema section, and#92-error-handlingpointed at the MCP binding rather than the error-code mapping. One,#category-rules, referenced a bold run-in paragraph that is not a heading at all and now reads as plain text - Added an anchor check to
tools/usp_check.py, so a link to a non-existent section fails the build instead of reading as a working cross-reference that goes nowhere tools/known-issues.txtis now empty. Every failure the validator found when it was introduced has been fixed rather than tolerated, which was the acceptance criterion for this commit
15/08/26 at 04:31:52 by Ran Yahalom
- Added ten test vectors under
tests/vectors/pop/covering canonicalization, issuance, presentation, and six rejection cases.platform_key_popis specified on both bindings and implemented on neither, so without these the normative text ships entirely unvalidated - and canonicalization is the one part of it that can be wrong in a way review will not catch, because two implementers can read the same rule and encode it differently - Signed the proof vectors with real Ed25519 keys derived from fixed seeds rather than publishing placeholders, so an independent implementation can verify them instead of taking them on trust. The private keys are in the repository deliberately, documented as test-only, precisely so the vectors are reproducible byte-for-byte
- Made
006-cross-key-replaythe centrepiece and said so in §10.1.6: its proof verifies correctly against its own header key, so an implementation that checks the signature and stops will accept it. Only comparing the thumbprint against the recordedcnf.jktrejects it. That is the test the superseded profile-URI binding would have failed, and it is the difference between this mechanism and a bearer token wearing a proof - Extended
tools/usp_check.pyto verify the vectors rather than merely parse them: it recomputes every JCS serialization andusp_pdigest, verifies each signature against the JWK in its own proof header, recomputes each published thumbprint, checksexpected_claimsagainst the signed payload, and asserts that apop_key_mismatchvector genuinely uses a key differing from the credential'scnf.jkt- otherwise that vector would pass while testing nothing - Made the checker fail any vector whose
idis not cited inspecification.md, and cited all ten in a §10.1.6 table. Vectors that nothing references are the normal way this kind of artefact rots; this makes prose and vectors fail together instead of drifting apart - Verified the checker is not vacuously green: tampering with a signature and neutering the cross-key vector each produce the expected failure
15/08/26 at 04:02:15 by Ran Yahalom
- BREAKING. Raised §10.1.6's per-resource authorization requirement from SHOULD to MUST for privileged operations on an existing booking or waitlist entry. The section deferred this explicitly while the credential's issuance format was unspecified; that format is now specified, so the deferral has expired. Platform authentication alone does not satisfy it, which is the entire point: a business accepting only a platform-level mechanism authorizes any authenticated platform to act on any booking it can identify
- Named the resource types the MUST covers instead of leaving it as "get/cancel/reschedule/PII", because the other two resource families need different answers and an unqualified MUST would have swept them in. Feed subscriptions: RECOMMENDED - no buyer personal data, but a subscription ID is still not a credential. Registry registrations: NOT REQUIRED - authorized at platform tier against the registering platform's bound principal, since a registry entry has exactly one owner
- Bumped the protocol version from
2026-02-21to2026-08-14, and recorded in the specification itself that this is a breaking authorization change rather than a clarification: a business conformant under2026-02-21may be non-conformant under this version without changing a line of its own code. Shipping that quietly under the old version number would have removed the only signal an implementer gets - Restricted the bump to the five places that assert this repository's version identity -
specification.md,README.md, both bindinginfo.versionfields, and a new roadmap row - and deliberately left every literal that names a specific historical version alone: the/.well-known/usp-2026-02-09supported_versionsexample, thedev.usp.services.booking@2026-02-09capability pin illustrating pin syntax, and the roadmap's history rows. Bumping a pin example would teach that pins track the current version, which is the opposite of what a pin is - Fixed a two-release staleness in passing: both bindings carried
info.version2026-02-09while the specification was at2026-02-21, so the bindings had been advertising a superseded version. Theversionassertion added with the CI now makes that class of drift a build failure rather than something found by inspection, and its entry intools/known-issues.txtis now cleared - Landed this as its own commit, apart from the additive mechanism registration, so the breaking and non-breaking halves of this work can be reviewed - and if necessary reverted - independently
15/08/26 at 03:38:40 by Ran Yahalom
- Rewrote §10.1.6's identity-binding MUST, which was unsatisfiable as written for a permissionless caller. It required a business to confirm the authenticated principal is authorized to act on behalf of the profile in the agent header, but a profile URI is self-asserted, fetched over an unauthenticated GET, and deliberately shared by every instance of a platform - so nothing in the document distinguishes one caller from another. A requirement that cannot be met gets implemented as a string comparison against a caller-supplied header, which authorizes nothing at all; that is exactly the defect this work exists to correct
- Defined what the MUST means instead: the authenticated principal is the key (the
jktunderplatform_key_pop, the profile-published key underhttp_message_signature, the registered client otherwise), the profile URI carries branding and capabilities and MUST NOT be treated as an authentication factor, and the pairing is recorded trust-on-first-use with a later mismatch rejected - Stated that a key-bound credential satisfies the mechanism-independent identity-binding MUST on its own, and that a business MUST NOT require a second platform credential on the same request merely to satisfy it. Without that sentence the natural reading forces every scoped call to carry two credentials, which would defeat the point of a per-resource one
- Applied the same reading to the MCP restatement of the rule, and recorded there why
_meta.usp.profileis deliberately kept inside theusp_pdigest: the profile a caller asserts is then covered by the proof rather than free to be rewritten in transit - Made §10.1.6's mechanism table illustrative rather than exhaustive. Read strictly, "a business MUST accept at least one of the following" over a five-row table meant a business accepting only a newer mechanism accepted none of them and was non-conformant - contradicting the forward-compatibility rule twenty lines below, which makes the same list an extension point
- Specified credential lifetime and invalidation:
expires_attracks the resource rather than a session, invalidation at terminal state is a MUST, and re-issuance to the same bound key on an authenticated read is permitted so a long-lived booking survives an expiry without a new create call - Scoped the word "revocable" honestly: USP defines no revocation operation on any binding. Expiry and terminal state are the only invalidation paths, and both are the business's own doing. Saying so plainly is what stops an implementer designing around a protocol facility that does not exist, and it is the reason
expires_atis REQUIRED rather than optional - expiry is the only bound the protocol itself guarantees
15/08/26 at 03:14:22 by Ran Yahalom
- Removed
booking_scoped_credentialfromPUT/DELETE /registry/businesses/{id}, where it was offered although no booking exists - contradicting both the scheme's own description and the platform-tier_metawrapper those methods used - Closed the hole that removal opens, which "platform_key_pop replaces it" does not close on its own:
usp_registry_updateandusp_registry_deletewereprivileged_scoped, so dropping the credential would have left them with no per-resource authority at all, and raising scoped authorization to a MUST would then have made them MUST-scoped methods with nothing to scope against. Both are re-tiered toprivileged_platformand authorized against the registering platform's boundjkt. A registry entry has exactly one owner, so trust-on-first-use ownership is already the model and no new credential type is needed - Made the re-tier a paired edit and asserted it:
x-usp-access, the_metawrapper$ref, the method description, and the_metaparameter description all move together. Changing the tier without the parameter description would leave a platform-tier method whose own parameter documentation still recommends a booking-scoped credential. Post-conditions: tiers are 8 public / 8 platform / 11 scoped, boilerplate counts are 8/11/8/11, and no method is left half-swapped - Kept
booking_scoped_credentialon the four REST feed-subscription operations rather than removing it alongside the registry ones. Feed subscriptions are a third resource family, neither booking nor waitlist, and a subscription ID is exactly the "a resource identifier is not a credential" case §10.1.6 opens by warning about - dropping the per-resource mechanism there would have made the specification weaker, and scoping the forthcoming MUST to booking and waitlist would have silently orphaned them. The credential's description now names all three families explicitly, and states that registry registrations are deliberately not among them - Recorded the REST/MCP asymmetry rather than leaving it to look like an omission: MCP exposes no subscription-lifecycle methods at all, so those four operations exist only on REST. Requirement count for the credential moves from 17 to 15, with all four subscription operations intact
- Fixed the §9.2.2 prose tier lists, the only place the tiers are written out in English and therefore the easiest place for them to drift out of agreement with
x-usp-access
15/08/26 at 02:51:07 by Ran Yahalom
- Added five proof-of-possession error codes -
pop_proof_missing,pop_proof_invalid,pop_key_mismatch,pop_proof_replayed,proof_nonce_required- to the §10.1.1 table and the OpenRPCUSPProtocolErrorenum, and retitled that table to cover proof verification as well as signatures. Distinguishable codes matter more here than usual: wrong key, replayed proof, and missing proof are three different caller mistakes with three different fixes, and collapsing them into one 401 leaves a platform unable to tell a bug from an attack - Allocated one new JSON-RPC code,
pop_proof_required=-32001, rather than one per failure mode. The USP range-32003…-32009is fully consumed and only-32001and-32002remain, so spending both would have exhausted the range for a single feature. The fine-grained codes ride indata.codeand the Problem Detailstype, which is exactly how the six existingsignature_*codes already work - they appear in the OpenRPC enum and in no §9.4 row at all.-32002is left free - Broadened
signature_missing/signature_invalid/signature_expiredto cover proofs as well as RFC 9421 signatures, and added adata.mechanismdiscriminator. Without it those codes became ambiguous the moment two mechanisms could produce them, leaving a caller unable to tell which credential to correct - Added
data.nonce, carried onproof_nonce_required.USPProtocolError.datawas already an open object requiring onlycodeandcontent, so this is one declared property rather than a structural change. The asymmetry is deliberate - a business MAY require nonces while a platform MUST support being challenged - which lets a business turn nonces on unilaterally without a flag day - Mirrored the codes into
openapi/usp-rest.json's 401 prose and added three worked Problem Details examples, including the cross-key case, so the response shape is discoverable from the binding rather than only from the specification body
15/08/26 at 02:26:18 by Ran Yahalom
- Fixed a latent defect that made the paid-bookings extension inert:
schemas/paid_bookings.jsondeclared$defs/dev.ucp.shopping.checkout- the object contributingbookingto a UCP checkout - but the rootallOfnever referenced it, so the extension was applied to nothing and an instance with a missing or misshapenbookingvalidated silently. This is a pre-existing bug, fixed here rather than deferred to the hygiene commit because the UCP-Native credential carriage is unimplementable without it: adding a property to an object nothing composes would have looked correct and validated nothing - Added
booking_scoped_credentialto that extension object as a sibling ofbooking, settling where the credential rides in UCP-Native paid bookings. Not insidebooking:BookingContextis scheduling data that platforms persist and re-display, so a credential placed there would be written to whatever store the booking is cached in - widening precisely the leak surface thecnfbinding closes - Recorded in §7.4 why this is not a namespace violation, since the obvious objection is that USP must not add members to a UCP-governed object. It is declared inside USP's own registered
dev.usp.services.paid_bookingsextension, by the sameallOfcomposition that already contributesbooking, so it is a declared extension member rather than an invented one and needs no governance rule beyond the one this extension already relies on - Marked the credential response-only in the schema description - a platform MUST NOT send it on a request and a business MUST ignore it if received - because a bidirectional-looking field in a checkout object invites a client to echo back what it was given
15/08/26 at 02:04:53 by Ran Yahalom
- Specified MCP proof carriage in §9.2.2 and wired it into
openrpc/usp-mcp.json: one newproofproperty onMcpAuthorization, the claim set, the canonicalization rule, and the credential returned on the three creating methods. The MCP binding previously could not express a mechanism its own advertisedAuthorizationMechanismset contains, which is the same class of defect this work exists to fix - Put
proofinsideMcpAuthorizationrather than as a sibling_meta.usp.proof. All five_meta.uspwrappers areadditionalProperties: false, so the sibling form would have required a structural edit to every one of them; they already$refMcpAuthorizationand needed only description changes. Easy to miss, and missing it would have made the design non-conformant with its own binding file - Carried the proof in
_meta.usp.authorization.proofon both MCP transports rather than giving MCP-over-HTTP a REST-styleDPoPheader. One client code path, and a business behind an SSE gateway does not need to know its own externally visible URL in order to verify a proof - Gave the MCP proof
typ: usp-pop+jwtrather thandpop+jwt, and boundusp_m/audin place ofhtm/htu. The differingtypmeans a REST proof and an MCP proof cannot be replayed as one another, and a verifier rejects the mismatch before evaluating any claim - Made
audmandatory. Withouthtuto bind the target, and with neitherathnor a credential present at issuance, a proof captured by one business would otherwise replay verbatim at a different business.audis always available to the caller because a conformant business is discovered through its profile URI in the first place - Specified the argument digest over JCS-canonicalized params rather than byte-exactly, because an MCP client does not control its own wire bytes - the SDK serializes
paramsand gateways re-serialize freely. Removed only_meta.usp.authorizationfrom the digest, deliberately leaving_meta.usp.profileand_meta.usp.idempotency_keyinside it: the first gives identity binding something to bind against, the second covers create-replay for free - Rewrote the four privileged wrapper descriptions, which actively forbade what this design requires.
McpUspMetaPrivilegedPlatformstated thatbooking_scoped_credential"does not apply until a booking or waitlist entry exists" without saying that this is the tier at which one is issued, and theauthorizationproperty on all four recommended a retained credential with no mention of the proof itscnfbinding requires - Recorded, in
McpAuthorization.proofitself, why the mandatory-proof rule is stated as policy rather than left to syntax:mechanismis caller-asserted and excluded from the digest, so without the rule an attacker holding a leaked credential could declaremechanism: booking_scoped_credential, omitproof, and present a sender-constrained credential as a bearer token - Added two §9.2.4 conformance items and deliberately did not restate the existing MUSTs on profile binding and mechanism selection, which already cover their ground
15/08/26 at 01:29:11 by Ran Yahalom
- Wired the REST carriage of
platform_key_pop: the proof rides theDPoPrequest header, the credential ridesAuthorization: DPoP <bsc_...>, andbooking_scoped_credentialis now returned on thePOST /bookings,POST /availability/holdsandPOST /waitlistcreation responses. The credential was previously consumable by 17 operations and issued by none - the security scheme depended on a value no response in the document ever returned - Modelled
PlatformKeyPopasapiKeyin theDPoPheader rather than ashttp/DPoP, correcting the entry added when the mechanism was registered. On a resource-creating call there is noAuthorizationheader at all and the proof header is itself the credential, so anhttpscheme would have misdescribed the wire form at exactly the point where the binding is established - Moved
BookingScopedCredentialfromapiKey/Authorizationtohttp/DPoP. This resolves the three-way collision in whichBookingScopedCredential,ApiKeyandOAuth2Bearerall resolved toAuthorization: Bearer, leaving a server unable to tell from the request alone which scheme the caller intended; the pre-existingOAuth2Bearer/ApiKeyoverlap remains and is out of scope. More importantly the scheme change is what stops a business silently accepting a sender-constrained credential as a plain bearer token - Expressed the credential-plus-proof requirement as a single security requirement object naming both schemes, which is OpenAPI's AND semantics and therefore an accurate machine-readable statement of the anti-downgrade rule. Kept the credential-alone alternative, because OpenAPI cannot express "only when
cnfis present" and unbound legacy credentials still exist; the conditional MUST stays in §10.1.6 and is stated in the scheme description so a reader of the binding alone does not conclude the bearer path is sanctioned - Added
PlatformKeyPopas an accepted alternative on all 23 privileged operations (6 platform-tier, 17 scoped), rather than only on the scoped ones. A create call is where the key binding is established, so omitting it there would have left the mechanism advertised but unreachable at issuance - Described the credential on the creation responses as returned beside the created resource and never inside it, and said why: a platform that persists the credential into the booking it re-displays has widened exactly the leak surface the
cnfbinding exists to close
15/08/26 at 00:58:44 by Ran Yahalom
- Specified the
platform_key_popmechanism normatively in §10.1.6: key generation andjktas the platform identifier, in-band binding at issuance, the REST and MCP presentation forms side by side, accepted algorithms, downgrade resistance, the verification order, and replay defence. Until now the section reserved a mechanism name and defined nothing, so two implementers building it would have built two incompatible things - Stated the anti-downgrade MUST for both bindings, which is the single load-bearing rule of the design. Syntax enforces it on neither binding by itself: REST's
Bearer->DPoPscheme change makes a downgrade visible but is not a rule, and MCP has no scheme at all while the declaredmechanismsits inside_meta.usp.authorization, outside the argument digest. Without the rule, an attacker holding a leaked credential could declaremechanism: booking_scoped_credential, omit the proof, and present it as a bearer - the whole mechanism bypassable in one field - Made the verification order normative and explained why the order is load-bearing rather than stylistic: each step returns a different code, so reordering leaks which part of the presentation was wrong. Recorded that at issuance the credential steps and
athare skipped and the thumbprint is recorded rather than compared, which is the one place the two flows genuinely differ - Required replay defence on reads as well as writes. Idempotency-key de-duplication is only a SHOULD and only covers state-modifying operations, so read operations had no replay protection at all - and those are exactly the operations returning buyer personal data
- Added the forward-compatibility carve-out, without which the closed
cnfand credential objects added earlier would contradict §10.1.6's ignore-what-you-do-not-recognize MUST. The two rules point in opposite directions deliberately: ignoring an unknown profile field costs a capability, whereas ignoring an unknown confirmation method downgrades a sender-constrained credential to a bearer token - Chose EdDSA as the algorithm floor rather than ES256, to avoid the fixed-width
r||sversus DER encoding trap that §9.1.4 already has to warn about;ES256remains permitted in addition. Also required rejectingalg: noneand any header JWK carrying a private-key member - Documented the three root-level platform-profile members -
keys,signing_keys,webhook_url- in the §8.2.3 field table. They existed only inschemas/profile.json, and §9.1.4 pointed at §8.2.3 for thekeysarray, a reference that led nowhere. Placed them in a second table described as siblings ofusp, because folding them into the existing table would have assertedusp.keysand contradicted the schema - Stated explicitly that a non-signing platform publishing no
keysis conformant, and quoted both halves of the schema's condition. An implementer reading only the first half would conclude that MCP-over-HTTP forces keys; since a proof rides in-band rather than as RFC 9421 headers, the keyless profile is conformant on both bindings, and that is what lets one shared profile serve every instance of a personal agent - Recorded what the mechanism does not defend against - theft of local key material, or a hostile process on the platform host - rather than leaving the proof-of-possession framing to imply more than it delivers
15/08/26 at 00:21:37 by Ran Yahalom
- Registered the
platform_key_popmechanism identifier across all six artefacts that duplicate the mechanism set by design:schemas/profile.json(AuthorizationMechanismexamples and description, plusaccepted_mechanisms),openapi/usp-rest.jsoncomponents.securitySchemes,openrpc/usp-mcp.jsoncomponents.x-usp-securitySchemes, the §10.1.6 mechanism table,site-docs/security.md, and the per-method boilerplate in the MCP binding. Partial updates are the most likely failure mode here and nothing enforced consistency, so a sweep across all six is part of the acceptance for this work - Corrected the working assumption that the MCP per-method boilerplate was "~30 occurrences of one string". It is four distinct strings totalling 38 occurrences across 19 methods, and the one usually quoted appears only 6 times. A search-and-replace on that single string would have left 32 sites advertising a mechanism set the binding's own security schemes contradict. This entry updates the two strings that enumerate mechanisms (6 method descriptions, 6
_metaparameter descriptions), asserted by exact count before and after; the other two carry scoped-credential semantics and are updated where the proof requirement lands - Registered the mechanism differently in each binding, because the two are not symmetric and treating them as such would have produced an invalid OpenAPI document: OpenRPC has a USP-specific
x-usp-securitySchemeswhose entries are{mechanism, description}, whereas OpenAPI has no such extension and uses standardcomponents.securitySchemes, where the entry must be a real OpenAPI scheme (type: http,scheme: DPoP) carrying the shared identifier inx-usp-mechanism - Retired the sentence "Detailed issuance and validation mechanics are tracked separately (issue #134)" from both places it was duplicated (§10.1.6 and
openapi/usp-rest.json). It became false the moment the credential acquired a schema, and leaving it would have told implementers to wait for a specification that had already landed - Added [RFC 7519], [RFC 7638], [RFC 7800] and [RFC 8785] as normative references with link definitions. The mechanism is described in terms of JWK thumbprints,
cnfsemantics, and JSON canonicalization, none of which the document previously cited; only [RFC 9449] and [RFC 7517] were already present - Recorded in each description that this mechanism composes with rather than replaces the rows around it, since the single most likely misreading is that
platform_key_popis an alternative tobooking_scoped_credentialrather than the thing that makes it sender-constrained
14/08/26 at 23:58:12 by Ran Yahalom
- Added
$defs/ConfirmationKeyand$defs/PopProofJwttoschemas/usp.jsonand$defs/BookingScopedCredentialtoschemas/profile.json.booking_scoped_credentialhas been an advertised mechanism name with no object definition anywhere inschemas/since it was reserved, so every implementer was free to invent an incompatible shape; §10.1.6 said as much, describing itself as reserving only the name - Put the credential in
profile.jsonrather thanbooking.json, against the obvious placement, for a reason the newrefscheck now proves mechanically:booking.json's$idcarries aservices/segment whileusp.json's does not, so a relativecnfreference written frombooking.jsonresolves under$idbase-URI rules tohttps://usp.dev/schemas/services/usp.json, a document that does not exist. It would have validated in any filesystem-based editor and broken in any$id-honouring validator.profile.jsonshares an$idlevel withusp.json, so the reference is correct under both. The placement is also the semantically right one - a credential is an authorization object, besideAuthorizationMechanismandAuthorizationPolicy, not booking domain data - Tightened the
refscheck to catch that class directly. The existing two-strategy comparison could not: its flat fallback, which same-level references legitimately need, silently absorbed the cross-level failure. It now flags any relative$refbetween schema files whose$iddirectory segments differ, and it fires on a probe reference frombooking.jsonwhile passing on the chosen placement - Made
cnfREQUIRED in practice by describing what its absence means rather than by schema alone: a credential withoutcnfis a plain bearer token, so anyone who observes the value in a log, an HTTP trace, or a compromised database can use it.cnfis left optional in the schema so that a business may issue an unbound credential and be visibly non-conformant, rather than being unable to express the legacy shape at all - Required
bsc_as a value prefix and forbade deriving the value from the resource identifier. The prefix keeps the credential distinguishable from anoauth2_bearertoken or anapi_keysharing theAuthorizationheader and greppable when a leak has to be scoped; the derivation ban closes the resource-identifier-as-credential mistake that §10.1.6 opens by forbidding - Documented that
expires_attracks the resource rather than a short session clock, since a booking made three months out still needs a cancel path on day 89 - the failure mode a naive short-lived-token reading would produce - Made both closed objects (
additionalProperties: false) and recorded why in the descriptions: the §10.1.6 forward-compatibility rule that requires consumers to ignore unrecognized members deliberately does not extend to credentials or confirmation keys, because ignoring an unrecognized confirmation method downgrades a sender-constrained credential to a bearer token - Added thin
$refentries in both bindings'components.schemasper CLAUDE.md; no inline object trees. Note the OpenAPI nameBookingScopedCredentialnow exists in bothsecuritySchemesandschemas, which OpenAPI namespaces separately - the security scheme is referenced by 17securityarrays and was deliberately not renamed
14/08/26 at 23:34:05 by Ran Yahalom
- Settled where
platform_key_popis normatively specified, which the surrounding design had left ambiguous in a way that would have made the mechanism inapplicable to half its audience. §10.2.3 already says businesses SHOULD support DPoP for proof-of-possession, but §10.2 is skipped in its entirety by UCP-Native deployments, so a mechanism specified there would not reach the deployments §7.3 explicitly directs to keep reading §10.1.6. The mechanism is therefore specified in §10.1.6, which is mode-agnostic, and §10.2.3 now carries a pointer saying so - Stated that the two are distinct rather than one generalizing the other: §10.2.3's DPoP hardens an already-issued OAuth token, while
platform_key_popis permissionless and involves no token at all. Left unstated, an implementer would reasonably read the new mechanism as a restatement of the old sentence and implement only the OAuth-bound form - Answered the open question of how the credential and proof travel in UCP-Native Mode, by separating two governance models that had been conflated. On USP's own service endpoint USP defines the headers in both modes. On a UCP-governed endpoint USP MUST NOT redefine
Authorization, so the proof rides the additiveDPoPheader and an issued credential is returned inside thedev.usp.services.paid_bookingsextension as a sibling ofbooking- never at the UCP checkout root, and never insidebooking, which platforms persist and re-display and so must never hold a secret - Recorded why that is permitted, since the namespace-governance rule alone does not answer it: that rule governs profile documents, whereas response bodies are governed by UCP's extension-composition model, which is already how
dev.usp.services.paid_bookingscontributesbookingto a checkout. A credential added the same way is a declared extension member rather than an invented one, so no new governance rule is required - Stated the UCP relationship honestly as an extension, not an inheritance: binding a key that is deliberately absent from the platform profile is a key-resolution path UCP does not define, so implementers MUST NOT read this as UCP conformance. Also recorded the converse, that USP's requirement for a fetchable profile on every privileged request is stricter than UCP's consistency-only rule, so the identity-binding work is not a divergence
- Split the
README.mdstandards table so RFC 9449 is no longer listed as Standalone-only, and added RFC 7638 and RFC 7800 alongside it; the previous row would have told readers that proof-of-possession does not apply in UCP-Native Mode
14/08/26 at 23:12:40 by Ran Yahalom
- Added
tools/usp_check.py, the repository's first mechanical validation. Nothing here previously checked that the JSON artefacts parse, thatschemas/*.jsoncompile as JSON Schema, or that cross-file$refs resolve at all - the onlypackage.jsonscript builds the docs site - so schema drift was detectable only by review - Made the
refscheck resolve every$reftwo ways, by$idbase-URI rules and by filesystem path, and fail when they disagree. Every$idunderschemas/declares a directory the flat on-disk layout does not have (services/,platform/), so a cross-level$refsuch asbooking.json->usp.jsonresolves cleanly in a filesystem-based editor and 404s in any$id-honouring validator. Existing refs all happen to stay within one level, which is exactly why the trap is invisible until someone adds the first cross-level one - Added a version-identity assertion across
specification.md,README.md, both bindinginfo.versionfields, and the roadmap's current row, turning what was a manual grep discipline into a build failure. It fires immediately: both bindings carry2026-02-09while the spec is at2026-02-21 - Added an unreferenced-
$defsreport, which found thatschemas/registry.json$defs/RegistrationRequestis referenced by nothing becauseopenapi/usp-rest.jsondeclares thePOST /registry/businessesbody as a large inline object tree - the duplication CLAUDE.md rule 3 forbids, with the two copies already free to drift - Added
tools/known-issues.txtas an explicit debt ledger rather than a suppression flag, so the three pre-existing failures above stay visible and their removal is a reviewable event; deliberately informative$defsare listed separately in the script, because "accepted forever by design" and "not fixed yet" should not look alike - Added
.github/workflows/ci.yml, the repository's first CI, running the three checks and a docs build. Deliberately notmkdocs --strict:site-docslinks to repository files outsidedocs_dirthat resolve on GitHub but not in mkdocs, and failing CI permanently on a design choice would train people to ignore it
14/08/26 at 22:56:14 by Ran Yahalom
- Resolved a contradiction where the schema permitted what the specification body forbids:
schemas/profile.jsonjustified not defaultingprivileged_operations_require_authenticationto true on the grounds that "free/demo/sandbox deployments MAY legitimately run without it", while §10.1.6 states that privileged operations - explicitly including creating a booking - MUST be authenticated. A business could therefore publishfalse, validate cleanly, and believe it was conformant while serving real bookings unauthenticated. The property description now states that the flag declares enforcement posture rather than permission to violate §10.1.6, that a conformant deployment serving real bookings or buyer data MUST set ittrue, and thatfalseis permitted only for explicitly non-production sandbox deployments - Added the matching §10.1.6 paragraph so the rule is normative in the body and not only in a schema description: a deployment publishing
falsedeclares itself out of conformance for privileged operations, and a platform MUST treatfalseas a signal to refuse to transact real bookings or transmit buyer personal data - refuse, not warn and continue. Stated the converse case too (publishingtruewhile accepting unauthenticated privileged requests is equally non-conformant), since the flag is only meaningful if it describes actual behaviour
12/08/26 at 15:33:08 by Ran Yahalom
- Aligned USP publisher rules so signing material MUST appear in top-level
keys(UCP-canonical) with optional identicalsigning_keysduring transition, dual-publish recommended, and verifiers resolvingkeysfirst acrossspecification.md§8.2.1 / §9.1.4 / §10.1.1,schemas/profile.json, site-docs, and OpenAPI examples - Softened former publisher MUST on
signing_keysso USP publishers satisfy UCP main/draft verifiers that requirekeys[], without breaking Standalone readers that still consume the transition alias - Cleared residual AC-S contradictions in the same signing surfaces: request covered components match UCP (
@authority/@path, not@createdas a covered component),createdis an OPTIONAL request signature parameter, anddigest_mismatchis HTTP 400 in both the spec table andopenapi/usp-rest.json
10/08/26 at 18:16:00 by Ran Yahalom
- Added an explicit guard against the pre-move placement of the authorization policy:
ServiceBinding.authorizationis now declared with a never-satisfiable schema inschemas/usp.json, so a binding that publishes the policy as a direct member is rejected instead of passing silently underadditionalProperties. Without the guard a business could publish the old shape, see no validation error, and believe it had advertised an authentication requirement that no conforming platform reads - a fail-open outcome. Stated the corresponding MUST NOT in §8.2.1 and recorded it in §10.1.6 as the single, deliberate exception to that section's ignore-unrecognized-fields rule, so the two rules do not appear to contradict each other - Posted amendment comments on #9 and #157 recording the
config.authorizationpath, the guard, and the tightenedServiceBindingrequired fields, since both issue bodies still instruct implementers to read and publish the policy at the old location
10/08/26 at 18:07:00 by Ran Yahalom
- Moved the UCP-Native
authorizationpolicy from a sibling member of thedev.usp.servicesbinding toconfig.authorizationon that binding. Being inside thedev.usp.*key satisfies UCP namespace governance, but UCP already definesconfigas the slot for entity-specific settings on a service or capability entry, so a sibling member was an invented field where UCP has an idiomatic one; keeping USP's own extension insideconfigalso means the binding stays fully self-describing against the service's published schema. Updatedschemas/usp.json(newconfigobject onServiceBindingholding theAuthorizationPolicy$ref), the §7.2 examples, the §7.3 and §10.1.6 placement rules, the §8.2.1 field tables,schemas/profile.jsondescriptions,openrpc/usp-mcp.json,site-docs/security.md, andsite-docs/deployment-modes/ucp-native.md - Aligned
ServiceBindingfield requirements with the UCP service definition, so a USP binding published inside/.well-known/ucpis conformant as-is:specis now required,schemais required forrest/mcp/embedded, andendpointis required forrest/mcp/a2a(the last two enforced viaif/thenrather than left as prose). Previously the schema required onlyversionandtransportwhile the prose calledspecandschemamerely RECOMMENDED, which meant USP was publishing bindings that strict UCP profile validation rejects. Also added the UCPidfield and documented thatspec/schemaorigins MUST match the namespace authority of the service key - Fixed the free-service-only UCP-Native profile example, which was the concrete instance of the above defect: it published a
dev.usp.servicesREST binding with nospecand noschemaand would have failed UCP validation if copied. Corrected in §7.2 ofspecification.mdand in the mirrored example insite-docs/deployment-modes/ucp-native.md, and updated theServiceBindingtable insite-docs/deployment-modes/standalone.mdto match the tightened rules
10/08/26 at 17:23:09 by Ran Yahalom
- Fixed a conformance defect that would have broken interoperability with UCP verifiers: §9.1.4 required the signature to cover
@target-uriand@created, but UCP requires@method/@authority/@path(plus@query, agent header,idempotency-key,content-digest,content-typewhen present), andcreatedis an RFC 9421 signature parameter, not a covered component. A signer following the old text would have been rejected by any verifier that enforces covered components, since target components absent from the covered set are treated as unsigned. Updated the normative list, the example,site-docs/transport/rest.md, and the OpenAPI/OpenRPC security-scheme descriptions, and added an explicit note that@target-urimay be covered additionally but never instead - Corrected the same
@createdmistake where it had propagated: the §10.1.1 webhook covered-component list, the webhook examples inspecification.mdandsite-docs/transport/mcp.md, the signature error table,openapi/usp-rest.json, and theUSPProtocolErrorenum inopenrpc/usp-mcp.json - Replaced the USP-invented signature-timestamp replay window for requests with UCP's model (replay protection is the signed
Idempotency-Key;createdis OPTIONAL and a business MUST NOT reject a request for lacking it), while keeping the 5-minutecreatedwindow plus event-idde-duplication as a MUST for webhooks, which carry no idempotency key. Previously both directions were conflated into one rule that contradicted UCP - Gave the §10.1.6
authorizationpolicy a defined, namespace-legal home in UCP-Native Mode: it is published on thedev.usp.servicesservice binding inside/.well-known/ucp, not as a top-level member of a UCP profile, because UCP namespace governance requires non-UCP declarations to sit under their own reverse-domain authority. Previously the spec required the policy "in the business profile" whileAuthorizationPolicywas only defined for the Standalone/.well-known/uspdocument, so UCP-Native deployments had nowhere legal to publish it. Added the placement rules to §10.1.6, §7.3, §8.2.1, the §7.2 examples, and anauthorizationproperty onServiceBindinginschemas/usp.jsonthat references the singleAuthorizationPolicydefinition - Made the profile documents forward compatible so that §10.1.6's own rationale (policy as data, so UCP evolution is a schema addition rather than a rewrite) actually holds: relaxed
additionalPropertiesonBusinessProfile,PlatformProfile, andAuthorizationPolicy, and convertedAuthorizationMechanismandSigningKey.kty/crv/algfrom closed enums to documented open vocabularies. Added a normative rule that consumers MUST ignore unrecognized mechanisms, algorithms, and fields rather than reject the document, and MUST NOT treat an unrecognized mechanism as accepted, so ignore-unknown never becomes fail-open - Added the
keysalias alongsidesigning_keysin both profile types, with verifiers resolvingkeysfirst, so USP tracks UCP's migration to a top-level RFC 7517 JWK Set without a flag day for either field name - Aligned the signature error surface with UCP: added
algorithm_unsupported, moveddigest_mismatchfrom 401 to 400 (the message is malformed, not unauthenticated), and rescopedsignature_expiredto signatures the verifier actually evaluates for freshness - Added
WWW-Authenticateguidance on 401 for privileged operations (spec §10.1.6 and an OpenAPI response header), so a mechanism mismatch between a business and an agent is diagnosable rather than a silent failure, matching UCP's own unauthorized-response example - Recorded as a Security Consideration that platform-level authentication answers "which platform is calling," not "may this caller act on this booking," so a business accepting only platform-level mechanisms on get/cancel/reschedule and PII-bearing operations knowingly exposes any identifiable booking to any authenticated platform. Left as SHOULD rather than MUST while the booking-scoped credential format is still open (#134 / #162)
- Added profile-fetch hardening to §8.2.3 (reject special-use IP ranges per RFC 6890, validate the resolved address against DNS rebinding, bound response size and timeouts, keep discovery cost constant for unrecognized platforms, limit force-refresh to once per TTL per origin), because a caller-supplied platform profile URI makes first-contact fetches an unauthenticated-request-triggered outbound request. Mirrors UCP's own fetching rules so UCP-Native businesses inherit rather than reimplement them, and added RFC 6890 to §14.1
- Updated §1.4 to describe RFC 9421 as covering both webhook verification and request signing, since it had described webhooks only
09/08/26 at 18:09:19 by Ran Yahalom
- Aligned
openrpc/usp-mcp.jsonwith the AC-S auth model already inopenapi/usp-rest.json, so transport-agnostic privileged-vs-public access and the five authorization mechanisms are shared rather than REST-only: extracted$defs/AuthorizationMechanisminschemas/profile.json(referenced byAuthorizationPolicy), annotated OpenAPIsecuritySchemeswithx-usp-mechanism, and added matchingcomponents.x-usp-securitySchemesplusMcpAuthorization/McpUspMeta*schemas and per-methodx-usp-access(public/privileged_platform/privileged_scoped) in the MCP binding - Made privileged MCP methods require
_metawith_meta.usp.profile(identity binding equivalent toUSP-Agent) and optional_meta.usp.authorizationfor credentials that must ride inside the tool call (stdio or booking-scoped), while MCP-over-HTTP continues to prefer HTTP-layer Authorization / RFC 9421 Signature / mTLS - Updated
specification.md§9.1.4 MCP note, §9.2.2 request format, and §9.2.4 MCP conformance, plussite-docs/security.md, so both bindings are explicitly subject to §10.1.6 and point at the sharedAuthorizationPolicy/AuthorizationMechanismdefinitions instead of duplicating mechanism enums
09/08/26 at 18:00:52 by Ran Yahalom
- Updated issue #9 so AC-L matches the locked AC-S resolution:
linkusp-climust negotiate auth from the business profileauthorization.accepted_mechanisms(prefer RFC 9421 signatures, then OAuth Bearer / API key / mTLS, and booking-scoped credentials for get/cancel when available), not hardcode Bearer-only; marked AC-S checkboxes complete and left AC-L open for CLI/SKILL implementation
09/08/26 at 17:55:43 by Ran Yahalom
- Implemented the AC-S resolution of issue #9 (Finalize HTTP/REST transport binding authentication): added
specification.md§10.1.6 "Platform Authentication for Privileged Operations" as a new mode-agnostic requirement (public catalog/availability/profile stay optionally anonymous; booking/hold/waitlist/payment-adjacent/PII-bearing/registry-write operations MUST be authenticated by at least one of HTTP Message Signatures, a booking-scoped capability credential, OAuth 2.0 Bearer, an API key, or mTLS), replacing the old blanket "USP endpoints MUST support OAuth 2.0 Bearer tokens" text in §10.2.3 that named a single mandatory mechanism - Motivation: UCP's own HTTP/REST binding treats platform authentication as optional (
SHOULD) because its ecosystem today is dominated by a small, enumerable set of well-known large AI platforms that can be vetted out-of-band; USP's scheduling domain additionally has to support personal, single-user "bring your own agent" deployments (one distinct agent instance per consumer, no realistic pre-onboarding step, no brand-level accountability) where unauthenticated privileged mutations and PII exposure are materially riskier against a materially larger population, so USP hardens this one point rather than inheriting UCP's optional posture for it, while leaving every other UCP-inherited concern unchanged - Made the requirement mechanism-agnostic and business-declared (rather than naming one mandatory mechanism) specifically so it stays compatible if UCP's own posture evolves toward permissionless/scoped-credential patterns, and so it does not force every personal agent instance through a pre-registration bottleneck that does not scale to "bring your own agent" populations
- Added
$defs/AuthorizationPolicytoschemas/profile.json(referenced, not duplicated, fromBusinessProfile.authorization) so a business can declareprivileged_operations_require_authenticationand itsaccepted_mechanisms(http_message_signature,booking_scoped_credential,oauth2_bearer,api_key,mtls) as versioned profile data instead of spec prose - Reserved
booking_scoped_credentialas an accepted mechanism name answering "does this caller hold the credential for this specific booking," independent of platform identity; deferred its issuance/validation mechanics to issue #134 (which feeds the broader plan item V2-X6 / issue #162) rather than designing it here - Updated
openapi/usp-rest.json: addedcomponents.securitySchemes(HttpMessageSignature,BookingScopedCredential,OAuth2Bearer,ApiKey,MutualTLS) and set per-operationsecurity(empty for public catalog/availability/profile/registry-search paths; the four platform-level mechanisms for create-type privileged paths; all five, including the booking/waitlist-scoped credential, for get/update/cancel/reschedule/confirm paths on an existing booking, waitlist entry, hold, feed subscription, or registry registration) - Updated
specification.md§7.3 (UCP-Native inherited-infrastructure table and reading guidance) to clarify that §10.1.6 is an additive USP floor that applies in UCP-Native Mode too, not something UCP-Native inherits automatically; updated §9.1.4 to cross-reference §10.1.6 as the recommended way to satisfy the privileged-operation requirement without a pre-established credential; rewrote §10.2.3 to defer to §10.1.6 for the mechanism-agnostic MUST and keep only Standalone-Mode-specific OAuth/DPoP mechanics - Mirrored the decision in
site-docs/security.md: added a "Platform Authentication for Privileged Operations" subsection under the shared USP Security Requirements (with a rationale callout), reframed the former Standalone-only "Authentication and Authorization" section as "Pre-established Authentication Mechanics", and updated the Security Checklist table so OAuth 2.0 is listed as one available mechanism rather than the sole required/inherited one - Posted an "AC-S resolution" comment on issue #9 documenting the full rationale (BYOA-vs-large-platform mental model, the booking-scoped credential answer to "does this caller hold the token for this booking," the intentional UCP-alignment strategy, and why the declared-policy design minimizes future rework if UCP's posture changes), so the AC-S1/AC-S2 decision trail is preserved on the issue itself
- Scope note: this change covers AC-S (spec + bindings + docs) only, per the user's request; AC-L (
linkusp-clisending the chosen headers/credentials) and server-side enforcement onusp-impl/usp-registry/acp-checkoutremain tracked in issues #118 and #157 respectively and were not touched here
06/08/26 at 20:55:50 by Ran Yahalom
- Resolved issue #40 by adding a first-class buyer service delivery address:
DeliveryAddressinschemas/booking.json, referenced (not duplicated) fromPOST /bookings,PUT /bookings/{booking_id}, and echoed on theBookingobject, so field-service bookings no longer have to smuggle an unparseable address into free-textnotes - Renamed
channel.type: in_persontoat_business_locationand addedat_buyer_location(plus optionalservice_area) inschemas/catalog.json, becausein_personwas defined as "the buyer must attend in person" which is semantically inverted for any service where the provider travels to the buyer; names were chosen against external precedent (Square Appointments'BUSINESS_LOCATION/CUSTOMER_LOCATIONenum, schema.orgserviceLocation/areaServed) rather than invented in isolation, and reuse USP's own Business/Buyer glossary terms - Promoted the Appendix A candidate vertical from
home_serviceto a core vertical namedfield_service, becausehome_servicereads as residential-only even though the same scheduling shape (buyer names a delivery address, provider travels there) applies to offices and other buyer-specified premises;field_servicematches existing field-service-management industry terminology (Skedulo, Salesforce, ServiceTitan) - Updated all affected bindings and mirrors for consistency:
openapi/usp-rest.jsonandopenrpc/usp-mcp.json(thin$refs only, no duplicated shapes per repo convention),specification.md(§1.3.1, Appendix A, §3.3 channel types and schema.org mapping table, §5.2 Booking schema, §5.3.1/§5.3.3 booking operations and examples), site-docs mirrors (specification/index.md,specification/service-catalog.md,specification/discovery-registry.md,deployment-modes/ucp-native.md,roadmap.md), and playground fixtures (playground/scenarios/services.json,site-docs/playground/scenarios/services.json) - Wrote design doc
docs/superpowers/specs/2026-08-06-service-delivery-address-and-channel-naming-design.mdand implementation plandocs/superpowers/plans/2026-08-06-service-delivery-address-and-channel-naming.mddocumenting the naming research and file impact - Reassigned GitHub issue #40 to
@maoryeh(owner of the USP registry and Wix business USP adapter tracks) with a comment detailing the breaking enum rename and new fields, since the Vespa registry indexing andusp-implbusiness adapter both need matching updates that are out of scope for this spec-only change
06/08/26 at 19:46:43 by Ran Yahalom
- Resolved issue #59 by adding normative registry filter-matching semantics (§6.3.1) so federated registries share the same yes/no inclusion contract: four
matchmodes (overlapdefault,contained,contains,equals) onprice_range/duration_range, within-currency matching with currency required when ambiguous, free-as-0, undetermined duration exclusion, geo km + virtual exclusion, and OR-within-field for multi-value filters - Extended
schemas/registry.jsonwithRangeMatchModeand agent-facing worked examples in filter$defs, retargeted OpenAPI search request bodies to thin$refs ofBusinessSearchRequest/ServiceSearchRequestto avoid drifting inline duplicates, and mirrored the rules in site-docs plus the registry design plan
06/08/26 at 19:06:07 by Ran Yahalom
- Removed the singular
categoryfield from the catalogServiceschema because the dual-field precedence rule in issue #54 caused implementer confusion about which representation was authoritative - Replaced the thin
{value, taxonomy}categories entries with an enrichedServiceCategory$def (taxonomy, optionalid/name/parent_id/value/primary) so onecategories[]array covers merchant hierarchy, display/localization, and multi-taxonomy labeling (e.g. merchant path plus Google Business Profile) - Documented normative primary selection, localization (
localized.category_nameoverrides primaryname), catalog filter match rules (primaryid, MAY match anyid), and registry projection pick order for the flatServiceSearchResult.categorystring so producers and registries share one rule - Updated
specification.md, site-docs (service catalog, discovery registry), OpenAPI/OpenRPC filter descriptions, playground fixtures (including a multi-taxonomy salon haircut scenario), and plan notes (V2_PRODUCTION_PLAN.md,usp-registry-design-plan.md) to match the single-field model without duplicating schema bodies into bindings
06/08/26 at 18:38:43 by Ran Yahalom
- Clarified overloaded "discovery" terminology in
specification.md§1.2 (and mirrored site-docs) by adding normative definitions for Catalog Discovery, Profile Discovery, and Platform Onboarding, plus a Mermaid lifecycle diagram, so implementors no longer infer meaning only from section context (issue #42) - Stated explicitly in §6 / discovery-registry docs that registry registration is a directory listing, not platform-business onboarding or credential exchange, to keep registry search SLAs and vault/DCR flows distinct (issue #42)
- Qualified ambiguous
checkout_systemsprose and schema description to reference profile discovery or platform onboarding with a cross-link to §1.2, and scoped §9.1.3 / REST Discovery to profile discovery only (issue #42) - Relabeled end-to-end sequence-diagram notes from generic "Service Discovery" to "Catalog & Availability/Booking" (and related platform/role wording) so diagram labels match the three-phase terminology without renaming
dev.usp.discovery.registryor RFC 8414 metadata discovery (issue #42)
05/08/26 at 20:43:08 by Ran Yahalom
- Created all 35 plan-local V2-* GitHub issues (#157-#191) in
wix-private/universal-scheduling-protocol-specfromplans/V2_PRODUCTION_PLAN.md§4 so production readiness work is tracked with full ACs, §1a clarifications, assignees, andv2labels - Applied §7 labelling on existing open issues (
v2,v>2,requires-approvaladditive with existingv1/v>1) and posted §1a/§3 clarification comments on key judgement inclusions and exclusions so implementers see scoped-down authz and deferral rationale on the issues themselves - Updated
plans/V2_PRODUCTION_PLAN.mdstatus to approved/issues-created and added Appendix A (V2-* → GitHub # mapping) so the plan is the durable index after issue creation
05/08/26 at 20:04:20 by Ran Yahalom
- Added per-track GitHub assignees to
plans/V2_PRODUCTION_PLAN.md§2 (Components and tracks) so newly created v2 issues are assigned consistently:yahalomranowns A, C, and S;maoryehowns B, D, E, and F
05/08/26 at 18:51:05 by Ran Yahalom
- Added §1a "Identity, authentication, and authorization clarifications" to
plans/V2_PRODUCTION_PLAN.mdso the plan records the Link-token piggyback verdict (not viable), AS-backed definition, why unauthenticated privileged UCP/USP APIs are dangerous vs public catalog/availability, that email match is CRM-only (not identity linking / not V2-X1), that booking get/cancel/PII authorization is a launch requirement with multiple mechanisms, that UCP identity linking remains optional, and thatspecification.md§10.2.4 now requires PKCE S256 plus RFC 9207iss - Added plan-local V2-X6 (Authorize booking get/cancel and any response carrying buyer PII), tightened V2-X1 to privileged ops plus platform attribution (not browse-identity), elevated #134 into the launch-blocking authz story, and refreshed #9 / #102 / #118 / #119 / launch gates / schedule / open decisions / labelling so identity linking (#119) stays deferred while booking authorization does not
05/08/26 at 15:31:04 by Ran Yahalom
- Added PKCE requirements to
specification.md§10.2.4 Identity Linking (new "Authorization Code Protection" paragraph pluscode_challenge/code_verifierin linking flow steps 1 and 3), because USP's identity linking omitted PKCE entirely while UCPdev.ucp.common.identity_linkingmakes RFC 7636 withS256a MUST on both the platform and the business side, leaving USP-only deployments exposed to authorization code interception - Added an "Issuer Identification" paragraph to §10.2.4 requiring businesses to return the RFC 9207
issresponse parameter and platforms to validate it against the discovered issuer, for parity with the UCP Mix-Up Attack defense that the existing RFC 8414 exact issuer comparison alone does not provide - Added normative reference entries for RFC 7617, RFC 7636, RFC 8414, and RFC 9207 to §14.1, fixing the defect where §10.2.4 cited RFC 8414 and RFC 7617 without listing them in §14 and covering the two newly cited RFCs
- Added the corresponding link definitions (including section-anchored
[RFC 8414 §3.3]and[RFC 6749 §10.12], which were previously cited but undefined) to both link-definition blocks at the end ofspecification.md, so the citations render as links instead of literal bracketed text
05/08/26 at 10:12:47 by Ran Yahalom
- Added
plans/V2_PRODUCTION_PLAN.md, a 2-week plan to take the existing UCP-Native end-to-end demo to a production MVP, because the v1 plan only covered the demo and there was no single document stating what is strictly required before real buyers and real money are involved - Classified all 55 open GitHub issues into v2 (25) and v>2 (30) with a per-issue production-implication justification, so that scope decisions are traceable rather than re-argued, and recorded the mandated segment constraints (Wix businesses with a connected Stripe account; buyers with a Stripe Link wallet; Base44 Superagent or any harness with the Link USP SKILL)
- Derived 34 new mandatory issues (
V2-*) from reading the USP and UCP normative requirements against all four codebases (linkusp-cli,usp-registry,usp-impl,acp-checkout), because the largest production gaps had no issue at all: no inbound authentication on any USP/UCP surface, no idempotency oncomplete_checkoutor on agent retries, no compensation when a charge succeeds but the booking does not, no registry Update/Delete or Stripe-eligibility admission gate, and zero custom metrics in any component - Documented the launch-blocking subset and the recommendation to cut merchant population rather than security or money-correctness work if the schedule slips, since 59 issues across 6 tracks in 10 days does not fit without a named tail
04/08/26 at 20:34:03 by Ran Yahalom
- Updated USP-open-issues-status canvas note for #127 to record that acceptance criteria are now explicit (11 checkboxes) and that primary implementation remains yahalomran/linkusp-cli while the Link-hosted calendar.link.com path is still backlog
04/08/26 at 16:36:30 by Ran Yahalom
- Added GitHub issue #156 (Migrate protocol namespace authority from usp.dev to usp.live) as STILL_OPEN Spec proposals in USP-open-issues-status so the inventory reflects the new open namespace-migration work
- Placed #156 in a new DISTINCT "Namespace authority migration" cluster in USP-issue-overlap (not website SEO or registry design) and bumped live open-count KPIs from 56 to 57 after verifying search is:issue is:open
04/08/26 at 16:23:38 by Ran Yahalom
- Marked GitHub issue #131 (USP onboarding extensions) CLOSED in USP-open-issues-status and USP-issue-overlap canvases after confirming state=closed and state_reason=not_planned, so canvas inventory matches the user's closure
- Decremented live open-issue KPIs from 57 to 56 (verified via user-wix-github search is:issue is:open) and removed #131 from open LinkUSP cluster ranges while refreshing closed-inventory counts and backlog themes
04/08/26 at 08:30:54 by Ran Yahalom
- Fully refreshed USP-open-issues-status and USP-issue-overlap canvases against live GitHub (57 open issues) so inventories, KPIs, consolidations (#56→#58, #50→#47, #14→#9), and #155 STILL_OPEN match current reality after recent closures
- Confirmed PR #152 closed without merge and emptied close-candidates while keeping remaining epic recommendations as pending (not marked done)
04/08/26 at 08:21:13 by Ran Yahalom
- Closed GitHub issues #56, #50, and #14 in wix-private/universal-scheduling-protocol-spec as high-confidence consolidations into canonical #58, #47, and #9 to remove duplicate backlog without losing acceptance criteria
- Posted fold-in comments on #58 (signing_key ownership-proof sub-question), #47 (poll 200+error / empty-query / stuck PAYMENT_PENDING ACs), and #9 (keep vs remove Authorization header) so remaining work stays on the canonical issues
- Updated USP-issue-overlap and USP-open-issues-status canvases to mark those consolidations DONE and the three issues CLOSED for reviewer visibility
04/08/26 at 08:02:28 by Ran Yahalom
- Added a focused Cursor Canvas for USP open-issue overlap analysis so reviewers can prioritize redundant closes, merge groups, and epic structures across all currently open issues without modifying GitHub
- Documented high-confidence consolidations (#56→#58, #50→#47, #14→#9) plus epic recommendations for webhook E2E, LinkUSP production, and registry clusters to reduce backlog noise while preserving owner/repo boundaries
03/08/26 at 20:41:07 by Ran Yahalom
- Updated website domain references from
usp.devtousp.liveinmkdocs.yml,llms.txt,llms-full.txt,robots.txt,humans.txt, and social-card assets so canonical/SEO/LLM URLs match the live site deployment - Added missing
faviconinmkdocs.ymlso browser tabs show the USP logo instead of the default MkDocs icon - Fixed MkDocs-strict broken internal anchors that used four dashes (
----) instead of the collapsed single-dash slugs in availability, booking, and discovery-registry docs - Left protocol namespace URLs (
https://usp.dev/schemas/..., etc.) unchanged because those are spec identifiers, not website links - Skipped the PR #152 responsive CSS chunk because later mobile styles on this branch already cover that need
03/08/26 at 20:22:55 by Ran Yahalom
- Added an interactive Cursor Canvas for the USP open-issues status analysis so reviewers can scan headline KPIs, prioritize evidence-backed close candidates, compare backlog themes, and filter or sort the full supplied issue inventory
- Confirmed the detailed inventory matches the supplied headline count and documented evidence limitations so the analysis remains transparent about its verification scope
17/07/26 at 21:17:51 by Ran Yahalom
- Fixed Standalone carousel sub-tabs (Catalog / Availability / Booking) clipping paragraph and code snippet text on the left on mobile by constraining
.sub-tab-contentwidth, stacking.sub-tab-panevertically withalign-items: stretch, and removing rigidmin-widthon pane children so code blocks stay within the viewport - Replaced
(width <= Npx)media query syntax with(max-width: Npx)for broader mobile browser support and aligned carousel pane alignment fromcentertostretchon narrow screens to prevent horizontally centered overflow from being clipped
- Improved mobile layout for the MkDocs site by adding overflow clipping, responsive padding, and stacked layouts for the landing page announcement banner, feature cards, promo sections, and carousel tabs in
extra.css, so narrow viewports (320px-768px) no longer trigger horizontal scroll from negative margins or fixedmin-widthvalues - Added responsive table and image rules for documentation pages so wide tables and figures scroll or scale within the content column on small screens
- Enhanced playground mobile styles in
playground.csswith stacked header toggles, 44px touch targets, wrapping transport buttons, two-column step pills, and full-width step footers so the interactive demo remains usable on phones
15/07/26 at 13:07:36 by Ran Yahalom
- Fixed the UCP-Native "See it in action" checkout code panel being clipped on the homepage by removing the rigid
min-widthon.pane-visuals, allowing flex children to shrink withmin-width: 0, and adding container queries so the pane and code blocks stack when the content column (including beside the docs sidebar) is too narrow for side-by-side layout
13/07/26 at 23:39:10 by Ran Yahalom
- Fixed missing right margin on playground screens by adding symmetric horizontal padding and a centered max-width on
.pg-playground, settingmin-width: 0on split/grid panes to prevent overflow, and consolidating responsive padding so nested sections no longer double up horizontal inset
13/07/26 at 23:36:55 by Ran Yahalom
- Made UCP-Native the default deployment mode in the homepage "See it in action" carousel by listing it first in the tab bar and marking its pane active on load, so visitors see the primary integration path before Standalone
13/07/26 at 23:35:36 by Ran Yahalom
- Removed the homepage "Endorsed across the ecosystem" partner marquee from
home.html, deleted all partner-carousel/chip CSS fromextra.css, and dropped unused industry-tab autoplay logic fromextra.js, so the site no longer displays placeholder partner, sponsor, or endorser affiliations
13/07/26 at 23:06:49 by Ran Yahalom
- Changed
repo_nameinmkdocs.ymlto "USP on GitHub" so the header source link matches the UCP site label instead of showing a truncated repository slug
13/07/26 at 22:34:17 by Ran Yahalom
- Removed the homepage "Co-developed by industry leaders" partner tabs section from
home.htmland dropped the unused#industry-tabsCSS rules fromextra.css, because that placeholder content is not ready to publish yet
13/07/26 at 22:31:32 by Ran Yahalom
- Moved Overview and Specification navigation into the left sidebar only (matching UCP) by removing
navigation.tabsandnavigation.tabs.stickyfrommkdocs.yml, and added defensive CSS inextra.cssto hide the header tab bar and keep top-level nav items visible in the primary panel on all viewports
13/07/26 at 22:29:57 by Ran Yahalom
- Reverted the site from green-tinted page backgrounds to white and neutral gray surfaces (
#fff,#f8f9fa,#f1f3f4) inextra.css, restored teal accent colors (#0d9488) for links, badges, and active tabs, and added a subtle hero radial glow matching the earlier site - Aligned playground panel and code backgrounds in
playground.cssto the same neutral palette and teal primary tokens
13/07/26 at 22:19:08 by Ran Yahalom
- Fixed homepage Catalog / Availability / Booking sub-tabs (and Standalone / UCP-Native main tabs) not switching by aligning
openTabandopenSubTabinextra.jswith theonclick+ element-id markup inhome.html, which toggles.activeon.tab-paneand.sub-tab-panesiblings
13/07/26 at 22:10:35 by Ran Yahalom
- Fixed playground response panes showing corrupted numeric placeholder output instead of real scenario JSON by reusing
highlightJsonfromcode-editor.jsinplayground-controller.js, which uses non-numeric placeholder tokens that survive the number-highlighting pass
13/07/26 at 22:04:57 by Ran Yahalom
- Swapped the site surface palette to a green-tinted background scale (
--usp-bg-0through--usp-bg-4) inextra.css, wired header, promo cards, sections, code blocks, partner carousel, and footer to those tokens, and kept normal body/landing text black via--md-typeset-colorand.landing-page { color: #000 } - Aligned playground panel/code backgrounds in
playground.cssto the same greenish elevated surfaces so the demo page matches the docs chrome
- Fixed playground bugs from verification: dynamic request pane headers on all steps, GET query strings in REST formatting, capability negotiation intersection with holds stripped on partial match, discovery refresh on scenario change, and accurate error labels (429 hold limit, 402 payment failed)
- Removed misleading schema-validation claim from playground intro; added
GET /servicesMCP mapping and carousel mode/sub-panel opacity grid CSS for homepage tabs
13/07/26 at 20:06:42 by Ran Yahalom
- Completed full ucp.dev homepage parity in
overrides/home.html: banner icon, hero-wrapper without in-hero CTAs, Learn/Implement promo cards, co-developed industry tabs, flexibility principles, deployment-mode action carousel, two-column deployment promo, lifecycle ecosystem roles, endorsed partner marquee, and Get started today (removed stats, verticals, how-it-works, transport cards, and custom footer) - Moved tab logic to
site-docs/javascripts/extra.jsas globalopenTab/openSubTabwith industry-tab 3s autoplay; kept announce-banner dismiss and removed the legacyusp-tabsdata-tab handler - Ported UCP landing CSS into
site-docs/stylesheets/extra.css(partner-carousel/chips, pane layout, opacity-grid carousel, lifecycle/two-column-promo blocks, get-started step chrome fix, 960px hero breakpoint) and added slate dark-mode palette tomkdocs.yml
13/07/26 at 20:04:37 by Ran Yahalom
- Restructured homepage "See It in Action" to match ucp.dev: deployment-mode tabs (Standalone / UCP-Native), sub-tabs (Catalog / Availability / Booking), pane-text + pane-visuals layout, opacity/visibility grid panels, and scoped
openTab()/openSubTab()handlers so panel height stays stable with fade-in transitions - Replaced partners placeholder with UCP-style industry vertical tabs (Appointments / Group / Reservations / Rentals) using text chips, plus an infinite-scroll ecosystem marquee with scheduling-relevant names; industry tabs autoplay every 3s and pause on hover or click
- Fixed homepage CTA parity: hero GitHub opens in a new tab; Get Involved cards use
<div>wrappers with title-only links; Playground and Contribute open in new tabs - Restored primary docs sidebar on the landing page (matching ucp.dev), added carousel responsive stacking at 1200px and 960px, and aligned hero stack breakpoint to 960px
13/07/26 at 17:30:57 by Ran Yahalom
- Wired the playground transport toggle to
transport-formatter.jsvia ES moduleplayground-controller.js, so REST/MCP/A2A/ESP switches re-render the request pane using the same formatting path as the fullplayground.jsengine (matching UCP's integrated playground script pattern) - Load playground controller as
type="module"inoverrides/playground.htmland cache per-step scenario state so transport and mode changes refresh requests without re-fetching - Added
/.well-known/ucptool mappings intransport-formatter.jsfor UCP-Native mode discovery
13/07/26 at 17:10:15 by Ran Yahalom
- Fixed broken cross-doc link in
site-docs/deployment-modes/ucp-native.md(pointed at repo-rootspecification.mdoutsidesite-docs) to the on-page#paid-bookings-extension-schemaanchor somkdocs build --strictpasses after the UCP parity site work
13/07/26 at 17:09:20 by Ran Yahalom
- Hid the primary docs sidebar on the homepage and playground so landing and demo pages use full-width layout like ucp.dev, instead of squeezing content beside the nav column
- Swapped the get-started CTA middle card to "Try the Playground" (matching UCP's Experiment card) so the bottom-of-page funnel highlights the interactive demo
13/07/26 at 17:08:44 by Ran Yahalom
- Aligned USP docs site global chrome with ucp.dev: white Material header, Google Sans/Roboto Mono fonts, indigo accent palette (removed teal custom theme and dark-mode toggle), plus
navigation.tracking,content.code.select,content.tooltips, and cookie consentscope: / - Ported UCP landing-page patterns into
extra.cssandhome.html: pill buttons, promo cards, light action-carousel code tabs with fade-in, vertical features list, light get-started CTA, announcement banner, and footer wrapper - Upgraded playground UX: request/response split panes, functional mode/transport toggles, step fade animation, auto-run on discovery/negotiation enter, side-by-side negotiation capability grid, and "About this demo" callout; aligned
playground.csstokens to UCP indigo/ink/surface colors - Fixed broken social/OG image references to use existing
social-card.svgandusp-logo.svginstead of missing PNG assets
13/07/26 at 17:08:42 by Ran Yahalom
- Realigned the USP docs site visual system with ucp.dev: white Material header, Google Sans typography, indigo accent palette, pill CTAs, light carousel tabs, and vertical principles layout so the sibling protocol sites read as one ecosystem
- Refreshed homepage markup (
overrides/home.html) with announcement banner, Learn/Implement promo cards, light "See It in Action" section, get-started CTA, and custom footer wrapper matching UCP landing-page patterns - Upgraded playground to UCP-style split request/response panes, negotiation capability grid, step fade transitions, functional mode toggle (USP vs UCP profile paths), and "About this demo" callout; rewrote
playground-controller.jsto match the new panel IDs - Updated
mkdocs.yml(Google Sans, white/indigo palette,navigation.tracking, consentscope: /) and fixed broken social/OG image references inoverrides/main.htmlandoverrides/playground.html
13/07/26 at 16:03:04 by Ran Yahalom
- Added
package.jsonwithpython3 -m mkdocs buildso Vercel treats the project as a static MkDocs site instead of a Python serverless app (Vercel CLI 55+ errors on missing Python entrypoints when onlyrequirements.txtis present) - Added
vercel.jsonwithoutputDirectory: site,/specrewrites,/githubredirect, and cache/security headers aligned withrender.yamlso Vercel deployment matches the existing Render static-site behavior
13/07/26 at 14:52:16 by Ran Yahalom
- Added optional
availability_hinttoServiceSearchResultinschemas/registry.json(by$refto catalogAvailabilityHint), so registry service search can pass through the catalog's approximate availability signal and agents can reason about near-term availability without an extra catalog fetch per hit - Updated
specification.md§6.3 andsite-docs/specification/discovery-registry.mdwith response examples and normative guidance: registries SHOULD pass through the hint when present at index time; platforms MUST NOT treat it as authoritative or as a hard availability filter - Aligned
plans/usp-registry-design-plan.md§1.4, §1.10, and §2.3 with the wire-model change (replacing the prior index-only, not-returned decision from PR #57 review)
03/07/26 at 13:08:53 by Ran Yahalom
- Refined
docs/dtc_charter_nomination.mdto increase GC approval odds: removed leftover assistant-conversation text from the submission body (e.g. "If you want, I can save this as a markdown file..."), which would have been embarrassing if filed as-is, and clearly fenced the internal submission notes behind a delete-before-filing marker - Replaced the spec link pointing to the inaccessible private repo (
wix-private/universal-scheduling-protocol-spec) with the publickobym707/universal-scheduling-protocolremote, since GC reviewers cannot evaluate evidence they cannot open - Added a "Domain Scope" subsection delimiting the four core verticals against the adjacent Lodging (#543) and Food Ordering (#518) DTCs, to preempt GC scope-overlap objections
- Reframed the "Reference implementation" paragraph as a "starting-point contribution" with explicit DTC authority over final namespaces and schemas, to counter the perception of a pre-baked single-vendor (Wix/USP) protocol being rubber-stamped rather than chartered
- Filled the Platforms (Google, Stripe Link, Microsoft Copilot) and Businesses (Wix, Square, Mindbody+ClassPass, Fresha) placeholders with ranked candidates marked "to be confirmed", plus a rationale section with alternates, because the charter requires 3+ committed organizations before filing
13/07/26 at 14:52:16 by Ran Yahalom
- Added optional
availability_hinttoServiceSearchResultinschemas/registry.json(by$refto catalogAvailabilityHint), so registry service search can pass through the catalog's approximate availability signal and agents can reason about near-term availability without an extra catalog fetch per hit - Updated
specification.md§6.3 andsite-docs/specification/discovery-registry.mdwith response examples and normative guidance: registries SHOULD pass through the hint when present at index time; platforms MUST NOT treat it as authoritative or as a hard availability filter - Aligned
plans/usp-registry-design-plan.md§1.4, §1.10, and §2.3 with the wire-model change (replacing the prior index-only, not-returned decision from PR #57 review)
03/07/26 at 13:08:53 by Ran Yahalom
- Refined
docs/dtc_charter_nomination.mdto increase GC approval odds: removed leftover assistant-conversation text from the submission body (e.g. "If you want, I can save this as a markdown file..."), which would have been embarrassing if filed as-is, and clearly fenced the internal submission notes behind a delete-before-filing marker - Replaced the spec link pointing to the inaccessible private repo (
wix-private/universal-scheduling-protocol-spec) with the publickobym707/universal-scheduling-protocolremote, since GC reviewers cannot evaluate evidence they cannot open - Added a "Domain Scope" subsection delimiting the four core verticals against the adjacent Lodging (#543) and Food Ordering (#518) DTCs, to preempt GC scope-overlap objections
- Reframed the "Reference implementation" paragraph as a "starting-point contribution" with explicit DTC authority over final namespaces and schemas, to counter the perception of a pre-baked single-vendor (Wix/USP) protocol being rubber-stamped rather than chartered
- Filled the Platforms (Google, Stripe Link, Microsoft Copilot) and Businesses (Wix, Square, Mindbody+ClassPass, Fresha) placeholders with ranked candidates marked "to be confirmed", plus a rationale section with alternates, because the charter requires 3+ committed organizations before filing
01/07/26 at 16:07:29 by Ran Yahalom
- Expanded
plans/USP+UCP_implementation_plan.md#89 section with full detail from issue comment #4761877725: checkoutpayment_handlersmust expose Stripe SPT prerequisites (network_id), server-side HTTP 402 /mpp decoderesolution during checkout creation, checkout-over-profile authority, acceptance criteria, and cross-links to #64 and #99 - so the implementation plan matches the GitHub issue guidance for UCP-native SPT acquisition - Updated #64 and demo-flow step 15 in the same plan to state the agent reads
network_idfrom checkoutpayment_handlers(not merchant HTTP probing) when required forshared_payment_tokenspend requests - Added normative intent note under #99 that PSP acquisition inputs such as
network_idbelong only on UCP checkoutpayment_handlers, not USP-only extension fields
23/06/26 at 20:12:36 by Ran Yahalom
- Moved all
signing_keys-related work out of demo scope: created GitHub issue #116 "usp-impl: RFC 9421 outbound webhook signing + signing_keys in merchant profile" (v>1, track-d, @maoryeh) as the single post-demo home for both Wix publishing signing_keys and signing outbound booking.confirmed webhooks - Updated #91 (usp-impl booking.confirmed webhook) to send unsigned webhooks for demo and reference #116 for post-demo signing, removing the RFC 9421 criterion that was in scope
- Updated #70 (Demo merchant readiness prerequisite) to remove
signing_keyspresence from the demo checklist description, with an explicit note that it is deferred to #116 - Updated #102 (UCP conformance gaps rollup) to add a new tracked gap row and prose section for Wix RFC 9421 outbound signing (#116), and added #116 to the dedicated post-demo implementation issues table alongside #112, #114, #115
- Updated
plans/USP+UCP_implementation_plan.mdto reflect the same scope reduction: step 21 description, demo success criteria, #70 readiness checklist, #92 webhook receiver step 3, #91 signing step, and the out-of-scope section now all explicitly state the demo webhook is unsigned and point to #116 / #115 for post-demo hardening
23/06/26 at 17:45:39 by Ran Yahalom
- Created GitHub issue #114 "Link: publish hosted per-agent platform profile (LINK_UCP_PLATFORM_PROFILE_URL)" (labels: v>1, track-a; assigned: yahalomran) with per-agent profile architecture (relay / tunnel / deployed), HTTPS hosting constraints, and
booking_webhook.pydurability requirements - motivated by #102 part (a) Link side lacking a dedicated actionable issue - Created GitHub issue #115 "Link: RFC 9421 webhook signature verification (booking.confirmed inbound)" (labels: v>1, track-a; assigned: yahalomran) to replace the
LINKUSP_WEBHOOK_VERIFY=1header-presence stub with full §10.1.1 verification - motivated by #102 rollup bullet having no dedicated Link implementation issue - Updated GitHub issue #102 with cross-refs to #114 and #115 in summary table, subsections, and a new "Dedicated post-demo implementation issues" table linking #114, #115, and #112
- Updated GitHub issue #112 to reference #114 (Link profile prerequisite) and #115 (inbound verification) in the production path steps and references
22/06/26 at 13:55:56 by Ran Yahalom
- Expanded GitHub issue #112 background with the full end-to-end "zero registration" production path (5 steps, §8.3 and §9.2.3 normative citations,
profile_unreachable/profile_malformederror types,FinalizeBookingOnPaymenttrigger, signing-key publication detail, and Step 5 Link-side verification consequences) - motivated by the earlier description being accurate but too shallow to serve as a complete spec reference for the implementer - Updated GitHub issue #112 acceptance criteria to replace the silent-fallback criterion with an explicit requirement that fetch failures MUST surface as protocol errors, and added a note that
USP_DEMO_PLATFORM_WEBHOOK_URLmay only remain as a clearly-labelled non-conformant dev override - Expanded GitHub issue #102 "Production webhook URL derivation" subsection with the §9.2.3 normative quote, the "zero registration" framing, and the split between the already-structurally-complete Link side and the Wix-side
profile_unreachable/profile_malformedobligation - also addedevent_iddeduplication confirmation requirement to the RFC 9421 webhook verification bullet
22/06/26 at 13:45:38 by Ran Yahalom
- Created GitHub issue #112 "usp-impl: derive webhook_url from platform profile (UCP-Agent header)" (labels: v>1, webhooks, track-d, usp-impl; assigned: maoryeh) to track the untracked Wix production path where the callback URL is derived from the UCP-Agent header rather than the out-of-band USP_DEMO_PLATFORM_WEBHOOK_URL env var - motivated by #91 step 4 naming this path without a dedicated issue or acceptance criteria
- Updated GitHub issue #102 "UCP conformance gaps" to add two new subsections in "Additional gaps": (a) "Production webhook URL derivation" covering the Link profile publication and Wix UCP-Agent fetch approach with cross-ref to #112; (b) "Full RFC 9421 webhook signature verification" covering replacement of the LINKUSP_WEBHOOK_VERIFY=1 header-presence stub - both gaps were previously untracked in any issue
- Added comment to GitHub issue #91 tagging @maoryeh and cross-referencing the new #112 issue as the dedicated follow-on for the production webhook URL derivation path named in #91 step 4
22/06/26 at 13:29:55 by Ran Yahalom
- Created GitHub issue #111 "Consider per-capability webhook_url in USP to align with UCP's registration model" to track the design discussion around replacing USP's top-level
webhook_urlwith per-capabilityconfig.webhook_urlentries - motivated by the inconsistency between USP's current model and UCP's capability-scoped webhook registration, which creates a structural hybrid in UCP-Native mode profiles
24/06/26 at 10:43:20 by Ran Yahalom
- Applied GitHub issue updates via wix-github MCP for the step 21 scope cut: #65 body + scope comment (demo ends at sync
complete_checkout, no webhook assertion), #70 (removedUSP_DEMO_PLATFORM_WEBHOOK_URLfrom demo checklist), #91 and #92 relabeledv>1with post-demo acceptance criteria; reopened #92 as open post-demo work
24/06/26 at 08:53:27 by Ran Yahalom
- Moved plan step 21 (
booking.confirmedwebhook E2E) out of demo scope inplans/USP+UCP_implementation_plan.md: demo now ends at synchronouscomplete_checkout(step 20) withstatus: completed,order_id, andbooking.booking_status: confirmed; removed G-12 from the in-scope gap matrix; updated sequence diagram, success criteria, Definition of Done, #65/#70/#91/#92 task sections, sprint calendar/critical path, and added a dedicated "Post-demo: booking.confirmed webhook E2E" out-of-scope section linking #91, #92, #112, #114, #115, #116 - Added GitHub issue update drafts under
.github/issue-drafts/for #65, #70, #91 (v>1), and #92 (v>1) reflecting the same scope cut; wix-github MCP returned 401 on issue update (credentials unavailable in this session), so issues need a manual apply or re-run after auth is restored
23/06/26 at 20:12:36 by Ran Yahalom
- Moved all
signing_keys-related work out of demo scope: created GitHub issue #116 "usp-impl: RFC 9421 outbound webhook signing + signing_keys in merchant profile" (v>1, track-d, @maoryeh) as the single post-demo home for both Wix publishing signing_keys and signing outbound booking.confirmed webhooks - Updated #91 (usp-impl booking.confirmed webhook) to send unsigned webhooks for demo and reference #116 for post-demo signing, removing the RFC 9421 criterion that was in scope
- Updated #70 (Demo merchant readiness prerequisite) to remove
signing_keyspresence from the demo checklist description, with an explicit note that it is deferred to #116 - Updated #102 (UCP conformance gaps rollup) to add a new tracked gap row and prose section for Wix RFC 9421 outbound signing (#116), and added #116 to the dedicated post-demo implementation issues table alongside #112, #114, #115
- Updated
plans/USP+UCP_implementation_plan.mdto reflect the same scope reduction: step 21 description, demo success criteria, #70 readiness checklist, #92 webhook receiver step 3, #91 signing step, and the out-of-scope section now all explicitly state the demo webhook is unsigned and point to #116 / #115 for post-demo hardening
23/06/26 at 17:45:39 by Ran Yahalom
- Created GitHub issue #114 "Link: publish hosted per-agent platform profile (LINK_UCP_PLATFORM_PROFILE_URL)" (labels: v>1, track-a; assigned: yahalomran) with per-agent profile architecture (relay / tunnel / deployed), HTTPS hosting constraints, and
booking_webhook.pydurability requirements - motivated by #102 part (a) Link side lacking a dedicated actionable issue - Created GitHub issue #115 "Link: RFC 9421 webhook signature verification (booking.confirmed inbound)" (labels: v>1, track-a; assigned: yahalomran) to replace the
LINKUSP_WEBHOOK_VERIFY=1header-presence stub with full §10.1.1 verification - motivated by #102 rollup bullet having no dedicated Link implementation issue - Updated GitHub issue #102 with cross-refs to #114 and #115 in summary table, subsections, and a new "Dedicated post-demo implementation issues" table linking #114, #115, and #112
- Updated GitHub issue #112 to reference #114 (Link profile prerequisite) and #115 (inbound verification) in the production path steps and references
22/06/26 at 13:55:56 by Ran Yahalom
- Expanded GitHub issue #112 background with the full end-to-end "zero registration" production path (5 steps, §8.3 and §9.2.3 normative citations,
profile_unreachable/profile_malformederror types,FinalizeBookingOnPaymenttrigger, signing-key publication detail, and Step 5 Link-side verification consequences) - motivated by the earlier description being accurate but too shallow to serve as a complete spec reference for the implementer - Updated GitHub issue #112 acceptance criteria to replace the silent-fallback criterion with an explicit requirement that fetch failures MUST surface as protocol errors, and added a note that
USP_DEMO_PLATFORM_WEBHOOK_URLmay only remain as a clearly-labelled non-conformant dev override - Expanded GitHub issue #102 "Production webhook URL derivation" subsection with the §9.2.3 normative quote, the "zero registration" framing, and the split between the already-structurally-complete Link side and the Wix-side
profile_unreachable/profile_malformedobligation - also addedevent_iddeduplication confirmation requirement to the RFC 9421 webhook verification bullet
22/06/26 at 13:45:38 by Ran Yahalom
- Created GitHub issue #112 "usp-impl: derive webhook_url from platform profile (UCP-Agent header)" (labels: v>1, webhooks, track-d, usp-impl; assigned: maoryeh) to track the untracked Wix production path where the callback URL is derived from the UCP-Agent header rather than the out-of-band USP_DEMO_PLATFORM_WEBHOOK_URL env var - motivated by #91 step 4 naming this path without a dedicated issue or acceptance criteria
- Updated GitHub issue #102 "UCP conformance gaps" to add two new subsections in "Additional gaps": (a) "Production webhook URL derivation" covering the Link profile publication and Wix UCP-Agent fetch approach with cross-ref to #112; (b) "Full RFC 9421 webhook signature verification" covering replacement of the LINKUSP_WEBHOOK_VERIFY=1 header-presence stub - both gaps were previously untracked in any issue
- Added comment to GitHub issue #91 tagging @maoryeh and cross-referencing the new #112 issue as the dedicated follow-on for the production webhook URL derivation path named in #91 step 4
22/06/26 at 13:29:55 by Ran Yahalom
- Created GitHub issue #111 "Consider per-capability webhook_url in USP to align with UCP's registration model" to track the design discussion around replacing USP's top-level
webhook_urlwith per-capabilityconfig.webhook_urlentries - motivated by the inconsistency between USP's current model and UCP's capability-scoped webhook registration, which creates a structural hybrid in UCP-Native mode profiles
22/06/26 at 09:45:35 by Ran Yahalom
- Repaired UTF-8 mojibake in
plans/USP+UCP_implementation_plan.md(arrow→, section sign§, middle dot·, em dash turned into spaced hyphen-) and normalized table-of-contents fragment links so GitHub-style anchors match the corrected headings, because the plan had been saved with Latin-1 mis-decoding of those UTF-8 sequences and stale double-hyphen slugs.
21/06/26 at 21:25:39 by Ran Yahalom
- Closed the gap tracked as wix-private/universal-scheduling-protocol-spec#99:
specification.md§7.2 / §7.4 / §7.5 / §7.7.2 now show UCP-conformantpayment_handlers(reverse-domain keys, handler arrays,available_instruments), normative rules that checkout responses override the profile at payment time with a MUST on using checkoutavailable_instrumentswhen present, andcomplete_checkoutexamples usepayment.instruments[].handler_idtied to the handler instanceid, so implementers stop mis-parsing flatstripe_cardshapes and match UCP payment architecture. - Updated
site-docs/deployment-modes/ucp-native.md,plans/USP+UCP_implementation_plan.md(step 4, §2.4 verification, #89 / #99 text), the Standalone §8.2 design note to separate UCPpayment_handlersfromcheckout_systems, and addeddocs/ucp-native-demo-merchant-profile.example.jsonas the canonical illustrative merged profile for the demo, so Track E/F work and registry docs stay aligned with the same wire examples.
- Brought
README.mdin line with the current specification outline (domain core through optional Section 6 Discovery Registry, Sections 7-8 deployment modes, 9-10 infrastructure, 11 extensions, 12-14 appendices), updated internal links, cross-cutting RFC section pointers, the machine-readable artifacts path (schemas/plus the full current schema file list), and the Mermaid implementer diagram, because those details had drifted after Section 6 and later renumbering landed onmain. - Expanded
specification.mdSection 1 Introduction with the narrative from wix-private/universal-scheduling-protocol-spec PR #38 (problem framing, agentic design call-outs, protocol structure overview) while citing existing informative references and avoiding ambiguous punctuation, so first-time readers get the same motivation without reviving a stale merge branch.
17/06/26 at 17:22:24 by maorye
- Updated
plans/usp-registry-design-plan.md— the design plan for the USP discovery registry (dev.usp.discovery.registry, §6). Organized in three parts: vendor-neutral protocol-level design (operations, wire model, ownership handshake, ingestion contract, filter semantics), the Wix implementation (Vespa/vFeed/vSearch, projection, ingestion/auth/search), and phasing (Phase 1 demo = no auth + registration + push-only service ingestion + business/service search, then auth, conformant pull+subscription ingestion, MCP, Wix onboarding, hybrid ranking). Includes Mermaid flow diagrams and a decision log scoped Protocol-vs-Impl. Merged the latest design content onto the existingplans/version (keeping its table of contents, cross-reference hyperlinks, and canonical issue URLs) and removed the earlierdocs/copy so the plan lives only underplans/. - Per PR #57 review: the catalog
availability_hint(§3.6) is indexed and searched against by the registry as a ranking/recall signal but is not returned inServiceSearchResultand is never a hard filter — so it is an implementation choice only, requiring no spec or schema change (the source field already exists on catalogService). Recorded the trust & anti-abuse concerns (legitimacy verification, Sybil/registry-pollution — issue #106) and the marketplace/aggregator-relay federation case (folded into #55) raised in review.
17/06/26 at 08:58:31 by Ran Yahalom
- Pointed every
#54–#59reference inplans/usp-registry-design-plan.mdat canonical GitHub issue URLs onwix-private/universal-scheduling-protocol-specso links work from forks, exports, and readers who are not already in the spec repo tree - Confirmed via the API that those five issues still match the plan topics (categories, registry discovery,
signing_keyrequirement, registration auth, search filter semantics); issue numbers needed no correction - Posted the same short cross-reference comment on each of #54, #55, #56, #58, and #59 so the tickets link back to Part 1 §1.10 of the design plan on
main
16/06/26 at 17:54:50 by Ran Yahalom
- Added a table of contents and cross-reference hyperlinks throughout
plans/usp-registry-design-plan.mdso readers can navigate between Part 1/2/3 sections, the decision log, and phasing phases without scrolling - Linked registry design sections to normative repo artifacts (
specification.md§6/§3/§9/§10,schemas/registry.json, OpenAPI/OpenRPC bindings, site docs) and external references (UCP profile, RFC 9421/9457) so protocol gaps and implementation choices trace back to source material
16/06/26 at 17:19:23 by Ran Yahalom
- Triaged GitHub issues in
wix-private/universal-scheduling-protocol-spec: closed #53 as duplicate of #103 (GH-099), assignedmaoryehto #103 withtrack-d/usp-impllabels, closed #19 as superseded by sprint Track C #71-#75, labeled all 24 previously unscoped open issues withv>1plus component labels (spec,usp-impl,registry,standalone,bug,question), and addedout-of-scopeto #51 - Renamed scope label references from
v > 1tov>1inplans/USP+UCP_implementation_plan.mdandscripts/update_plan_issues.pyto match the renamed GitHub label
16/06/26 at 12:40:08 by Ran Yahalom
- Filed all 44 USP+UCP plan work items as GitHub issues #60–#103 in
wix-private/universal-scheduling-protocol-spec(labelv1for in-scope demo;v > 1for GH-054, GH-055, GH-098, GH-099) - Updated
plans/USP+UCP_implementation_plan.md: central issue-tracking assumption, replaced allGH-NNNplaceholders with live issue URLs, removed Task A1–F5 headings in favor of issue-linked track sections, replaced Missing GitHub issues section with issue index table - Added
scripts/issue_map.jsonandscripts/update_plan_issues.pyfor plan ID to issue number mapping
15/06/26 at 14:12:36 by Ran Yahalom
- Fixed internal step cross-references in
plans/USP+UCP_implementation_plan.mdafter calendar renumbering (profile/catalog/availability/checkout tables now point at steps 5, 9, 12, 14, 17; step 9 Fields consumed as table; step 17/20 UCP correlation fields) - Added UCP conformance gaps G-28–G-34 to §4 matrix with demo issues GH-058–GH-064, §2.3 UCP checkout binding rows, sprint timeline, Definition of Done, and Missing GitHub issues section; moved 3DS/G-21 to out-of-scope via GH-098
- Added § Out of scope — UCP conformance gaps (future) rollup for auth, trusted UI, 3DS, full UCP surface, and related non-demo items
- Created issue drafts under
.github/issue-drafts/for GH-058–GH-064 (demo in-scope) and GH-098 (UCP conformance gaps out of scope)
14/06/26 at 16:43:39 by Ran Yahalom
- Added buyer calendar free/busy availability slot filtering to the UCP-Native demo in
plans/USP+UCP_implementation_plan.md, aligned with linkusp-cli (flow calendar ask|connect|skip,filter_slots_by_busy_times) and ds-general USP subagent (Scenario 2 calendar gate beforequery_availability): expanded §1 sequence diagram (steps 7-11), detailed steps, demo success criteria, §2.1 discovery and §2.2 architecture, §2.3 normative map (step 1c / §11.2), §3.2 Calendar section, gap G-27, Task A3b, GH-003b, GH-005/Task A5/Definition of Done updates; renumbered checkout/webhook steps 12-21
14/06/26 at 16:17:19 by Ran Yahalom
- Augmented §1 step-by-step flow in
plans/USP+UCP_implementation_plan.mdwith per-step field provenance tables (fields obtained/consumed → latercreate_checkout,complete_checkout, and webhook use), traceable topaid_bookings.jsonBookingContext, UCP checkout body, and upstream registry/catalog/availability schemas
14/06/26 at 16:13:58 by Ran Yahalom
- Fixed relative hyperlinks in
plans/USP+UCP_implementation_plan.mdafter move from repo root (../specification.md,../schemas/,../openapi/,../openrpc/,../USP+UCP_readiness.md,../.github/issue-drafts/, same-file#anchors); repaired broken GH-055 link inCHANGE_LOG.md
14/06/26 at 14:56:22 by Ran Yahalom
- Removed the client-side
deployment_modepost-filter step from the demo inUSP+UCP_implementation_plan.md(sequence diagram, step-by-step flow, discovery path, Tasks A5/C2/C5, GH-005/021/024, out-of-scope, and GH-055 consumer scope); registry-side capability/payment filters via GH-055 are documented as the correct solution when agents need to narrow by deployment mode, payment handlers, or other USP/UCP capabilities
14/06/26 at 14:47:55 by Ran Yahalom
- Numbered all interaction steps (1-19) in the §1 target demo sequence diagram in
USP+UCP_implementation_plan.md, added the implicit availability response arrow, and inserted a matching step-by-step explanation list so each chronology step states what happens and why it is required
14/06/26 at 14:42:29 by Ran Yahalom
- Reinstated spec-aligned
GET /services/{service_id}inUSP+UCP_implementation_plan.mddemo path (after profile, before availability) per USP §6.3 live-catalog requirement; updated sequence diagram, §2.1/§2.2/§7.5 alignment, Tasks A3/A5/C5, GH-003/005/024, Definition of Done; keptPOST /services/listout of scope
14/06/26 at 14:33:03 by Ran Yahalom
- Removed
POST /services/listfrom demo flow inUSP+UCP_implementation_plan.md(sequence diagram, architecture, §7.5 map, Tasks A3/A5, GH-003/005); demo uses registrysearch_services+service_idthen availability only, aligned with linkusp-cli and ds-general agents; added out-of-scope Merchant-direct catalog discovery section for list
10/06/26 at 18:55:51 by Ran Yahalom
- Trimmed
USP+UCP_implementation_plan.mdgap matrix to in-scope gaps only (removed G-05–G-08, G-11, G-13, G-14, G-16–G-19, G-22–G-25); out-of-scope section no longer references removed matrix IDs
10/06/26 at 18:49:16 by Ran Yahalom
- Brought
booking.confirmedwebhook withorder_idinto demo scope inUSP+UCP_implementation_plan.md(USP §7.5 step 8): P0 gap G-12, Tasks D5/C6, GH-056/057, E2E/assertion updates, sequence diagram, removed from out-of-scope conformance list
10/06/26 at 18:44:07 by Ran Yahalom
- Added plan §2.4 clarifying what "
paid_bookingsextendscheckout" means (profileextendsfield verification, schema/protocol behavior, agent obligations); expanded Task C3, GH-022, GH-040, demo success criteria, and §2.1 discovery step 5 with explicit checks andverify_paid_bookings_extends_checkoutexample
10/06/26 at 18:39:45 by Ran Yahalom
- Switched demo discovery path in
USP+UCP_implementation_plan.mdtosearch_servicesonly: updated sequence diagram, §2.1 discovery steps, Track B/C/A tasks, Definition of Done, and GH-005/011/013/021/024 to useServiceSearchResultwith client-sidebusiness.deployment_mode == ucp_nativepost-filter (registry still implements business search for API completeness)
10/06/26 at 18:19:33 by Ran Yahalom
- Added future-version out-of-scope task and GH-055 to
plans/USP+UCP_implementation_plan.mdfor registry business/service search filters on indexed profile-derived fields (capabilities,payment_handlers,supports_spt) with staleness and re-validation on register/update
10/06/26 at 18:03:28 by Ran Yahalom
- Aligned
USP+UCP_implementation_plan.mdwith USP §6 (registryprofile_urlas full document URL,RegistrationRequestshape, search filters, no capabilities snapshot), §7.2–7.5 (UCP-Native profile, §7.5 flow mapping, atomic complete), and UCP checkout/idempotency/payment_handlers; added normative protocol alignment map (§2.3), fixed discovery/E2E/registry examples and GH issue acceptance criteria
10/06/26 at 17:50:43 by Ran Yahalom
- Refactored
USP+UCP_implementation_plan.mdto treat Link platform and USP registry as independent ecosystem components: registry registration moved to Track B operator process (GH-013/014), Track C reworked as registry consumer only (GH-020-024), added ecosystem architecture section, updated gap matrix (G-26), calendar, and GitHub issue specs; Link no longer registers businesses
10/06/26 at 15:30:17 by Ran Yahalom
- Rewrote
USP+UCP_implementation_plan.mdas a single 2-week UCP-Native demo sprint with six parallel tracks (Link agent, registry, onboarding, Wix usp-impl, UCP+USP extension, Stripe SPT), updated gap matrix, fixed Mermaid diagrams, per-task rationale and steps, GitHub issue anchors (GH-001 through GH-054), and an Out of scope section for holds, mixed cart, order capability, and Standalone Mode
10/06/26 at 11:43:30 by Ran Yahalom
- Added GitHub issue draft for
usp-implPattern B checkout return relay (.github/issue-drafts/usp-impl-checkout-return-relay-body.md) documenting the Wix Headless allowed-redirect-domain failure and why a merchant-owned relay inusp-implis required to serve arbitrary USP agents on redirect checkout
09/06/26 at 14:46:30 by Ran Yahalom
- Added
USP+UCP_implementation_plan.md, a phased gap-closure plan mapping all P0-P2 items from the readiness report to concrete tasks acrossusp-implandecom/acp-checkout, including architecture decisions, acceptance criteria, dependencies, risks, and GA checklist for USP Section 7.7.2
09/06/26 at 14:40:24 by Ran Yahalom
- Added source-verified
ecom/acp-checkoutsection toUSP+UCP_readiness.mdfrom downloaded codebase at/Users/ranya/Downloads/ecom-master/server/agentic-checkout, documenting UCP REST/MCP lifecycle, Google Pay-only payment handlers, and Stripe delegated-checkout as a separate webhook path (not UCP SPT) - Revised Stripe SPT and UCP checkout readiness estimates and gap tables to reflect that no Stripe UCP payment handler or
paid_bookingsintegration exists in eitheracp-checkoutorusp-impl
09/06/26 at 14:20:38 by Ran Yahalom
- Replaced inferred
usp-implarchitecture inUSP+UCP_readiness.mdwith verified source-level analysis from downloaded codebase at/Users/ranya/Downloads/wix-vmr-repo-master/usp-impl, including handler layout, RPC scope, payment path (ChannelType.WEB+ redirect), and documented source bugs (GetBookingempty query,ConfirmPaymentgaps) - Cross-referenced internal
usp-implemented-methods-gap-report.mdto confirm UCP-Native blockers (no holds, no UCP types, no SPT) and updated readiness estimates
09/06/26 at 14:14:49 by Ran Yahalom
- Added inferred source-level architecture section to
USP+UCP_readiness.mdfor Wixusp-impl, mapping RPC operations (ListServices,CreateBooking, etc.) and deployable artifactcom.wixpress.usp.impl.usp-implfrom livex-wix-responded-byheaders after GitHub MCP remained unavailable for the private repo - Expanded endpoint matrix and spec-divergence tables with black-box findings (404 routes, auth-gated operations, ID codecs, error model) so implementers have operation-level detail without source checkout
09/06/26 at 14:05:14 by Ran Yahalom
- Revised
USP+UCP_readiness.mdafter analyzing Wixusp-implvia live deployments (hvac-koby,rolucknow.com) andlinkusp-cliintegration, since GitHub MCP could not read the privatewix-vmr-reporepository - Documented that
usp-implalready ships Standalone Mode USP (catalog, availability, create-booking with redirect payment) while UCP-Nativepaid_bookings, merged/.well-known/ucpprofile, Stripepayment_handlers, and atomic SPT checkout remain gaps
09/06/26 at 13:41:59 by Ran Yahalom
- Added
USP+UCP_readiness.mdgap analysis report evaluating Wix readiness to support USP as a UCP extension with Stripe Shared Payment Tokens, so implementers can see which components exist versus what still blocks end-to-end paid booking checkout - Mapped required USP Section 7 capabilities (catalog, availability, bookings, paid_bookings) and UCP payment architecture requirements against Wix's
ecomagentic-checkout module structure and public Bookings/ecom APIs
27/05/26 at 17:48:19 by itays
- Restructured Overview tab sidebar to match UCP's pattern (8 items vs previous 4) — moved Specification overview, Security, Extensions, and Playground from the Specification tab into Overview so the home page sidebar has comparable depth to ucp.dev
27/05/26 at 17:41:04 by itays
- Redesigned site aesthetics with a Swiss Precision / Technical Authority design system — new typography (Instrument Serif for display, DM Sans for body, DM Mono for code), refined color tokens with teal accent, and light editorial layout to replace the generic AI-generated look
- Updated home page template with section eyebrow labels (e.g., "The Problem", "Verticals", "Workflow", "Architecture") for a more editorial, magazine-like structure matching the new CSS design tokens
- Trimmed verbose code examples in the "See It in Action" section to keep the page scannable while still showing real API payloads
- Sidebar now always visible on home page (hero renders within content grid alongside sidebar, not above it)
27/05/26 at 14:45:02 by itays
- Restructured site navigation from 9 top tabs to 3 (Home, Overview, Specification) to match UCP's navigation pattern — consolidates Deployment Modes, Transport Bindings, Security, Extensions, and Playground under the Specification tab with a deep sidebar, and moves Roadmap under Overview
- Restored left sidebar navigation on the Playground page (was previously hidden) so users can navigate the site without leaving the playground, matching UCP's playground layout
- Removed CSS rules that force-hid the sidebar and forced full-width layout on the playground page
26/05/26 at 18:20:05 by itays
- Added
render.yamlRender Blueprint spec for deploying the USP website as a static site on Render's global CDN, with PR preview environments, cache headers for assets and scenario data, security headers, convenience redirects (/spec→/specification/,/github→ repo), and a build filter scoped to docs-related paths only
26/05/26 at 17:57:27 by itays
- Built interactive USP Playground at
/playground/— server-rendered Jinja2 template (overrides/playground.html) with 8-step scheduling lifecycle simulator (Discovery, Negotiation, Browse Services, Check Availability, Hold Slot, Create Booking, Payment, Manage Booking), modeled after the UCP playground at ucp.dev - Each step has a split layout: configuration panel (scenario dropdown + run button) and code panel (method badge, endpoint path, syntax-highlighted JSON response with copy button)
- Created
playground-controller.js— lightweight vanilla JS controller handling step switching, scenario loading from JSON files, mock request execution with simulated latency, copy-to-clipboard, manage step method/path updates, and mode/transport toggle state - Added step navigation pills, mode toggle (Standalone/UCP-Native), transport toggle (REST/MCP/A2A/ESP), and Next/Back navigation between steps
- Extended
playground.csswith template-specific styles: step pills, split layout grid, config panel, code panel, method badges (GET/POST/PATCH/DELETE), status badges, select dropdowns, syntax highlighting tokens, and responsive breakpoints - Added Playground to
mkdocs.ymlnavigation between Extensions and Roadmap
26/05/26 at 17:32:29 by itays
- Created
playground/src/playground.js— core USP Playground engine implementing the 8-step scheduling lifecycle state machine (discovery, negotiation, browse, availability, hold, book, payment, manage) plus waitlist bonus step, with mode toggle (Standalone/UCP-Native), transport toggle (REST/MCP/A2A/ESP), scenario selection, mock request execution with simulated latency, step navigation with visibility filtering, and full DOM rendering of the playground UI - Created
playground/src/code-editor.js— lightweight JSON display module with regex-based syntax highlighting (keys=gray, strings=teal, numbers=amber, booleans=green, null=red), contentEditable support for request editing, getValue/getRawText parsing, and clipboard copy with fallback - Created
playground/src/response-viewer.js— read-only response display component with HTTP status badge (color-coded 2xx/4xx/5xx), simulated timing display, collapsible sections for large responses (30+ lines), and copy button - Created
playground/src/transport-formatter.js— transport binding converter that transforms REST request configurations into MCP (JSON-RPC 2.0tools/callenvelope with_meta.usp), A2A (tasks/sendwith DataPart), and ESP (iframe embed snippet withpostMessageprotocol) formats, with full method-to-tool-name and method-to-operation-type mapping tables
26/05/26 at 17:29:33 by itays
- Created 10 mock scenario JSON files in
playground/scenarios/for the USP interactive playground simulator, covering the full scheduling lifecycle for "Downtown Wellness Spa" (business IDbiz_downtown_spa) with 4 services across all USP verticals (appointment, group, reservation, rental) business-profile.json: 3 scenarios (standard, full, minimal) for/.well-known/uspbusiness profile responses with varying capability sets, including waitlist/holds toggle and multi-location supportplatform-profile.json: 2 scenarios (standard, advanced) for platform capability negotiation with transport preferences and signing keysservices.json: 4 scenarios (happy_path, filtered_wellness, search_massage, empty_results) with full catalog data for all 4 services including staff/room/equipment resources, policies, media, ratings, and availability hintsavailability.json: 5 scenarios (available_slots, limited_availability, resource_specific, no_availability, range_too_wide) with realistic time slots across 2026-03-15 to 2026-03-17 including peak/off-peak pricing and resource assignmentsholds.json: 4 scenarios (hold_granted, slot_unavailable, hold_limit_exceeded, release_hold) covering the hold lifecycle with proper TTL and error responsesbookings.json: 5 scenarios (instant_confirmation, payment_required, manual_confirmation, validation_error, slot_expired) covering auto/manual confirmation, payment actions with PaymentContext, and error cases (422/409)payment.json: 3 scenarios (payment_success, payment_failed, deposit_flow) for payment completion including deposit-based spa suite reservationsmanage.json: 6 scenarios (view_booking, update_booking, cancel_booking, cancel_with_fee, reschedule_booking, reschedule_limit_reached) for the full booking management lifecycle including late cancellation fees and reschedule limitswebhooks.json: 5 webhook payloads (booking.confirmed, booking.canceled, booking.rescheduled, booking.reminder, booking.completed) conforming to the BookingEvent schemawaitlist.json: 4 scenarios (join_waitlist, offer_received, accept_offer, decline_offer) covering the waitlist lifecycle with offer expiration and conversion to booking- All data uses consistent IDs across files (e.g.,
slot_mass_0315_0900appears in availability, holds, and bookings), amounts in minor currency units (cents), RFC 3339 timestamps, and the USP envelope pattern withversion: "2026-02-21"
26/05/26 at 17:28:03 by itays
- Created comprehensive playground CSS (
playground/styles/playground.css) with full design system: layout containers, horizontal stepper with numbered dots and connector lines (active/completed/upcoming/optional states), mode pill toggle and transport dropdown, request/response code panes with dark background and syntax highlighting classes, method badges (GET/POST/PATCH/DELETE), status badges (2xx/3xx/4xx/5xx), buttons with loading spinner state, navigation footer, negotiation capability grid, manage tab bar, field annotations, callouts, and utility classes — all prefixed withpg-to avoid conflicts with the main site CSS - Created playground Jinja2 template (
overrides/playground.html) extendingmain.htmlwith sidebar/TOC hidden via{% block sidebars %}, OG/Twitter meta tags for social sharing, and deferred loading of playground CSS and JS module — keeps the top nav bar and footer from the main site - Created playground MkDocs entry point (
playground/index.md) with front matter specifying the custom template, SEO metadata (title, description, keywords), and hidden navigation/toc/footer sections - All three files use the existing USP teal color palette (
#0d9488family) and match the dark code-editor aesthetic established inextra.css, with responsive breakpoints at 1024px, 768px, and 480px plus print styles
26/05/26 at 17:20:43 by itays
- Created
playground/directory and drafted comprehensive playground specification (playground/SPEC.md) modeled after the UCP playground at ucp.dev — an 8-step browser-based interactive simulator covering the full USP scheduling lifecycle (discovery, negotiation, browse, availability, hold, book, payment, manage) with scenario dropdowns, transport binding toggle (REST/MCP/A2A/ESP), deployment mode toggle (Standalone/UCP-Native), schema validation, and a waitlist extension bonus step
26/05/26 at 16:53:04 by itays
- Built full USP website using Material for MkDocs to replace the empty placeholder at usp.base44.app, matching the quality level of the UCP website (ucp.dev) with a teal color palette (#0D9488) distinct from UCP's blue
- Created custom homepage template (
overrides/home.html) with 11 sections: hero, stats, verticals, design principles, how-it-works flow, interactive code examples, deployment modes, transport bindings, ecosystem, partners placeholder, and CTA footer - Created 19 content pages derived from the 430KB
specification.md: core concepts, getting started, security, extensions, roadmap, specification overview, service catalog, availability, booking lifecycle, discovery registry, deployment modes (index, UCP-Native, Standalone), transport bindings (index, REST, MCP, A2A, ESP) - Added comprehensive SEO: Open Graph meta tags, Twitter Cards, JSON-LD structured data (WebSite + SoftwareSourceCode + Organization on homepage, TechArticle on inner pages), canonical URLs, robots.txt, sitemap.xml, keywords meta tags
- Created
llms.txtandllms-full.txtfollowing the emerging standard for LLM-readable site descriptions, providing structured protocol summaries for AI consumption - Generated social card image (1200x630 SVG + PNG) with dark gradient background, calendar-clock icon, protocol title/tagline, code snippet preview, transport binding labels, and vertical pills for use in OG/Twitter social sharing
- Added custom CSS design system (
extra.css, 615 lines) with CSS variables, dark mode support, responsive grid layouts, card styles, and homepage section styling - Added Jinja2 template override (
overrides/main.html) for global<head>meta tags with safe{% if page %}guard to handle 404.html rendering wherepageis None - Created
mkdocs.ymlconfiguration with Material theme, Inter/JetBrains Mono fonts, navigation tabs, code copy/annotate, search suggestions, cookie consent, and minify plugin
28/03/26 at 00:47:53 by Ran Yahalom
- Added
$defs/WaitlistEventinschemas/webhook_event.json, RESTwebhooks.waitlistEventinopenapi/usp-rest.json, andWaitlistWebhookEventinopenrpc/usp-mcp.jsonso waitlist webhooks match booking/catalog machine-readable artifacts; expanded specification.md §11.1.5 and §9.2.3 accordingly. - Extended
BookingEventwithbooking.service_startedandbooking.service_updated, aligned §5.4.1 and §5.5.3 prose, and fixed the §5.5.3businesses **MAY**typo so service-delivery events are first-class booking webhook events.
29/03/26 at 14:34:01 by roysha-wix
- Fixed missing space in §11.1 capability declaration (
extends\...→extends `...`) per gap 10.1 - Added request/response schema tables for all 6 waitlist operations in §11.1.3, including the new
POST /waitlist/listpagination endpoint (gap 10.5, 10.12), with cross-reference hyperlinks to OpenAPI and OpenRPC binding files - Clarified offer acceptance flow: accepting atomically creates a booking, response includes
{entry, booking}, payment follows normal flow (gap 10.7) - Added §11.1.6 with waitlist-specific error codes (
waitlist_full,offer_expired,entry_not_found,offer_already_accepted) and explicitmessages[]pattern reference (gap 10.4, 10.6), mirrored in §9.4 error code table - Added introductory note to §12 explaining webhook URL configuration and ESP exclusion (gap 10.8), and split the operation reference into visually grouped sub-tables: Catalog, Availability, Booking, Extension (Waitlist), and Discovery (gap 10.10)
- Added
POST /waitlist/listendpoint toopenapi/usp-rest.jsonwith request filtering (service_id, status) and cursor-based pagination - Added
usp_waitlist_listmethod toopenrpc/usp-mcp.jsonwith matching parameters and result schema - Added
POST /waitlist/list/usp_waitlist_listrow to the §9.2.1 transport mapping table
29/03/26 at 11:21:16 by roysha-wix
- Merged origin/master into gaps-9-security to incorporate Ranya's webhook formalization (schemas/webhook_event.json, OpenAPI webhooks, OpenRPC webhook refs), paid_bookings enhancements, ACP booking extension, and ProfileCapabilityEntry — all complementary to the security gap fixes on this branch
- Resolved CHANGE_LOG.md conflict (both sides prepended entries; kept both in chronological order)
- Verified alignment: webhook payloads chain through Booking → Buyer → BuyerConsent, signature error codes present in both bindings, all component schemas use thin $refs, no duplicate keys, and webhook sections cross-reference §10.1.1 signing requirements
28/03/26 at 00:47:53 by Ran Yahalom
- Added
$defs/WaitlistEventinschemas/webhook_event.json, RESTwebhooks.waitlistEventinopenapi/usp-rest.json, andWaitlistWebhookEventinopenrpc/usp-mcp.jsonso waitlist webhooks match booking/catalog machine-readable artifacts; expanded specification.md §11.1.5 and §9.2.3 accordingly. - Extended
BookingEventwithbooking.service_startedandbooking.service_updated, aligned §5.4.1 and §5.5.3 prose, and fixed the §5.5.3businesses **MAY**typo so service-delivery events are first-class booking webhook events.
27/03/26 at 23:35:39 by Ran Yahalom
- Closed
gaps.md§1–2 items in specification.md: §2.3 profile hosting, graceful degradation (continue_url), andsupported_versions; §2.4 transport-bindings terminology, capability field table, extensionrequiresversion rules; §2.5 governance model and spec/schema URL origin binding; §2.7 error-handling overview and idempotency forward refs; expanded §2.1.3 credential-provider rationale; fixed §2.1.1/§2.6 formatting (spacing, blockquote). - Added
$defs/ProfileCapabilityEntryinschemas/usp.json(requiresspecandschemain business/platform profiles, aligned with UCP); wiredbusiness_schemaandplatform_schemacapability arrays to it; updated §8.2.1 profile field tables for consistency. - Exposed
ProfileCapabilityEntryinopenapi/usp-rest.jsonandopenrpc/usp-mcp.jsonvia thin$refs to canonical$defs.
27/03/26 at 23:18:18 by Ran Yahalom
- Aligned §8.5.6 and §8.6.4 ACP booking extension with the Agentic Commerce
Protocol: extension uses
extendsas a JSONPath array targeting$.CheckoutSession.booking, replaces the non-normativeextensionsbag with a namedbookingfield, and fixes line-item /totals/ currency examples so implementers mappayment_contextto real ACPCheckoutSessionshapes. - Documented PSP vs ACP identifiers for
confirm-payment(transaction_idfrom PSP or handler;order_referencefromorder.idororder.order_number), deposit behaviour under ACP, emptyfulfillment_optionsfor scheduling, ACP payment sub-steps (handlers, delegate payment,complete, 3DS), and slot subset vsSlotReference. - Added machine-readable
schemas/acp_booking_extension.jsonfor the extension payload and pointed the spec’sschemaURL tohttps://usp.dev/schemas/acp_booking_extension.json.
27/03/26 at 22:57:33 by Ran Yahalom
- Addressed Standalone Mode gaps from
gaps.md§7: expanded §8.5 with confirm-payment error codes (§9.4), buyer-side escalation, payment action expiry and abandonment,checkout_systemsdesign note vs UCPpayment_handlers,continue_urlHTTPS rules, and fraud-signal delegation; renamed §8.5.4 to embedded/generic flow and merged lifecycle prose. - Added optional
tax_amounttoschemas/booking.json$defs/PaymentContextand tightenedAction.continue_urldescription; updated Payment Context table in specification.md §8.5.2. - Restructured end-to-end flows: §7.7 and §8.6 now share a consistent preamble +
JSON pattern; new §8.6.2–8.6.5 (Embedded, Redirect, ACP, Deposit) and new §8.7
Payment Path Comparison across deployment modes; updated TOC and cross-links
to
schemas/,openapi/usp-rest.json, andopenrpc/usp-mcp.jsonwhere relevant. - Fixed broken reading-guidance blockquote in §7.3.
27/03/26 at 14:08:18 by Ran Yahalom
- Implemented UCP-Native Mode §7 gap fixes:
BookingContext.booking_statusderivation rules vs fullBooking.status,update_checkout/get_checkoutguidance, escalation/continue_url, cancel checkout semantics,expires_atvs hold, UCP-alignedtotals/linksin checkout example,actionsonBookingContext,confirmation_modemanual vs atomicity, mixed cart note in §7.2, webhookorder_idand delivery caveats, andprice_mismatchin §9.4. - Added machine-validatable webhooks:
new schemas/webhook_event.json (
BookingEvent,CatalogEvent),webhooksin openapi/usp-rest.json,BookingWebhookEvent/CatalogWebhookEventcomponent$refs in openrpc/usp-mcp.json; reconciled §5.4.1 / §9.2.3 withevent_id,order_id, anddatafield naming;BookingContextActionand updatedbooking_statusin schemas/paid_bookings.json.
26/03/26 at 17:54:46 by roysha-wix
- Fixed security gaps 9.1–9.20 from issue #20, aligning §10 with UCP security patterns
- Gap 9.1: Added threat-model framing to §10.1.1 listing attacks that HTTP Message Signatures mitigate (impersonation, tampering, replay, method/endpoint confusion)
- Gap 9.2: Added ECDSA raw
r||sencoding guidance — signatures MUST use fixed-width raw encoding, not ASN.1/DER - Gap 9.3: Deprecated RSA-PSS algorithm — MUST NOT be used in UCP-Native mode, transition period ending 2027-12-31 for Standalone mode
- Gap 9.4: Increased key rotation grace period from 24 hours to 7 days, added 90-day rotation cadence and key compromise response guidance
- Gap 9.5: Added SHOULD-level response signing recommendation for booking confirmations and pricing data
- Gap 9.6: Added replay protection requirements —
@createdtimestamp check (5-minute window) combined with idempotency key/event ID tracking - Gap 9.7: Added intermediary warning that proxies MUST NOT re-serialize JSON bodies (would break Content-Digest)
- Gap 9.8: Added
@authorityand@pathto covered components (replacing@target-uri), preventing cross-host relay attacks - Gap 9.9: Aligned buyer consent categories with UCP — replaced
data_sharingwithsale_of_data, addedpreferences, retainedhealth_dataas USP extension - Gap 9.10: Added declarative consent clarification — protocol communicates consent but does not enforce it
- Gap 9.11: Moved
consentinsidebuyerobject to match UCP'scheckout.buyer.consentpattern; updated schemas/booking.json, openapi/usp-rest.json, openrpc/usp-mcp.json - Gap 9.12: Added RFC 8414 OAuth Server Metadata Discovery requirement to §10.2.4
- Gap 9.13: Added CSRF protection via
stateparameter in authorization requests per RFC 6749 §10.12 - Gap 9.14: Added client authentication requirement — platforms MUST use
client_id/client_secretvia HTTP Basic Auth [RFC 7617] - Gap 9.15: Added recursive token revocation — revoking refresh_token MUST also revoke associated access_tokens
- Gap 9.16: Added UCP scope mapping note for reverse-DNS naming convention in UCP-Native mode
- Gap 9.17: Added account creation flow requirement — authorization endpoint MUST support both login and registration
- Gap 9.18: Added SHOULD-level recommendation for OpenID RISC Profile 1.0 support for security event signaling
- Gap 9.19: Added §10.1.5 Sensitive Credential Handling — raw payment credentials MUST NOT traverse USP APIs
- Gap 9.20: Added signature verification error codes table (signature_missing, signature_invalid, key_not_found, digest_mismatch, signature_expired) to spec, OpenAPI, and OpenRPC
26/03/26 at 16:06:42 by roysha-wix
- Fixed transport binding gaps 8.1–8.14 from issue #20, aligning §9 with UCP patterns
- Gap 8.1: Adopted
structuredContent/contentdual-envelope pattern for MCP responses so AI clients get both typed data and human-readable text - Gap 8.2: Updated MCP binding to use
tools/callwrapper instead of raw JSON-RPC methods, matching the MCP specification - Gap 8.3: Added
idempotency_keyto_meta.uspfor state-modifying MCP operations, providing parity with RESTIdempotency-Keyheader - Gap 8.4: Fixed MCP error model — business outcome errors now return in
result.structuredContent.messages[], not as JSON-RPCerror; only protocol errors use JSON-RPCerror - Gap 8.5: Resolved JSON-RPC error code collisions — removed JSON-RPC codes from business errors table (they use
messages[]now), assigned unique codes to all protocol errors - Gap 8.6: Expanded A2A binding with Agent Card specification (§9.3.3), DataPart conventions (§9.3.4), and session management (§9.3.5)
- Gap 8.7: Added
403 Forbidden,503 Service Unavailableto REST status code table; addedServiceUnavailableresponse component to OpenAPI; addedservice_unavailableprotocol error - Gap 8.8: Added
201 Createdto REST status code table; changed OpenAPI creation endpoints (bookings, holds, registry, waitlist, feed subscriptions) from 200 to 201 - Gap 8.9: Added §9.1.3 Discovery cross-referencing §8.2 business profiles and
USP-Agentheader - Gap 8.10: Added §9.1.4 Request Signing for state-modifying REST requests using RFC 9421; added
signing_keysto PlatformProfile inschemas/profile.json - Gap 8.11: Added conformance subsections to all transport bindings: §9.1.5 REST, §9.2.4 MCP, §9.3.6 A2A, §9.5.6 ESP
- Gap 8.12: Fixed missing spaces between backtick-delimited
Idempotency-Keyand following words in §9.1.1 - Gap 8.13: Added ESP error handling (§9.5.5) with
esp.error,esp.cancel,esp.timeoutmessages and well-known error codes - Gap 8.14: Expanded webhook notifications (§9.2.3) with at-least-once delivery semantics, retry policy, acknowledgment requirements, URL registration, and signature verification; added
webhook_urlto PlatformProfile inschemas/profile.json - Updated
openrpc/usp-mcp.json: renamedUSPErrortoUSPProtocolErrorwith only protocol error codes, wrapped all method results instructuredContentenvelope, addedidempotency_keyto state-modifying methods, updatedinfo.descriptionfortools/call - Updated
openapi/usp-rest.json: addedServiceUnavailable(503) response to all endpoints, changed creation endpoints to return 201
26/03/26 at 13:53:40 by Ran Yahalom
- Finished the zero-duplication OpenAPI/OpenRPC plan: documented
in specification.md §9.1 and §9.2 that
schemas/holds authoritative$defs, bindings use relative$refs and are not self-contained until bundled, and pointed to Redocly/Swagger CLI for bundling.
26/03/26 at 13:50:39 by Ran Yahalom
- Documented agent workflow in AGENTS.md so JSON Schema definitions
stay single-sourced under
schemas/and OpenAPI/OpenRPC bindings use thin external$refs only, preventing drift from duplicated inline bodies and pointing to bundling when a self-contained file is needed.
26/03/26 at 11:24:35 by Ran Yahalom
- Closed Discovery Registry gaps (§6): field tables for business and service
search; MUST-level rule that at least one search filter is present;
cross-references to §9.4 for errors; optional
context(locale,currency);pricing(catalog-aligned) andlast_indexed_aton service hits; conditionallocationand optionaldescriptionon registration; clarifieduspenvelope as the registry’s own capability declaration; indexing guidance (feed subscriptions, 24h fallback, non-authoritative results). - Added registry lifecycle operations
GET/PUT/DELETE/registry/businesses/{id}(§6.4–6.6), renumbered Registry Governance to §6.7, updated Table of Contents, and documented six new MCP methods in §9.2.1. - Added machine-readable schemas/registry.json with
$defsfor registration, search requests, and service search results ( including$refto catalogPricing). - Updated openapi/usp-rest.json: aligned
profile_urlanddeployment_modewith the spec;RegistryContext; revisedRegistryEntryandServiceSearchResult(pricing,last_indexed_at); optionalmessageson registry responses;GET/PUT/DELETEunder/registry/businesses/{id}. - Updated openrpc/usp-mcp.json:
usp_registry_*methods, registry component schemas, andPaginationRequestfor registry search params.
25/03/26 at 17:11:29 by kobym707
- Adopted strict slot-per-resource model (§4.1, §5.3.1): a slot now represents a
specific bookable combination of time window + assigned resources, eliminating
the race condition and undefined behaviour caused by a separate
resource_idselection at booking time. - Added "One slot per resource combination" normative note to §4.1 (TimeSlot):
when the same time window is available for multiple resources, the business
MUST return a separate slot per option, each with its specific resource in the
resourcesarray. - Expanded
resourcesfield description in §4.1 to make clear that each slot carries at most one resource of each type and that picking a slot is equivalent to picking both the time and the resource. - Removed
resource_idfrom the CreateBookingRequest field table (§5.3.1) — resource selection is now fully encoded inslot_id, making the field redundant. - Updated all three
POST /bookingsrequest examples (§5.3.1) to removeresource_id, keeping the examples in sync with the new schema. - Added introductory note to §5.3.1 explaining that resource selection happens at availability query time (via slot choice), not at booking time.
25/03/26 at 12:17:34 by kobym707
- Added
> **JSON Schema:** [/$defs/TypeName](schemas/file.json)blockquotes to every schema-describing and operation section inspecification.mdthat was missing one: §3.12.1, §3.12.3, §3.12.4, §4.1, §4.2, §4.3.1, §4.3.2, §5.3.1–5.3.7, §7.4, §8.5.2, §8.5.5 — making it easy for implementors to jump directly to the machine-readable$defsentry for any section. - Updated all 8 existing
> **JSON Schema:**blockquotes from bare file links to specific/$defs/TypeNamelinks (§3.3, §4 availability intro, §5.2, §5.5.2, §8.5.1, §10.1.1 signing keys, §11.1.1, §11.2.3), consistent with the new pattern.
25/03/26 at 12:08:27 by kobym707
- Added
links[]to theServiceschema (§3.3,catalog.json, OpenAPI, OpenRPC): service-specific policy links (cancellation policy, waiver, ToS) belong at the service level so platforms can surface them during the booking flow before the buyer confirms, not after. - Added
booking_urlto theBookingschema (§5.2,booking.json, OpenAPI, OpenRPC): stable permalink for the buyer to view and manage their booking, used in confirmation emails, calendar events, and buyer portals. - Added
messages[]to theBookingschema (§5.2,booking.json, OpenAPI, OpenRPC): soft informational messages from the business about booking state ( e.g., manual confirmation pending), consistent with howmessages[]is already documented on hold responses. - Added
disputefield andDisputeschema to theBookingobject (§5.5.2,booking.json, OpenAPI, OpenRPC): formalizes the dispute lifecycle with structuredstatus,reason,opened_at, andresolved_atfields; clarifies that opening a dispute does NOT changepayment.status. - Added
tax_amounttoBookingPayment(§8.5.1,booking.json, OpenAPI, OpenRPC) and clarified thatamountis the pre-tax service fee: resolves ambiguity about whether pricing amounts are tax-inclusive. - Added "Booking Expiry" behavioral rules to §5.2: business MUST transition to
canceled, SHOULD sendbooking.canceledwebhook, MUST keep expired booking retrievable via GET, and MUST release the slot. - Added idempotency note to §5.3.1:
hold_idserves as a natural idempotency key; second POST with samehold_idMUST return existing booking; no-hold flows SHOULD useIdempotency-Keyheader. - Expanded §5.3.3 Update Booking with request field table and response
description: documents the three mutable fields (
buyer,recipient,notes) and partial-update semantics. - Expanded §5.3.4 Confirm Booking with request field table, eligible status guidance, and response example.
- Expanded §5.3.5 Cancel Booking with request field table (
reason,canceled_by), eligible statuses, slot-release requirement, and cancel/refund response example. - Expanded §5.3.6 Reschedule Booking with eligible status guidance, booking-ID-preservation note, response description, and price-change handling for peak/off-peak rescheduling.
- Added webhook payload schema and example to §5.4.1 Booking Webhooks, mirroring the existing §5.4.2 Catalog Webhooks structure.
- Added single-service design note to §5 intro (Gap 4.14): USP bookings are single-service by design; multi-service coordination is handled by the platform issuing separate bookings.
24/03/26 at 23:03:02 by kobym707
- Added non-transactional disclaimer to §4.1 (Gap 3.1): slots are advisory-only; platforms MUST NOT treat availability responses as booking commitments, and businesses MUST validate slot availability at booking creation time regardless of holds.
- Added
location_idto §4.3.1 request field table (Gap 3.2): was already in OpenAPI/OpenRPC but absent from the normative prose; now synced across all artifacts. - Added date range guidance to §4.3.1 (Gap 3.3): platforms SHOULD query at most
7 calendar days per request; businesses MAY reject wider ranges with HTTP 422
and error code
range_too_wide. - Added optional
messagesarray to §4.3.1 query response (Gap 3.4): consistent with hold response; enables businesses to return soft warnings (e.g., holiday hours, reduced staffing) alongside slots. - Added single-service design note to §4.3.1 (Gap 3.5): documents the deliberate single-service-per-query design choice and notes that a future multi-service availability extension is under consideration.
- Added §9.1.2 Pagination to the REST Binding section (Gap 3.6): defines shared
cursor semantics (opaque cursors, 60s minimum TTL, ordering note, default page
sizes) used by all paginated USP operations; added cross-reference in §4.3.1;
noted the intentional
next_cursorvscursordistinction between the feed and all other endpoints in §3.1. - Added
spots: 1to §4.3.3 release response example (Gap 3.7): release response now matches hold response schema for consistency. - Added "Concurrent Holds" subsection to §4.2 (Gap 3.8): normative MUST/MUST NOT
rules for concurrent hold behavior by service type —
appointmentallows one active hold maximum,group/reservationallows multiple up to remaining capacity,rentaltreats resource overlap as unavailable. - Added
opening_hours[]field table to §4.3.1 response (Gap 3.9): definesday_of_week(lowercase day names),opens(HH:MM),closes(HH:MM), and clarifies the field reflects regular hours only; special closures are surfaced via absent slots. Fixed OpenRPCusp_availability_queryresult to include full item schema (was previously"type": "array"with no properties). - Added optional
locale(BCP 47) parameter to §4.3.1 (Gap 3.10): allows platforms to request locale-specific human-readable content; narrowed UCP's full context/signals suggestion to only the scheduling-relevant subset. - Added
locale,cursor, andlimitparameters tousp_availability_queryinopenrpc/usp-mcp.jsonandopenapi/usp-rest.jsonto keep all artifacts in sync. - Expanded
Paginationschema descriptions in bothusp-rest.jsonandusp-mcp.json.
24/03/26 at 13:47:43 by kobym707
- Gap 2.10: Added optional
tags(array of strings) andmetadata( freeform object) to Service schema, aligning with UCP. Enables freeform categorization and business-defined custom data. - Gap 2.11: Fixed space-in-URL typo in feed example (
cursor=2026-03-10T08: 00: 00Z). Changed feed cursor examples to opaque values (crs_...) since the spec says cursors are opaque. Removedformat: date-timefrom feed cursor parameter in OpenAPI. - Gap 2.12: Standardized feed pagination from
next_cursortocursorto match thePaginationcomponent used by/services/list. Both endpoints now use{cursor, has_more}. - Gap 2.13: Added §3.13 Catalog Conformance Requirements with 10 numbered
MUST/SHOULD requirements for
dev.usp.services.catalogimplementations. - Gap 2.14: Already addressed — formal filter table was added in the earlier catalog_search alignment commit.
- Gap 2.15: Added optional
categoriesarray (multi-taxonomy,{value, taxonomy}entries) to Service schema alongside existingcategory. If both present,categoriesis authoritative. Aligns with UCP. - Gap 2.16: Added optional
handle(URL-friendly slug) andurl(canonical page) fields to Service schema. Aligns with UCP. - Gap 2.17: Added
statusfield to Service schema with valuesactive( default),suspended,archived. Formally defines thesuspendedstate referenced byservice.suspendedwebhook events. - Gap 2.18: Added formal webhook payload schema table for catalog change
events, defining
event,service_id,subscription_id,timestamp, anddatafields with required/optional semantics.
24/03/26 at 12:12:11 by kobym707
- Added optional
ratingobject to the Service schema withvalue(required),scale_min(default 1),scale_max(required), andcount. Matches UCP's rating schema exactly. Enables platforms and AI agents to display and compare service ratings without external lookups. - Added
Rating$def toschemas/catalog.jsonandratingfield toopenapi/usp-rest.jsonandopenrpc/usp-mcp.json.
24/03/26 at 12:03:55 by kobym707
- Added optional
providerobject to the Service schema (§3.3.3) withname( required),url, andlinks(array of typed links to policy pages). Aligns with UCP'ssellerobject on product variants. Enables platforms to display business name, website, and policy links alongside services without a separate profile fetch — critical for multi-business search results, cached catalogs, and AI agent descriptions. - Added
ProviderandLink$defs toschemas/catalog.json, andproviderfield toopenapi/usp-rest.jsonandopenrpc/usp-mcp.json. - Link types follow UCP pattern:
privacy_policy,terms_of_service,refund_policy,cancellation_policy,faq, with optionaltitlefor display text and graceful handling of unknown types.
24/03/26 at 09:40:22 by kobym707
- Extended
descriptionfield on the Service schema to accept either a plain string (backward compatible) or a structuredDescriptionobject withplain(required),markdown, andhtmlvariants. Aligns with UCP'sDescriptiontype which supports multi-format content. Platforms prefer the richest format they can safely render, falling back toplain. - Added §3.3.2 Description Schema to
specification.mddocumenting the structured format, backward compatibility rules, and HTML sanitization requirements. - Added
Description$def toschemas/catalog.jsonand updateddescriptionfield inopenapi/usp-rest.jsonandopenrpc/usp-mcp.jsonwithoneOf( string | object).
24/03/26 at 09:36:31 by kobym707
- Added
mediaarray to the Service schema (§3.3.1), replacingimages. Each media entry hastype(format:image/video),url,alt_text,role( display:hero/gallery/thumbnail), and optionalwidth/height. Aligns with UCP's typed media model. The previousimagesfield ({url, alt, type}) is retained as a deprecated alias for backward compatibility. - Separated media format type (
type: image/video) from display role (role: hero/gallery/thumbnail) — the oldimages.typeconflated both concepts. - Renamed
alttoalt_textfor consistency with UCP and accessibility standards. - Updated schema.org mapping to handle both image and video media types.
- Updated
schemas/catalog.json,openapi/usp-rest.json, andopenrpc/usp-mcp.json.
24/03/26 at 09:33:08 by kobym707
- Added optional
price_range({min, max}in minor currency units) to the Pricing object in §3.8,schemas/catalog.json,openapi/usp-rest.json, andopenrpc/usp-mcp.json. RECOMMENDED when pricing model isvariable,hourly, orper_person, so platforms can display "from $50 – $150" without querying availability. Aligns with UCP'sprice_rangeon products. Closes the gap where USP services with variable pricing had no displayable price at catalog level.
24/03/26 at 09:30:00 by kobym707
- Added
coordinatesfield (latitude/longitude, WGS 84) to thecontextobject, enabling proximity-based ranking and "near me" queries for scheduling services. Addresses the gap where USP had no mechanism for platforms to signal buyer geographic location beyond postal code. - Extended
contextobject toPOST /services/lookup(previously only on/services/list), so both catalog request endpoints support buyer locale/intent signals for localization of returned content. - Documented that the
contextobject is shared across all catalog request payloads with the same field definitions, and that businesses MUST ignore unrecognized context fields without error for forward compatibility.
24/03/26 at 09:26:45 by kobym707
- Extended
POST /services/listfilters to align with UCPcatalog_search: addedcategories(array, OR logic) alongside existingcategory_id, and addedpricerange filter (min/maxin minor currency units). All filters combine with AND logic; withincategories, values combine with OR logic. - Added
contextobject toPOST /services/listrequest, aligning with UCP's context pattern. Carries buyer locale and intent signals (address_country,address_region,postal_code,language,currency,intent) that businesses use for relevance, localization, and personalization. Businesses MUST ignore unrecognized context fields without error. - Updated §3.12.1 in
specification.mdwith filter and context field tables, updated request examples, and documented precedence rules (categoriesovercategory_id,context.currencyas denomination for price filters).
24/03/26 at 09:21:23 by kobym707
- Added optional
queryfree-text search parameter toPOST /services/listinspecification.md(§3.12.1),openapi/usp-rest.json, andopenrpc/usp-mcp.json— aligns with UCP'scatalog_searchpattern. When present, business ranks results by relevance; when combined with filters, filters are hard constraints and query determines ranking within the filtered set. - Defined graceful degradation: businesses that do not support search MUST
ignore the
queryfield (not error). Businesses that support it SHOULD advertise"search": truein their catalog capability entry.
24/03/26 at 08:55:39 by kobym707
- Added
POST /services/lookupbatch endpoint (§3.12.4) tospecification.md,openapi/usp-rest.json, andopenrpc/usp-mcp.json— analogous to UCP'scatalog_lookup. Accepts an array of service IDs and returns matching services with partial-success semantics (unresolved IDs reported viamessages[]withcode: service_not_found). Closes the gap where USP only offered single-service retrieval viaGET /services/{service_id}. - Defined batch size limits (MUST accept at least 50), deduplication rules ( silent dedup), and ordering contract (unordered response) for the new lookup endpoint.
- Added
Lookup Servicesto the §12 Operation Reference table.
24/03/26 at 08:48:29 by kobym707
- Added optional
messages[]array to all three catalog endpoint responses (/services/list,/services/{service_id},/services/feed) in bothopenapi/usp-rest.jsonandopenrpc/usp-mcp.json, aligning with the UCP message model wherecatalog_lookupandcatalog_searchresponses carry structured messages for partial-success signalling, filter feedback, and service-level warnings. - Updated the
Messageschema in both OpenAPI and MCP specs to match UCP: addedcontent_typefield (plain/markdown), addedunrecoverableseverity level, changedpathfield from JSON Pointer to RFC 9535 JSONPath, madetypeandcontentrequired fields, and expanded severity descriptions to match UCP's semantics. - Added a formal Message field reference table and severity level table to §9.4
in
specification.md, so the message contract is fully documented in the spec prose (previously only in the OpenAPI/MCP schemas). - Updated §9.1 error model description to clarify that
messages[]is available on all USP response envelopes including catalog responses, not only state-modifying operations. - Added
messages[]notes to §3.1 (feed), §3.12.1 (list), and §3.12.3 (get service) endpoint descriptions.
21/03/26 at 14:05:04 by kobym707
- Added §11.2 Buyer Calendar Free/Busy Extension to
specification.md— a MAY-level, platform-scoped extension that enables platforms to access a buyer's calendar for opaque free/busy blocks only, then cross-reference with business availability to suggest mutually free times. Addresses issue #18 requesting privacy-preserving calendar access for scheduling agents. - Introduced the
dev.usp.platform.*capability namespace in §2.5 to distinguish platform-scoped capabilities (implemented entirely by the platform) from business-facingdev.usp.services.*capabilities. Needed because the calendar free/busy extension is the first capability that does not require any business-side implementation. - Created
schemas/calendar_freebusy.jsondefiningBusyBlock(opaque{start, end}withadditionalProperties: falseto enforce no event detail leakage),BuyerFreeBusy(aggregated buyer availability), andCalendarProviderConfig(informative provider reference). - Added
BusyBlockandBuyerFreeBusycomponent schemas toopenapi/usp-rest.jsonfor schema registry completeness, even though no new endpoints are introduced (the feature is platform-internal). - Added
BusyBlockandBuyerFreeBusyto the §1.2 Terminology table so the new types are discoverable alongside existing protocol terms. - Updated §11 Extensions intro to note that extensions can be platform-scoped, not just business-scoped.
- Added informative references to §14.2 for RFC 4791 (CalDAV), Google Calendar FreeBusy API, and Microsoft Graph getSchedule API.
21/03/26 at 16:27:55 by kobym707
- Expanded §11.2.2 Proactive Agent Use Cases with 4 business-initiated reactive scenarios (#8–#11) that compose calendar free/busy with USP webhooks and the waitlist extension: calendar-aware waitlist auto-accept/decline, proactive rebooking on business cancellation, smart conflict detection on business-initiated reschedule, and waitlist priority pre-fetching. These demonstrate the extension's value beyond buyer-initiated flows.
- Reorganized the use cases table into two groups — "Buyer-initiated scenarios" and "Business-initiated scenarios (reactive via webhooks)" — with cross-references to §5.4 (Webhooks) and §11.1 (Waitlist Extension).
21/03/26 at 14:12:18 by kobym707
- Added §11.2.2 Proactive Agent Use Cases to the calendar free/busy extension, describing 7 buyer-initiated agentic scenarios (conflict-aware slot presentation, multi-service coordination, smart rescheduling, travel-time-aware scheduling, availability-first discovery, recurring pattern matching, group scheduling) to strengthen the motivation for the extension and illustrate its value for AI-driven scheduling agents.
- Renumbered §11.2.3–11.2.8 to §11.2.4–11.2.9 to accommodate the new sub-section.
19/03/26 at 18:03:50 by Ran Yahalom
- Expanded
USPErrordefinition inopenrpc/usp-mcp.jsonwith a fully-typeddataschema:code(string enum of all 22 §9.4 error codes including the 5 new profile error codes),messages(array of$ref: Message), andseverity(enum). Previously thedatafield was an unstructured description string, making the error contract unvalidatable. - Added
Forbidden(403) response component toopenapi/usp-rest.jsonfor theprofile_not_trustederror code. This was the only §9.4 protocol error without a corresponding OpenAPI response component. - Added
403and424error responses to all business-facing endpoints inopenapi/usp-rest.json. Profile negotiation errors are protocol-level and can occur on any Standalone Mode call, but previously onlyPOST /services/listreferencedFailedDependency(424). - Fixed previous CHANGE_LOG entry: corrected "four profile-related protocol
error codes" to "five" —
profile_unreachablewas missing from the list.
18/03/26 at 23:26:59 by Ran Yahalom
- Added
schemas/usp.json— formal JSON Schema (Draft 2020-12) for theuspmetadata object used in business profiles, platform profiles, and API responses. Defines$defs/base,business_schema(services, capabilities, checkout_systems, business identity, supported_versions),platform_schema( capabilities + optional service preferences), andresponse_schema(version + active capabilities), along with reusableServiceBinding,CapabilityEntry, andBusinessInfosub-types. Needed to give implementors a machine-validatable schema for the core protocol metadata object. - Added
schemas/profile.json— formal JSON Schema for the two USP profile document types:$defs/BusinessProfile(the document at/.well-known/usp) and$defs/PlatformProfile(the document advertised viaUSP-Agent). Defines$defs/SigningKey(JWK structure for webhook verification keys) with all required EC and RSA fields. Needed because there was no machine-validatable schema for either profile document, making automated validation impossible. - Expanded
specification.md§8.2 with four subsections: §8.2.1 Business Profile Fields (field-level tables for top-level profile,uspobject, ServiceBinding, CapabilityEntry, and namespace governance), §8.2.2 Profile Hosting Requirements (HTTPS, no-redirect, Cache-Control, Content-Type rules and implementation obligations for both sides), §8.2.3 Platform Profile (full specification of the platform profile document structure, example, field table, hosting requirements, and business-side fetch/cache obligations), and §8.2.4 Backward Compatibility (thesupported_versionsmap pattern with 90-day guidance). Needed because the profile was documented only via a single example with no formal field definitions. - Expanded
specification.md§8.3 Capability Negotiation with a six-step negotiation algorithm covering platform profile fetch timing, caching, intersection computation, extension pruning, response envelope, and the empty-intersection error case. Needed to replace the bare four-bullet description with a complete normative algorithm. - Added five profile-related protocol error codes to
specification.md§9.4 error table:invalid_profile_url,profile_unreachable,profile_malformed,capabilities_incompatible, andprofile_not_trusted, with REST status codes and JSON-RPC codes. Needed to make profile failure modes first-class, consistent, and interoperable. - Expanded
specification.md§10.1.1 signing keys documentation with a fullSigningKeyfield table (kid, kty, crv, x, y, n, e, use, alg) and cross-references toschemas/profile.json. Needed becausesigning_keysfield-level constraints were undocumented. - Updated
openapi/usp-rest.json: markedUSP-Agentparameter asrequired: true; addedSigningKey,ServiceBinding,CapabilityEntry,BusinessProfile, andPlatformProfilecomponent schemas; addedGET /.well-known/usppath with full response schema and example. Needed to make the OpenAPI spec self-describing for both the profile endpoint and the header the spec already referenced. - Updated
openrpc/usp-mcp.json: tightened_metaparam schema across all 19 methods —_meta.usp.profileis now declared withformat: uri, descriptive text clarifying it is required in Standalone Mode, andrequired: ["profile"]within theuspsub-object. Needed to align the MCP binding with the REST binding's capability negotiation semantics.
16/03/26 at 12:20:45 by Ran Yahalom
- Implemented
USPRestClient.search_registry_for_servicesmethod body per the/registry/search_servicesOpenAPI schema — performs a POST to the USP registry, builds the request from typed parameters (query, location, verticals, categories, price_range, duration_range, pagination), and parses the response intoServiceSearchResultmodels. Handles both camelCase and snake_case response field names (e.g.resultsvsservices,pagingMetadatavspagination) so the client works against both the live API and schema-compliant implementations. - Added four new Pydantic models to
shopping_agent/subagents/usp/models.py:ServiceSearchResultPrice,ServiceSearchResultLocation,ServiceSearchResult, andServiceSearchPagination— all configured withalias_generator=to_camelandpopulate_by_name=Truefor bidirectional camelCase/snake_case support, matching theServiceSearchResultandPaginationschemas in the OpenAPI spec.
01/03/26 at 15:28:19 by Ran Yahalom
- Scoped
post_payment_return_requestto theredirectcheckout path: Added a note in §8.5.5 and in all schema descriptions clarifying that the field applies only whencheckout_systems: redirectis in use, and is not applicable to theacporembeddedcheckout paths. - Made cancellation/abandonment a first-class outcome
in
post_payment_return_request: Expanded all prose, table descriptions, and schemadescriptionstrings to explicitly state the business MUST honor the return redirect in both terminal outcomes — payment completed and payment cancelled/abandoned — not only on success. - Added SHOULD recommendation for including
post_payment_return_request: Even though the field is optional, updated §8.5.5, the §5.3.1 field table, and all schema descriptions to state that the platform SHOULD always include it on the redirect path, because without it the platform has no way to predict or control where the buyer lands after payment or cancellation.
01/03/26 at 15:24:37 by Ran Yahalom
- Added
post_payment_return_requesttoPOST /bookingsas a first-class spec field with MUST-level compliance language: Resolves the missing return-redirect mechanism in the redirect-based payment flow. The new field lets the platform supply a return URL (with opaque correlation params) at booking creation time — exactly when a server-side checkout system (e.g. Wix headless checkout) needs it — rather than after the buyer reaches the payment page. - Introduced
PostPaymentReturnRequestschema across all spec artefacts (specification.md,openapi/usp-rest.json,openrpc/usp-mcp.json,schemas/scheduling.json): Definesurl(required, URI) andparams( optional, string key-value map) with descriptions that make clear the business must appendparamsverbatim as query parameters on the GET redirect, and that keys/values are opaque platform-controlled correlation state. - Expanded §8.5.5 from "Action Continue URL" to "Redirect Flow and
Post-Payment Return": Added a mermaid sequence diagram of the full redirect
round-trip, MUST language, and the analogy to OAuth 2.0's
redirect_uri+statepattern.
26/02/26 at 10:27:59 by kobym707
- Renamed
schemas/scheduling.jsontoschemas/booking.json: Renamed the file and updated the schema identity ($id,title) to "USP Booking" to better reflect that the schema defines the booking lifecycle (Booking, Buyer, BookingPayment, etc.), not the broader scheduling domain. Updated all references in specification.md and README.md.
25/02/26 at 17:23:00 by Ran Yahalom
- Updated
openrpc/usp-mcp.jsonto match the current OpenAPI and specification: Expanded the sparseBookingschema to include all properties from the OpenAPI spec (resources,location,payment,actions,notes,cancellation,created_at,updated_at,expires_at) with proper types, enums, and descriptions. AddedBookingPayment,PaymentContext, andActioncomponent schemas matching the OpenAPI definitions. UpdatedMessageschema to includeseverityenum,pathfield, and description. The OpenRPC now has full parity with the OpenAPI for all domain schemas (Booking, BookingPayment, PaymentContext, Action, Message).
25/02/26 at 17:16:27 by Ran Yahalom
- Updated
openapi/usp-rest.jsonto match the actions[] changes: AddedActionschema to OpenAPI components. Removedpayment_context,messages, andcontinue_urlfrom the Booking schema and replaced withactionsarray referencing the new Action schema. Removedpayment_urlfrom BookingPayment. Removedexpires_atfrom PaymentContext required fields and properties. Added description to Message schema clarifying its dual use (response-level and action-level).
25/02/26 at 16:11:33 by Ran Yahalom
- Introduced
actions[]array on the booking object: Replaced the flatpayment_context,continue_url, andmessagesfields on the booking with an orderedactionsarray. Each action hastype,status,continue_url,expires_at, and an optionalmessage. Payment actions carry a nestedpayment_context. This makes the spec extensible for future non-payment action types (e.g., waivers, intake forms) while cleaning up thepayment_urlredundancy. - Established the status-actions invariant:
booking.status: requires_actionis now structurally tied toactions[]— the booking MUST have this status if and only if at least one action hasstatus: pending. When the last pending action completes, the business MUST transition the booking out ofrequires_action. - Made actions mode-agnostic for non-payment actions: In UCP-Native Mode,
actions[]never containspayment-type actions (payment is handled by UCP checkout), but non-payment actions may appear on the booking inside thecreate_checkoutresponse.complete_checkoutmay be rejected if non-payment actions are still pending. - Added action ordering rationale: Non-payment actions SHOULD precede payment actions so that the buyer can review requirements (e.g., read a liability waiver) and opt out before committing financially, avoiding unnecessary refunds.
- Removed
payment_urlfrom BookingPayment: Absorbed into the payment action'scontinue_urlfield. - Removed
expires_atfrom PaymentContext: Moved to the action-levelexpires_atfield. - Removed
booking.messages[]: The only concrete usage (payment_required) now lives onaction.message. Response-levelmessages[]remains for business outcome errors/warnings. Removedinfofrom response-level message types. - Added
actions_pendingerror code: For whenconfirm-paymentorcomplete_checkoutis called while non-payment actions are still pending. - Updated
schemas/scheduling.json: AddedActiondefinition to$defswithtype,status,continue_url,expires_at,message, andpayment_context. Removedpayment_context,messages, andcontinue_urlfrom Booking properties. Addedactionsarray. Removedpayment_urlfrom BookingPayment. Removedexpires_atfrom PaymentContext. - Updated all affected sections: Glossary (1.2), operational modes (2.2.1), business responsibilities (2.1.2), architecture diagram text (2.3), booking status lifecycle (5.1), booking schema (5.2), create booking example (5.3.1), confirm-payment (5.3.7), UCP checkout flow (7.5), standalone mode (8), payment integration (8.5.1–8.5.7), checkout_systems (8.2), end-to-end flows (8.6), REST error model (9.1), and error code mapping (9.4).
25/02/26 at 12:51:33 by Ran Yahalom
- Promoted Discovery Registry to standalone Section 6: Extracted Section
7.5 (Discovery Registry) from Standalone Mode and promoted it to a top-level
section (new Section 6) placed before the deployment modes. This reflects that
the Discovery Registry is deployment-mode-independent and can index both
Standalone and UCP-Native businesses. Incurred changes:
- Generalized Discovery Registry for both deployment modes: Replaced
usp_profile_urlwithprofile_url, added adeployment_modefield (standaloneorucp_native) to registration and search schemas, and updated validation rules to support both/.well-known/uspand/.well-known/ucpprofiles. - Renumbered Sections 6-13 → 7-14: Cascading renumber due to the new Section 6 insertion. UCP-Native Mode is now Section 7, Standalone Mode is Section 8, Transport Bindings is Section 9, Security is Section 10, Extensions is Section 11, Operation Reference is Section 12, IANA Considerations is Section 13, References is Section 14.
- Updated all cross-references, ToC, implementation stages, reading path diagram, and reading path tables to reflect the new section numbering and the mode-independent Discovery Registry.
- Generalized Discovery Registry for both deployment modes: Replaced
23/02/26 at 21:30:07 by kobym707
- Added Section 2.1.5 "Implementor Note: Expected Deployment Topology": Clarifies that business-side USP is almost always implemented by SaaS platforms (Wix, Square, Mindbody) on behalf of their merchants, not by individual businesses. This sets reader expectations for why features like the catalog feed, subscriptions, and hold abuse prevention are scoped for professional platform teams, and preempts the "too complex for a small business" objection.
23/02/26 at 16:26:54 by kobym707
- Simplified Section 2.6 (Multi-Location Businesses): Collapsed two
sub-sections (2.6.1 Per-Location Profiles and 2.6.2 Parent-Entity Profile)
into a single unified section. The per-location model was just standard
single-location USP and didn't need its own sub-section; it's now a one-line
note. The section now focuses on the only case that introduces protocol
surface: a single endpoint serving multiple locations via the
locations[]profile field andlocation_idfilters.
23/02/26 at 16:21:59 by kobym707
- Fixed broken Mermaid diagram in Section 2.3 (High-Level Architecture): The
graph TDdiagram used invalid single-dash edge syntax (- "label" -->) which caused a parse error on GitHub. Replaced with valid double-dash syntax (-- "label" -->) and switched\nto<br/>for multi-line edge labels.
22/02/26 at 15:36:29 by kobym707
- Made holds optional via feature flag on the availability capability:
Introduced a
holdsboolean feature flag ondev.usp.services.availabilityto explicitly declare whether a business supports the Hold Slot and Release Slot operations, because many businesses (especially small or low-contention ones) can operate safely without the hold mechanism, and forcing it on all implementers raised the integration bar unnecessarily. - Updated Section 4 (Availability) with feature flag table and discovery
guidance: Added the flag definition, profile declaration example, and
clarified that when
holdsis absent orfalse, the booking flow proceeds directly from slot query to booking creation. - Gated Sections 4.2, 4.3.2, and 4.3.3 behind the holds flag: Added callout
blocks to the Hold entity, Hold Slot, and Release Slot operation sections
noting they require
"holds": true, preventing platforms from calling endpoints the business does not support. - Made
hold_idexplicitly optional in Create Booking (5.3.1) and Reschedule (5.3.6): Added field-level tables withhold_idmarked as optional, added a "without hold" request example, and updated the prose to describe both hold and no-hold flows. - Updated the caching strategy funnel (4.4): Marked the Commit tier as optional and updated the Mermaid diagram to show a conditional branch for hold support.
- Updated all end-to-end flow diagrams (6.7 and 7.7): Changed Mermaid
sequence diagrams to use
opt Business supports holdsblocks instead of showing holds as mandatory steps. - Updated A2A booking flow (8.3.2): Made the hold step conditional and noted
hold_idas optional in the booking creation step. - Updated profile examples (6.2, 7.2) to include
"holds": true: Demonstrates how businesses declare hold support in both UCP-Native and Standalone profiles. - Updated OpenAPI schema: Added descriptions to hold/release endpoints
noting the feature flag requirement, made
hold_idoptional in the reschedule request body, and updatedhold_iddescriptions in create booking. - Updated OpenRPC schema: Added feature flag descriptions to hold/release
methods and made
hold_idoptional (not required) in the reschedule method. - Updated paid_bookings.json schema: Clarified
hold_iddescription to note it depends on holds capability support. - Updated Operation Reference (11) and MCP/A2A mapping tables: Annotated
hold/release operations with
(holds: true)to signal the feature flag requirement. - Updated Hold Abuse Prevention (9.1.2): Scoped the section to apply only when holds are supported.
22/02/26 at 14:09:11 by kobym707
- Promoted Business ID and Localization to peer-level sections: Extracted former 3.3.1 (Business ID) and 3.3.2 (Localization) from under the Service Schema section into their own top-level sections (3.4 and 3.5), consistent with how other complex Service fields (Duration, Pricing, Policies, etc.) are structured. Renumbered sections 3.4-3.10 to 3.6-3.12 and updated all cross-references throughout the spec.
22/02/26 at 13:54:36 by kobym707
- Moved extended verticals to informative Appendix A: Relocated the five
candidate verticals (
event,course,healthcare,home_service,tour) from Section 1.3.2 to a new non-normative Appendix A, following RFC conventions for separating forward-looking content from normative spec. Added promotion criteria (A.2) requiring two independent implementations before a vertical can become core. - Renumbered Custom Verticals to Section 1.3.2: Former Section 1.3.3 is now 1.3.2 with a forward reference to Appendix A for candidate verticals.
- Opened the
typefield enum in JSON schemas: Removed the closed enum constraint onservice.typeinusp-rest.jsonandpaid_bookings.jsonso that vendor-defined custom verticals using reverse-domain notation are not rejected by schema validation, aligning the schemas with what Section 1.3 already permits.
22/02/26 at 12:18:07 by kobym707
- Added
business_idto Service schema: Every service object now carries the identifier of its owning business, making services self-describing for cross-business semantic search, cached catalog aggregation, and agent-to-agent hand-off. The composite key(business_id, id)is the globally unique identifier. Updatedcatalog.json,usp-rest.json,usp-mcp.json, and all service examples inspecification.md. - Added localization (i18n) support: Introduced the
localizedfield on Service with per-locale overrides forname,description,category_name, andchannel_instructionsusing IETF BCP 47 language tags. Enables businesses serving multilingual audiences to provide translations in a single cacheable response. AddedLocalizedFieldstype tocatalog.jsonandusp-rest.json. - Added undetermined duration option: Services with no meaningful duration (
consultations, custom quotes) can now set
duration.undetermined: trueinstead of being forced to provide a fixed or range value. Added mutual exclusivity constraint withfixed/rangeand a validation rule preventinghourlypricing with undetermined duration.
21/02/26 at 11:42:09 by Ran Yahalom
- Extended USP Booking Form Profile with slot selection: Added D0 derivation
rules (slot picker, date picker), new inputs (
slots[],flow_mode), A2UI mappings for slot/date pickers,usp_select_dateaction, and D3/D4/D5 fallbacks when slot not yet selected, enabling unified forms where slot selection is part of the form (pre-fetched or date-first flow) - Bumped profile version to 1.1
21/02/26 at 10:47:37 by Ran Yahalom
- Added USP Booking Form Profile: New separate spec (
docs/usp-booking-form-profile.md) defining field derivation rules and A2UI component mapping for AI agent platforms building booking forms, so platforms know which form fields to show based on service/slot context and how to render them via A2UI - Added design doc:
docs/plans/2026-02-21-usp-booking-form-profile-design.mdcapturing the approved design from brainstorming - Updated README: Added USP Booking Form Profile to the Specification documents table with link to the profile spec
21/02/26 at 10:12:28 by Ran Yahalom
- Updated AGENTS.md entry format to include a mailto link for the author's git email, so each change log entry attributes the author with a clickable email link for traceability and easy contact
- Fixed wrong cross-section links in specification.md: Corrected Section
1.3 (Vertical) link from
#9-service-verticalsto#13-service-verticals; Section 4.4 (Caching Strategy) from#34-caching-strategyto#44-caching-strategy; RFC 6749 (OAuth) from non-existent Section 9.6 to Section 9.2.3 Authentication and Authorization (#923-authentication-and-authorization); RFC 9421 (Webhooks) from Section 9.3 to Section 9.1.1 Webhook Security (#911-webhook-security); Section 5.1 ( Booking Status) from#31-booking-status-lifecycleto#51-booking-status-lifecycle - Fixed TOC: Section 1.5 link text and anchor from "Deployment Modes and
Implementation Guide" /
#15-deployment-modes-and-implementation-guideto " Deployment Modes" /#15-deployment-modesto match actual heading - Added missing cross-links: Converted plain "Section X" references to markdown links throughout the specification (intro, terminology table, implementation stages, deployment mode descriptions, core constructs table, booking schema, webhooks, security, extensions, etc.)
Added schema file links to all schema definition sections
- Section 3.3 (Service Schema): added link to
schemas/catalog.json - Section 4 (Availability): added link to
schemas/availability.json - Section 5.2 (Booking Schema): added link to
schemas/scheduling.json - Section 7.6.1 (Booking Payment Schema): added link to
schemas/scheduling.jsonwith note pointing toBookingPaymentandPaymentContextdefinitions - Section 10.1.1 (WaitlistEntry Schema): added link to
schemas/waitlist.json
**Fixed broken schema reference in Section 6.4 (Paid Bookings Extension Schema) **
- Updated
schemas/services/paid_bookings.json→schemas/paid_bookings.jsonto reflect the schema file relocation fromschemas/services/toschemas/ - Converted plain text reference to a proper Markdown link
Moved 22 schemas out of USPEnvelope to top-level components.schemas
PaginationRequest,Pagination,Service,Duration,Pricing,Location,Channel,ServicePolicies,AvailabilityHint,FeedSubscription,TimeSlot,Hold,Buyer,Booking,BookingPayment,PaymentContext,Message,WaitlistEntry,ResourceRequirement,RegistryEntry,ServiceSearchResult, andProblemDetailswere incorrectly nested as extra keys inside theUSPEnvelopeschema object (siblings of itstype/required/properties)- All 22 are now proper siblings of
USPEnvelopeundercomponents.schemas, which allows$refpointers like#/components/schemas/Durationto resolve correctly
Moved responses block from inside schemas to components.responses
- The 8 response definitions (
BadRequest,Unauthorized,NotFound,Conflict,UnprocessableEntity,FailedDependency,TooManyRequests,InternalServerError) were nested undercomponents.schemas.responsesinstead ofcomponents.responses - They are now correctly placed as a sibling of
schemasundercomponents
Section 7.5.2 –
Renamed POST /registry/search → POST /registry/search_business
- Endpoint path changed to disambiguate from the new service search endpoint
Section 7.5.3 – Added Service Search (POST /registry/search_services)
- New section enabling platforms to search across all registered businesses' services directly
- Request accepts
location,verticals,categories,query,price_range(min/max/currency),duration_range(min_minutes/max_minutes), andpagination - Response returns a
servicesarray withservice_id,service_name, nestedbusinessobject (id, usp_profile_url, name),category,duration_minutes,price,location, andtimezone
Section 7.5.4 – Renumbered Registry Governance
- Previously 7.5.3, renumbered to accommodate the new Service Search section
Section 11 – Endpoint Summary Table
- Updated
/registry/searchrow to/registry/search_business - Added new row for
Search Services | POST | /registry/search_services | discovery (optional)
Renamed path /registry/search → /registry/search_business
- operationId remains
searchBusinesses
Added path /registry/search_services
- operationId:
searchServices - Request body includes
price_rangeandduration_rangefilters in addition to the base search fields - Response returns
servicesarray ofServiceSearchResultitems with pagination
Added schema ServiceSearchResult
- Fields:
service_id,service_name,business(id, usp_profile_url, name),category,duration_minutes,price(amount, currency),location,timezone
Section 7.5.1 – Business Registration (POST /registry/businesses)
- Added
Request:label before the existing JSON body - Added
Response:snippet returning aUSPEnvelopewithdev.usp.discovery.registrycapability and aregistrationobject containingid, echoed request fields,status, andcreated_at
Section 7.5.2 – Business Search (POST /registry/search_business)
- Added
Request:label before the existing JSON body - Added
Response:snippet returning aUSPEnvelopewith abusinessesarray ofRegistryEntryobjects andpaginationwithcursor/has_more
Section 4.3.3 – Release Slot response
- Added
slot_id,service_id, andexpires_atto theholdobject in the response, which are required fields per theHoldschema
Section 7.5.2 – Business Search response
- Added
statusandcreated_atto each business entry in thebusinessesarray, which are required fields per theRegistryEntryschema
Section 7.5.3 – Service Search request and response
- Changed
price_range.min/maxfrom50/200to5000/20000(minor currency units) - Changed
price.amountfrom120/180to12000/18000(minor currency units), consistent with the convention used throughout the spec
Section 7.7.4 – Deposit Flow
- Added
slot_starttopayment_context.metadata, matching thePaymentContextschema and othercreate_bookingresponse examples
New schemas
| Schema | Description |
|---|---|
Duration |
fixed / range (min, max, step), buffer_before, buffer_after |
Pricing |
model (enum), amount, currency, deposit (type, value, refundable) |
Location |
id, name, address, coordinates |
Channel |
type (enum: in_person/virtual/phone/hybrid), virtual_provider, instructions |
ServicePolicies |
cancellation, rescheduling, no_show, booking_window, confirmation_mode, requires_payment, payment_timing with all sub-fields |
AvailabilityHint |
summary, generated_at, next_available_date |
BookingPayment |
status (enum), timing, amount, currency, amount_due, deposit_amount, transaction_id, order_reference, payment_url |
PaymentContext |
amount_due, currency, description, line_items, metadata, expires_at |
ResourceRequirement |
type (enum: staff/room/equipment/other), name, selectable, options |
RegistryEntry |
id, usp_profile_url, name, verticals, categories, location, timezone, status, created_at |
Updated schemas – added missing fields
| Schema | Fields added |
|---|---|
Service |
category, locations, resources, images |
Booking |
resources, location, cancellation |
WaitlistEntry |
preferred_slots |
Updated schemas – added types, descriptions, defaults, and enums
Every property across all schemas was updated from bare {} to include explicit
type, description, format, default, and/or enum values. This applies
to:
USPEnvelope(version, capabilities)Service(all 14 properties)FeedSubscription(id, callback_url, categories, events, status, created_at)TimeSlot(all 10 properties including capacity sub-fields, resources items, location, pricing)Hold(id, slot_id, service_id, spots with default:1, expires_at, status)Buyer(first_name, last_name, email with format:email, phone_number)Booking(all 18 properties including slot sub-object, status enum with 7 values, confirmation_mode enum)Message(type, code, content, severity, path)WaitlistEntry(all 8 properties including preferred_slots items, offered_slot, position with minimum:1)ResourceRequirement(type, name, selectable with default:false, options)RegistryEntry(all 9 properties)ServiceSearchResult(all 8 properties)ProblemDetails(type, title, status, detail, instance, errors)
All request body schemas were also updated (list services filters, availability query, hold slot, create booking, update booking, cancel booking, reschedule booking, confirm payment, join waitlist, accept waitlist offer, register business, search businesses, search services).
Updated endpoint responses
| Endpoint | Change |
|---|---|
POST /registry/businesses |
Response now returns USPEnvelope + { registration: RegistryEntry } instead of bare envelope |
POST /registry/search_business |
businesses array items now reference RegistryEntry; pagination now references Pagination schema |
Fixed inconsistencies with specification.md
| Issue | Fix |
|---|---|
Booking.status enum missing in_progress |
Added in_progress to the enum to match Section 5.1 lifecycle |
opening_hours typed as object |
Changed to array with items schema (day_of_week, opens, closes) to match Section 4.3.1 |