@xema/omni-protocol 0.1.47 → 0.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/testing.js CHANGED
@@ -257,6 +257,18 @@ export async function exerciseAdapter(adapter, context, options = {}) {
257
257
  violations.push(...validateHostGuarantees(context.host.guarantees, "context.host.guarantees"));
258
258
  // The zone is the host's to state, so a context without one is a host that cannot exist.
259
259
  violations.push(...validateTimeZone(context.timeZone, "context.timeZone"));
260
+ // A provider that reads its own clock passes the round trip on any machine in the host's zone,
261
+ // which for a demo and a runner in one datacentre is most of them. A conformance run states a
262
+ // zone this machine is not in, so the only way the identity carries it is that the provider
263
+ // took it from the host.
264
+ if (isTimeZone(context.timeZone)) {
265
+ const canonical = (zone) => new Intl.DateTimeFormat("en", { timeZone: zone }).resolvedOptions().timeZone;
266
+ const local = Intl.DateTimeFormat().resolvedOptions().timeZone;
267
+ if (canonical(context.timeZone) === canonical(local)) {
268
+ violations.push({ rule: "context.timeZone.local", path: "context.timeZone",
269
+ message: `a conformance run states a zone this machine is not in; ${context.timeZone} is this machine's, so a provider reading its own clock would pass the round trip` });
270
+ }
271
+ }
260
272
  // How the agent hears the call decides what the host owns: on a softphone the host has the
261
273
  // audio and reports it; on a desk phone, or off voice, there is none for it to report.
262
274
  violations.push(...validatePhone(context.phone, adapter.manifest, "context.phone"));
package/guide.md CHANGED
@@ -1939,7 +1939,10 @@ field to fill in later: an identity without one is refused (`authentication.iden
1939
1939
  so is a zone that is not an IANA name, wherever it appears. Nothing is ever assumed in its place --
1940
1940
  not the viewer's browser, which gives a different answer per reader for the same record, and not the
1941
1941
  provider's clock. The harness holds a provider to the round trip: the identity carries the zone the
1942
- host stated (`authentication.identity.timeZone.republished`). **The round trip is not the store.**
1942
+ host stated (`authentication.identity.timeZone.republished`), and a conformance run states a zone
1943
+ the machine running it is not in (`context.timeZone.local`): a provider that read its own clock
1944
+ would otherwise pass the round trip on any runner in the host's zone, which for a demo and a runner
1945
+ in one datacentre is most of them. **The round trip is not the store.**
1943
1946
  An adapter that echoes the stated zone back onto the identity passes that check with nothing kept,
1944
1947
  and a lead reading a colleague's day would still get the wrong one. What proves the store is a zone
1945
1948
  the run never sent: a colleague's `User` from `describeUsers()` carrying theirs. A provider's own
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xema/omni-protocol",
3
- "version": "0.1.47",
3
+ "version": "0.1.48",
4
4
  "description": "The Omni protocol: the contract every provider adapter implements",
5
5
  "type": "module",
6
6
  "license": "MIT",