@curless/hotel-storefront 0.26.2 → 0.27.1

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.
Files changed (90) hide show
  1. package/dist/__tests__/audit-p0.test.d.ts +2 -0
  2. package/dist/__tests__/audit-p0.test.d.ts.map +1 -0
  3. package/dist/__tests__/audit-p0.test.js +274 -0
  4. package/dist/__tests__/audit-p0.test.js.map +1 -0
  5. package/dist/__tests__/card-contract.test.js +15 -0
  6. package/dist/__tests__/card-contract.test.js.map +1 -1
  7. package/dist/__tests__/demo-hotels.test.js +2 -1
  8. package/dist/__tests__/demo-hotels.test.js.map +1 -1
  9. package/dist/__tests__/huazhu-audit.test.js +19 -0
  10. package/dist/__tests__/huazhu-audit.test.js.map +1 -1
  11. package/dist/__tests__/huazhu-backend.test.js +510 -14
  12. package/dist/__tests__/huazhu-backend.test.js.map +1 -1
  13. package/dist/__tests__/huazhu-sandbox.test.js +1 -1
  14. package/dist/__tests__/huazhu-sandbox.test.js.map +1 -1
  15. package/dist/__tests__/server.test.js +1 -1
  16. package/dist/__tests__/server.test.js.map +1 -1
  17. package/dist/__tests__/tools.test.js +13 -7
  18. package/dist/__tests__/tools.test.js.map +1 -1
  19. package/dist/backend.d.ts +30 -0
  20. package/dist/backend.d.ts.map +1 -1
  21. package/dist/backend.js +37 -0
  22. package/dist/backend.js.map +1 -1
  23. package/dist/card.generated.d.ts +1 -1
  24. package/dist/card.generated.js +2 -2
  25. package/dist/card.generated.js.map +1 -1
  26. package/dist/demo-hotels.d.ts +14 -0
  27. package/dist/demo-hotels.d.ts.map +1 -1
  28. package/dist/demo-hotels.js +100 -12
  29. package/dist/demo-hotels.js.map +1 -1
  30. package/dist/huazhu/backend.d.ts +11 -2
  31. package/dist/huazhu/backend.d.ts.map +1 -1
  32. package/dist/huazhu/backend.js +524 -271
  33. package/dist/huazhu/backend.js.map +1 -1
  34. package/dist/huazhu/bookings.d.ts +119 -9
  35. package/dist/huazhu/bookings.d.ts.map +1 -1
  36. package/dist/huazhu/bookings.js +355 -66
  37. package/dist/huazhu/bookings.js.map +1 -1
  38. package/dist/huazhu/catalog.d.ts.map +1 -1
  39. package/dist/huazhu/catalog.js +11 -1
  40. package/dist/huazhu/catalog.js.map +1 -1
  41. package/dist/huazhu/check.d.ts.map +1 -1
  42. package/dist/huazhu/check.js +19 -4
  43. package/dist/huazhu/check.js.map +1 -1
  44. package/dist/huazhu/client.d.ts +26 -0
  45. package/dist/huazhu/client.d.ts.map +1 -1
  46. package/dist/huazhu/client.js +77 -2
  47. package/dist/huazhu/client.js.map +1 -1
  48. package/dist/huazhu/fake.d.ts +12 -2
  49. package/dist/huazhu/fake.d.ts.map +1 -1
  50. package/dist/huazhu/fake.js +17 -4
  51. package/dist/huazhu/fake.js.map +1 -1
  52. package/dist/huazhu/origin.d.ts +29 -0
  53. package/dist/huazhu/origin.d.ts.map +1 -0
  54. package/dist/huazhu/origin.js +69 -0
  55. package/dist/huazhu/origin.js.map +1 -0
  56. package/dist/huazhu/sandbox.d.ts.map +1 -1
  57. package/dist/huazhu/sandbox.js +5 -1
  58. package/dist/huazhu/sandbox.js.map +1 -1
  59. package/dist/huazhu/sellable.d.ts +6 -1
  60. package/dist/huazhu/sellable.d.ts.map +1 -1
  61. package/dist/huazhu/sellable.js +14 -3
  62. package/dist/huazhu/sellable.js.map +1 -1
  63. package/dist/huazhu/wire.d.ts +28 -4
  64. package/dist/huazhu/wire.d.ts.map +1 -1
  65. package/dist/huazhu/wire.js +42 -3
  66. package/dist/huazhu/wire.js.map +1 -1
  67. package/dist/index.js +13 -5
  68. package/dist/index.js.map +1 -1
  69. package/dist/limits.d.ts +10 -0
  70. package/dist/limits.d.ts.map +1 -1
  71. package/dist/limits.js +25 -2
  72. package/dist/limits.js.map +1 -1
  73. package/dist/server.d.ts +25 -8
  74. package/dist/server.d.ts.map +1 -1
  75. package/dist/server.js +114 -9
  76. package/dist/server.js.map +1 -1
  77. package/dist/sessions.d.ts +31 -4
  78. package/dist/sessions.d.ts.map +1 -1
  79. package/dist/sessions.js +66 -15
  80. package/dist/sessions.js.map +1 -1
  81. package/dist/state.d.ts +16 -0
  82. package/dist/state.d.ts.map +1 -1
  83. package/dist/state.js +33 -3
  84. package/dist/state.js.map +1 -1
  85. package/dist/tools.d.ts.map +1 -1
  86. package/dist/tools.js +63 -18
  87. package/dist/tools.js.map +1 -1
  88. package/dist/types.d.ts +16 -1
  89. package/dist/types.d.ts.map +1 -1
  90. package/package.json +9 -11
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
package/dist/state.d.ts CHANGED
@@ -1,7 +1,20 @@
1
+ /**
2
+ * The most one store may write, in characters of JSON.
3
+ *
4
+ * ⚠️ PAST IT, NOTHING IS WRITTEN AND SOMEBODY IS TOLD. Unbounded guest fields
5
+ * once grew the bookings file past what `JSON.stringify` can make at all; the
6
+ * write threw, a line went to a log nobody reads, and every booking from then
7
+ * on lived only in memory until the next deploy forgot it (2026-10-05 audit).
8
+ * Now an over-size snapshot leaves the last good file where it is, the store
9
+ * says it is in trouble, and the demo stops taking bookings it could not keep.
10
+ */
11
+ export declare const MAX_STATE_CHARS: number;
1
12
  export declare class StateFile {
2
13
  readonly path: string;
3
14
  private timer;
4
15
  private snapshot;
16
+ /** Why the last write did not happen - cleared by the next one that does. */
17
+ trouble: string | undefined;
5
18
  constructor(path: string);
6
19
  /**
7
20
  * What was written last time, or undefined when there is nothing usable.
@@ -18,6 +31,7 @@ export declare class StateFile {
18
31
  /** Write now if anything is waiting. */
19
32
  flush(): void;
20
33
  private write;
34
+ private fail;
21
35
  }
22
36
  /** Where the stores of one deployment keep their files - or nothing, when it has no directory. */
23
37
  export declare class StateDir {
@@ -28,5 +42,7 @@ export declare class StateDir {
28
42
  file(name: string): StateFile | undefined;
29
43
  /** Everything still waiting, written now - on a clean stop. */
30
44
  flush(): void;
45
+ /** The stores whose last write did not happen, and why - for `/healthz/detail`. */
46
+ troubles(): Record<string, string>;
31
47
  }
32
48
  //# sourceMappingURL=state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAuBA,qBAAa,SAAS;IAIR,QAAQ,CAAC,IAAI,EAAE,MAAM;IAHjC,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,QAAQ,CAA8B;gBAEzB,IAAI,EAAE,MAAM;IAEjC;;;;;;OAMG;IACH,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,SAAS;IAuBxB,kGAAkG;IAClG,IAAI,CAAC,QAAQ,EAAE,MAAM,OAAO,GAAG,IAAI;IAInC,wCAAwC;IACxC,OAAO,IAAI,IAAI;IAMf,wCAAwC;IACxC,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,KAAK;CAed;AAED,kGAAkG;AAClG,qBAAa,QAAQ;IAGP,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAF5C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;gBAEpB,GAAG,EAAE,MAAM,GAAG,SAAS;IAE5C,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAOzC,+DAA+D;IAC/D,KAAK,IAAI,IAAI;CAGd"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,QAAmB,CAAC;AAEhD,qBAAa,SAAS;IAMR,QAAQ,CAAC,IAAI,EAAE,MAAM;IALjC,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,QAAQ,CAA8B;IAC9C,6EAA6E;IAC7E,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEP,IAAI,EAAE,MAAM;IAEjC;;;;;;OAMG;IACH,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,SAAS;IAuBxB,kGAAkG;IAClG,IAAI,CAAC,QAAQ,EAAE,MAAM,OAAO,GAAG,IAAI;IAInC,wCAAwC;IACxC,OAAO,IAAI,IAAI;IAMf,wCAAwC;IACxC,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,KAAK;IAuBb,OAAO,CAAC,IAAI;CAMb;AAED,kGAAkG;AAClG,qBAAa,QAAQ;IAGP,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAF5C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;gBAEpB,GAAG,EAAE,MAAM,GAAG,SAAS;IAE5C,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAOzC,+DAA+D;IAC/D,KAAK,IAAI,IAAI;IAIb,mFAAmF;IACnF,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAKnC"}
package/dist/state.js CHANGED
@@ -18,10 +18,23 @@ import { dirname, join } from 'node:path';
18
18
  // rewrite its file on every tool call - so the last half second before a crash
19
19
  // can be lost. A clean stop (`flush`, on SIGTERM) loses nothing.
20
20
  const WRITE_DELAY_MS = 500;
21
+ /**
22
+ * The most one store may write, in characters of JSON.
23
+ *
24
+ * ⚠️ PAST IT, NOTHING IS WRITTEN AND SOMEBODY IS TOLD. Unbounded guest fields
25
+ * once grew the bookings file past what `JSON.stringify` can make at all; the
26
+ * write threw, a line went to a log nobody reads, and every booking from then
27
+ * on lived only in memory until the next deploy forgot it (2026-10-05 audit).
28
+ * Now an over-size snapshot leaves the last good file where it is, the store
29
+ * says it is in trouble, and the demo stops taking bookings it could not keep.
30
+ */
31
+ export const MAX_STATE_CHARS = 32 * 1024 * 1024;
21
32
  export class StateFile {
22
33
  path;
23
34
  timer;
24
35
  snapshot;
36
+ /** Why the last write did not happen - cleared by the next one that does. */
37
+ trouble;
25
38
  constructor(path) {
26
39
  this.path = path;
27
40
  }
@@ -78,18 +91,31 @@ export class StateFile {
78
91
  if (!this.snapshot)
79
92
  return;
80
93
  try {
94
+ const text = JSON.stringify(this.snapshot());
95
+ if (text.length > MAX_STATE_CHARS) {
96
+ this.fail(`${text.length} characters, over the ${MAX_STATE_CHARS} a store may write`);
97
+ return;
98
+ }
81
99
  mkdirSync(dirname(this.path), { recursive: true });
82
100
  const tmp = `${this.path}.${process.pid}.tmp`;
83
101
  // ⚠️ OWNER-ONLY. These files hold names, emails and phone numbers.
84
- writeFileSync(tmp, JSON.stringify(this.snapshot()), { mode: 0o600 });
102
+ writeFileSync(tmp, text, { mode: 0o600 });
85
103
  chmodSync(tmp, 0o600);
86
104
  renameSync(tmp, this.path);
105
+ this.trouble = undefined;
87
106
  }
88
107
  catch (err) {
89
108
  // A full disk must not take the conversation down with it: the state is
90
- // still right in memory, and the next change tries again.
91
- console.error(`[state] could not write ${this.path}: ${err.message}`);
109
+ // still right in memory, and the next change tries again - but until one
110
+ // does, the store says so (see `trouble`).
111
+ this.fail(err.message);
112
+ }
113
+ }
114
+ fail(why) {
115
+ if (this.trouble !== why) {
116
+ console.error(`[state] NEEDS A PERSON: ${this.path} was not written - ${why}`);
92
117
  }
118
+ this.trouble = why;
93
119
  }
94
120
  }
95
121
  /** Where the stores of one deployment keep their files - or nothing, when it has no directory. */
@@ -114,5 +140,9 @@ export class StateDir {
114
140
  for (const f of this.files)
115
141
  f.flush();
116
142
  }
143
+ /** The stores whose last write did not happen, and why - for `/healthz/detail`. */
144
+ troubles() {
145
+ return Object.fromEntries(this.files.filter((f) => f.trouble).map((f) => [f.path, f.trouble ?? '']));
146
+ }
117
147
  }
118
148
  //# sourceMappingURL=state.js.map
package/dist/state.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,8EAA8E;AAC9E,iCAAiC;AACjC,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAChF,4EAA4E;AAC5E,+EAA+E;AAC/E,2EAA2E;AAC3E,8CAA8C;AAC9C,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,yEAAyE;AACzE,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,iEAAiE;AAEjE,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,MAAM,OAAO,SAAS;IAMC;IALb,KAAK,CAA4C;IACjD,QAAQ,CAA8B;IAC9C,6EAA6E;IAC7E,OAAO,CAAqB;IAE5B,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAErC;;;;;;OAMG;IACH,IAAI;QACF,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC,CAAC,WAAW;QAC/B,CAAC;QACD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;gBACP,gEAAgE;YAClE,CAAC;YACD,OAAO,CAAC,KAAK,CACX,WAAW,IAAI,CAAC,IAAI,mBAAoB,GAAa,CAAC,OAAO,cAAc,KAAK,EAAE,CACnF,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,kGAAkG;IAClG,IAAI,CAAC,QAAuB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,wCAAwC;IACxC,OAAO;QACL,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO;QACvB,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,cAAc,CAAC,CAAC;QAC5D,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IACvB,CAAC;IAED,wCAAwC;IACxC,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QACxB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC7C,IAAI,IAAI,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;gBAClC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,yBAAyB,eAAe,oBAAoB,CAAC,CAAC;gBACtF,OAAO;YACT,CAAC;YACD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;YAC9C,mEAAmE;YACnE,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1C,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACtB,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,wEAAwE;YACxE,yEAAyE;YACzE,2CAA2C;YAC3C,IAAI,CAAC,IAAI,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAEO,IAAI,CAAC,GAAW;QACtB,IAAI,IAAI,CAAC,OAAO,KAAK,GAAG,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,IAAI,sBAAsB,GAAG,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;IACrB,CAAC;CACF;AAED,kGAAkG;AAClG,MAAM,OAAO,QAAQ;IAGE;IAFJ,KAAK,GAAgB,EAAE,CAAC;IAEzC,YAAqB,GAAuB;QAAvB,QAAG,GAAH,GAAG,CAAoB;IAAG,CAAC;IAEhD,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC;IAChC,CAAC;IAED,IAAI,CAAC,IAAY;QACf,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAChC,MAAM,CAAC,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,+DAA+D;IAC/D,KAAK;QACH,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK;YAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IACxC,CAAC;IAED,mFAAmF;IACnF,QAAQ;QACN,OAAO,MAAM,CAAC,WAAW,CACvB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAC1E,CAAC;IACJ,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/dist/tools.js CHANGED
@@ -1,4 +1,4 @@
1
- import { DEFAULT_PAGE, FULL_CAPABILITIES, LASTING_REQUESTS, MAX_PAGE, REQUEST_KINDS, REQUEST_NOTE_MAX, } from './backend.js';
1
+ import { DEFAULT_PAGE, FULL_CAPABILITIES, LASTING_REQUESTS, MAX_PAGE, REQUEST_KINDS, REQUEST_NOTE_MAX, guestTooLong, } from './backend.js';
2
2
  import { isDay, nights as nightsBetween } from './dates.js';
3
3
  import { FACILITIES } from './facilities.js';
4
4
  import { DESCRIPTION_MAX, POLICY_MAX, hotelText } from './fence.js';
@@ -1340,14 +1340,17 @@ const dateFlex = (dates, stay) => {
1340
1340
  const identity = (deps, ctx, key, args = {}) => {
1341
1341
  const email = str(args.email);
1342
1342
  const member = deps.members.read(key);
1343
+ const own = tripKey(ctx.session, deps.vocab.brand);
1343
1344
  return {
1344
- // ⚠️ THE CONVERSATION, NOT THE CONNECTION. A card's calls arrive on a
1345
- // different connection from the conversation's (see trip-ids.ts), so a
1346
- // booking filed under the raw session was one the card itself could not
1347
- // find: "Cancel this booking" on the confirmation it had just drawn
1348
- // answered that no booking matched (2026-09-28 audit). `key` is the trip
1349
- // key, which the card names and the conversation shares.
1350
- sessionId: key,
1345
+ // ⚠️ THE CALLER'S OWN SESSION, NEVER THE TRIP IT NAMED. This was the trip
1346
+ // key, so that the card - on a connection of its own - could cancel what
1347
+ // the conversation booked. But a trip id travels in every card answer, and
1348
+ // it opened every booking of that conversation, names and emails and all,
1349
+ // from any connection or none (2026-10-05 audit). A trip id is for the
1350
+ // trip; a booking opens by its conversation, or by its code AND email,
1351
+ // which is what the card now sends.
1352
+ sessionId: own,
1353
+ ...(key !== own ? { tripOwner: key } : {}),
1351
1354
  ...(email ? { email } : {}),
1352
1355
  // ⚠️ THE MEMBER BUYS A RATE, NOT A LOOKUP. `listBookings` and the
1353
1356
  // cancellation tools still key on the conversation and on the email the
@@ -1391,6 +1394,29 @@ const remember = (deps, k, amount) => {
1391
1394
  m.delete(oldest);
1392
1395
  }
1393
1396
  };
1397
+ /**
1398
+ * What a backend's refusal says, for the guest - or, when the failure is the
1399
+ * code's own, a sentence that says nothing about the code.
1400
+ *
1401
+ * ⚠️ A REFUSAL IS WORDS FOR THE GUEST; A FAULT IS NOT. Every backend refuses
1402
+ * with a plain Error, or one carrying a `code`, and those words are written to
1403
+ * be read back ("Nothing was booked: ..."). A TypeError's words - "Cannot read
1404
+ * properties of null" - were read back too (2026-10-05 audit); they go to the
1405
+ * log now.
1406
+ */
1407
+ const guestWords = (err, fault = 'That could not be done just now - nothing was changed. Try again in a moment.') => {
1408
+ const e = err;
1409
+ if (e instanceof Error && (typeof e.code === 'string' || e.constructor === Error))
1410
+ return e.message;
1411
+ console.error('[tools] failed:', err);
1412
+ return fault;
1413
+ };
1414
+ /**
1415
+ * A booking's own fault sentence. ⚠️ IT CANNOT SAY "NOTHING WAS CHANGED": the
1416
+ * fault may come after the backend has booked (华住's review, 2026-10-05), and
1417
+ * a guest told nothing happened books again.
1418
+ */
1419
+ const BOOKING_FAULT = 'It is not certain whether that booked - list the bookings before asking for it again.';
1394
1420
  /** Said when a lookup has missed too often - see limits.ts. */
1395
1421
  const TOO_MANY_TRIES = 'Too many codes and emails that did not match, so looking a booking up by email is paused for a quarter of an hour. Check the code and the email on the confirmation, then try again.';
1396
1422
  /**
@@ -1401,8 +1427,19 @@ const TOO_MANY_TRIES = 'Too many codes and emails that did not match, so looking
1401
1427
  * email; after a few, lookups by email wait (limits.ts). A lookup of this
1402
1428
  * conversation's own booking, with no email, is never counted and never waits.
1403
1429
  */
1404
- const guarded = async (deps, key, who, run) => {
1405
- const keys = who.email ? [`lookup|${key}`, `email|${who.email.trim().toLowerCase()}`] : [];
1430
+ const guarded = async (deps, ctx, who, code, run) => {
1431
+ // ⚠️ NOT ONLY THE CONVERSATION. Counted against the conversation alone, a
1432
+ // guesser started a new one - or sent none - after every five (2026-10-05
1433
+ // audit). So also against the CODE, which stops "I know the code, let me
1434
+ // guess the email", and the network address, which stops the rest.
1435
+ const keys = who.email
1436
+ ? [
1437
+ `lookup|${who.sessionId}`,
1438
+ `email|${who.email.trim().toLowerCase()}`,
1439
+ ...(code ? [`code|${code.trim().toLowerCase()}`] : []),
1440
+ ...(ctx.ip ? [`ip|${ctx.ip}`] : []),
1441
+ ]
1442
+ : [];
1406
1443
  if (keys.length && deps.misses?.blocked(keys))
1407
1444
  return { found: null, tooMany: true };
1408
1445
  const found = await run();
@@ -2353,7 +2390,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
2353
2390
  const code = str(args.booking);
2354
2391
  const who = identity(deps, ctx, key, args);
2355
2392
  const { found, tooMany } = code
2356
- ? await guarded(deps, key, who, () => deps.backend.findBooking(code, who))
2393
+ ? await guarded(deps, ctx, who, code, () => deps.backend.findBooking(code, who))
2357
2394
  : { found: null, tooMany: false };
2358
2395
  const booked = found && (found.status === 'requested' || found.status === 'confirmed') ? found : undefined;
2359
2396
  if (code && found && !booked) {
@@ -2548,6 +2585,8 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
2548
2585
  !guest.name && 'a name',
2549
2586
  !guest.email.includes('@') && 'an email',
2550
2587
  phoneNeeded && phone.replace(/\D/g, '').length < 6 && 'a phone number',
2588
+ // Too long is as unusable as missing - see GUEST_LIMITS.
2589
+ ...guestTooLong({ ...guest, phone }),
2551
2590
  ].filter((x) => typeof x === 'string');
2552
2591
  if (missing.length) {
2553
2592
  const said = missing.length > 1
@@ -2674,14 +2713,15 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
2674
2713
  };
2675
2714
  }
2676
2715
  catch (err) {
2716
+ const words = guestWords(err, BOOKING_FAULT);
2677
2717
  return {
2678
2718
  structured: {
2679
2719
  view: 'error',
2680
2720
  ...common(deps, key),
2681
2721
  error: 'not-bookable',
2682
- detail: err.message,
2722
+ detail: words,
2683
2723
  },
2684
- text: err.message,
2724
+ text: words,
2685
2725
  };
2686
2726
  }
2687
2727
  }
@@ -2691,7 +2731,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
2691
2731
  // Elsewhere, only with the code AND the email - see `listBookings`.
2692
2732
  const code = str(args.booking);
2693
2733
  const { found: there, tooMany } = code && str(args.email)
2694
- ? await guarded(deps, key, who, () => deps.backend.findBooking(code, who))
2734
+ ? await guarded(deps, ctx, who, code, () => deps.backend.findBooking(code, who))
2695
2735
  : { found: null, tooMany: false };
2696
2736
  const bookings = there && !here.some((b) => b.id === there.id) ? [there, ...here] : here;
2697
2737
  // ⚠️ A MISS IS SAID EVEN WHEN THERE IS SOMETHING TO LIST. With two
@@ -2737,7 +2777,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
2737
2777
  ...(str(args.extra) ? { extra: str(args.extra) } : {}),
2738
2778
  ...(typeof args.quantity === 'number' ? { quantity: args.quantity } : {}),
2739
2779
  };
2740
- const { found: preview, tooMany } = await guarded(deps, key, who, () => deps.backend.previewChange(ref, change, who));
2780
+ const { found: preview, tooMany } = await guarded(deps, ctx, who, ref, () => deps.backend.previewChange(ref, change, who));
2741
2781
  if (!preview) {
2742
2782
  return {
2743
2783
  structured: {
@@ -2859,13 +2899,13 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
2859
2899
  };
2860
2900
  }
2861
2901
  catch (err) {
2862
- return { ...asPreview, text: err.message };
2902
+ return { ...asPreview, text: guestWords(err) };
2863
2903
  }
2864
2904
  }
2865
2905
  if (name === t.previewCancellation || name === t.cancelBooking) {
2866
2906
  const ref = str(args.booking);
2867
2907
  const who = identity(deps, ctx, key, args);
2868
- const { found: preview, tooMany } = await guarded(deps, key, who, () => deps.backend.previewCancellation(ref, who));
2908
+ const { found: preview, tooMany } = await guarded(deps, ctx, who, ref, () => deps.backend.previewCancellation(ref, who));
2869
2909
  if (!preview) {
2870
2910
  return {
2871
2911
  structured: {
@@ -3051,7 +3091,12 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
3051
3091
  const surname = str(args.surname);
3052
3092
  // Counted like a booking lookup - see limits.ts. A number and a surname
3053
3093
  // read a tier, a point balance and saved preferences.
3054
- const tries = [`signin|${key}`, `member|${number.replace(/\s+/g, '').toUpperCase()}`];
3094
+ const tries = [
3095
+ `signin|${key}`,
3096
+ `member|${number.replace(/\s+/g, '').toUpperCase()}`,
3097
+ // The network too, as for bookings - see `guarded`.
3098
+ ...(ctx.ip ? [`ip|${ctx.ip}`] : []),
3099
+ ];
3055
3100
  if (deps.misses?.blocked(tries)) {
3056
3101
  return {
3057
3102
  structured: {