@origonai/web-sdk 0.1.0 → 0.1.2

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/docs/contract.md CHANGED
@@ -34,9 +34,69 @@ reciprocal cross-repository contract ledger.
34
34
 
35
35
  ## Release gate
36
36
 
37
- Run typecheck, unit tests, and the production build, then rebuild the linked
38
- `workspace/web/chat` consumer before publication. Publishing to npm remains an
39
- owner action and is never part of an implementation spin.
37
+ Run typecheck, unit tests, and the production build, then rebuild both linked
38
+ `workspace/web/chat` and `workspace/web/cx` consumers. Inspect the packed
39
+ declarations and artifact bytes before publication. Publishing to npm remains
40
+ an owner action and is never part of an implementation spin.
41
+
42
+ ## Live-chat monitoring and optional message metadata
43
+
44
+ - Version 0.1.2 exposes optional `Message.metadata` and optional
45
+ `MessageMetadata.audience`. ORPC messages plus REST directory/history rows
46
+ normalize missing/null containers to `undefined`, while a present object with
47
+ a missing/null/empty audience remains `{}`. Lowercase `internal|all` is
48
+ preserved and every other non-empty value fails without trimming. Received
49
+ `TypingEvent.metadata` remains required and known.
50
+ - Ordinary participant message and typing calls omit request metadata. CX
51
+ resolves participant-purpose omission to `all`; monitor-purpose omission is
52
+ invalid. Monitor consumers therefore validate and send an explicit
53
+ `internal|all` audience for every message and typing operation.
54
+ - CX remains the authorization and projection boundary. Optional parsing never
55
+ authorizes an internal row for an external consumer, and newly authored CX
56
+ storage/events/replay/history/directory values remain explicit.
57
+ - `onTyping` receives exactly `{participantId, role, userId, userName, state,
58
+ metadata}`. Inbound watchdogs are participant-keyed; one participant's off
59
+ or message cannot clear an unrelated participant.
60
+
61
+ ## Authenticated attachment lane
62
+
63
+ - `Credentials.attachmentBaseUrl` is the only lane selector. It accepts an
64
+ HTTP(S) absolute or root-relative base only when its resolved origin exactly
65
+ matches `Credentials.endpoint`; credentials, query, fragment, raw/encoded/
66
+ backslash traversal, malformed encodings, and cross-origin inputs fail during
67
+ `initialize()` before network.
68
+ - Selecting this authenticated lane requires the otherwise-optional top-level
69
+ token; omission fails during `initialize()`.
70
+ - When the explicit base is present, XHR upload and fetch delete send the
71
+ existing top-level token as `Authorization: Bearer …`. When it is absent, the
72
+ widget endpoint lane suppresses the token even if one was supplied for other
73
+ APIs. Error surfaces redact the bearer.
74
+ - Upload progress, cancellation-by-upload-id, and delete behavior are shared by
75
+ both lanes. An upload response may omit `Attachment.url`; the canonical chat
76
+ message echo is the first required server-URL carrier.
77
+
78
+ ## Provisioned chat recovery
79
+
80
+ - `joinSession({channel:'chat', ..., chat:{recovery}})` is the only provisioned
81
+ recovery opt-in. `recovery` requires `replay:'server'`, an explicit 1–8 entry
82
+ finite non-negative `delaysMs` schedule, and caller-owned `reauthorize`.
83
+ - Recoverable transport error, clean FIN, `stream_overflow`, and an
84
+ unauthenticated Attach serialize through that callback. Every invocation
85
+ carries the original `sessionId`, one-based attempt, monotonic generation,
86
+ and cause. A successful result must be a fresh `{sessionId,url,token}` for
87
+ that exact same session; a changed id, empty credential, or late generation
88
+ fails closed and is never attached.
89
+ - `reauthorize` owns the authenticated monitor start request. The SDK never
90
+ calls visitor `POST /session/start` or `GET /session/:id` in provisioned
91
+ recovery. Attach is the authoritative full server replay; existing message
92
+ ids dedupe replay/live overlap while preserving stream order.
93
+ - A callback may return `{terminal:'ended'|'revoked'|'removed'|'capacity'}`.
94
+ These, terminal Attach refusals, and exhausted schedules stop recovery.
95
+ Participant/audience typing watchdogs clear independently at each transport
96
+ boundary and terminal. Leave is sent only for a live Attach; after an in-band
97
+ `sessionEnded`, local close emits no Leave.
98
+ - Omitting `chat.recovery` preserves ordinary visitor behavior exactly,
99
+ including overflow history reconciliation and same-id visitor re-mint.
40
100
 
41
101
  ## Provisioned receive-only voice join
42
102
 
@@ -12,8 +12,8 @@ arms that descriptor carries.
12
12
  | Direction | RPC (`chat.v1.Session/…`) | Payload |
13
13
  |-----------|-------------------------------|---------|
14
14
  | attach | `Attach` (server-streaming) | initial `AttachResponse {participantId, role}`, then one `ChatEvent` per frame |
15
- | send | `Message` (unary) | `MessageRequest {clientMessageId, text?, html?, attachments, value?, galleryLabel?}` → the canonical `Message` echo |
16
- | typing | `Typing` (unary) | `TypingRequest {state: "on"\|"off"}` |
15
+ | send | `Message` (unary) | `MessageRequest {clientMessageId, text?, html?, attachments, value?, galleryLabel?, metadata:{audience}}` → the canonical `Message` echo |
16
+ | typing | `Typing` (unary) | `TypingRequest {state: "on"\|"off", metadata:{audience}}` |
17
17
  | leave | `Leave` (unary) | empty; immediate server-side finalize |
18
18
 
19
19
  `ChatEvent` is a oneof: `message`, `typing`, `participant_joined`,
@@ -22,6 +22,21 @@ arms that descriptor carries.
22
22
  it does not know — is consumed and dropped. That tolerance is the
23
23
  forward-compat contract.
24
24
 
25
+ The live-monitoring metadata is a deliberate hardcut: every `Message`,
26
+ `MessageRequest`, `TypingRequest`, and `TypingEvent` carries audience
27
+ `internal|all`. Missing/unknown audience fails closed. Ordinary visitor sends
28
+ inject `all`; monitor callers can select `internal`. The public typing callback
29
+ is the participant-aware `{participantId, role, userId, userName, state,
30
+ metadata}` object, and watchdog state is keyed by participant.
31
+
32
+ Provisioned monitor recovery is an SDK control seam, not a new wire arm. With
33
+ `joinSession(... chat.recovery)`, transport error/FIN/overflow triggers a
34
+ caller-owned reauthorization request followed by a fresh Attach. Attach replays
35
+ the authoritative full transcript; the client never substitutes visitor
36
+ history/start APIs. Existing message ids dedupe replay/live overlap, while the
37
+ stream retains canonical sequence order. Ordinary visitor overflow recovery is
38
+ unchanged.
39
+
25
40
  ## The extension rule: proto arms first
26
41
 
27
42
  **A chat feature does not exist until it has a proto arm.** The path for
@@ -80,7 +95,7 @@ default). Mapping vs. the legacy chat-sdk:
80
95
  `sendMessage`'s wire carrier is `MessageRequest`:
81
96
  `clientMessageId` (SDK-minted idempotency key), `text`, `html`,
82
97
  `attachments` (ids/names only — URLs are server-assigned on the echo),
83
- `value`, `galleryLabel`. The public payload surface also accepts the local
98
+ `value`, `galleryLabel`, and required `metadata`. The public payload surface also accepts the local
84
99
  typed `buttonReply {value,label?}` adapter and maps it to those two top-level
85
100
  wire fields; the nested adapter never rides ORPC. Two other local-only fields
86
101
  are stripped before send: `role` (the provisional-row hint) and
@@ -89,3 +104,6 @@ SSE-era fields with no wire carrier (`type`/`results`/`meta`/`context`/
89
104
  `createSystem`/`mode`) were deleted with 0.5.0 (owner decision,
90
105
  2026-08-07) — a new outbound field starts with a proto arm, per the
91
106
  extension rule above.
107
+
108
+ Accordingly, the public `Attachment.url` is optional on provisional/upload
109
+ responses and becomes authoritative only on the canonical message echo.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@origonai/web-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Origon Web SDK - chat and voice session client",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.5.1",