@pam-ai/pam-ordo-contracts 3.27.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -178,6 +178,30 @@ export interface paths {
178
178
  patch?: never;
179
179
  trace?: never;
180
180
  };
181
+ "/v1/inbox/conversations/{conversationId}/interactions/{interactionId}/attachments/{attachmentId}/url": {
182
+ parameters: {
183
+ query?: never;
184
+ header?: never;
185
+ path?: never;
186
+ cookie?: never;
187
+ };
188
+ /**
189
+ * Mint a short-lived URL for one attachment's bytes
190
+ * @description Exchange an attachment identifier for a URL a browser can fetch.
191
+ * WHY THIS IS NOT ON THE INTERACTION READ. A Conversation's detail read returns every Interaction it has, and hydrates bodies under a budget it can exhaust. Minting a storage credential for every attachment on every one of those reads would spend that budget on media nobody scrolls to, and would put an expiring secret inside a response a client is entitled to hold. So the attachment travels with the Interaction and the credential is asked for separately, once, by a reader that is about to show it.
192
+ * ADDRESSED THROUGH ITS CONVERSATION because that is what authorizes it. The same visibility rule as the Conversation detail read applies: a reader who cannot see the Conversation cannot mint a URL for anything inside it, and the attachment identifier alone is not a grant.
193
+ * NOT A REDIRECT TO THE BYTES. It returns the URL as data so a client can see the expiry, decide whether to re-read, and fetch on its own terms — rather than following a redirect it cannot inspect from an `img` tag.
194
+ * EXPECT TO CALL IT AGAIN. The URL lapses; the attachment does not. A client that has held one past `expiresAt`, or that is refused by the storage host, re-reads here rather than reporting a failure.
195
+ */
196
+ get: operations["getInboxInteractionAttachmentUrl"];
197
+ put?: never;
198
+ post?: never;
199
+ delete?: never;
200
+ options?: never;
201
+ head?: never;
202
+ patch?: never;
203
+ trace?: never;
204
+ };
181
205
  "/v1/inbox/contacts": {
182
206
  parameters: {
183
207
  query?: never;
@@ -1131,6 +1155,42 @@ export interface components {
1131
1155
  /** @description Concrete eligible Users, deduplicated across every requested target. */
1132
1156
  users: components["schemas"]["InboxTargetResolutionUserV1"][];
1133
1157
  };
1158
+ /** @description A source-qualified staff identity. The external ID is meaningful only inside the named source system and provider; it is never a PAM User ID and must not be resolved through a display name. */
1159
+ SourceUserIdentityV1: {
1160
+ sourceSystem: string;
1161
+ sourceProvider: string;
1162
+ externalUserId: string;
1163
+ };
1164
+ /**
1165
+ * @description resolved identifies one currently eligible rooftop User. unmapped means no active binding exists. ineligible means the binding exists but its User is inactive, outside the rooftop, or lacks the required Inbox capabilities. ambiguous is a fail-closed integrity result for multiple active bindings. Authority outages fail the request instead of being misreported as an identity result.
1166
+ * @enum {string}
1167
+ */
1168
+ SourceUserResolutionStatusV1: "resolved" | "unmapped" | "ineligible" | "ambiguous";
1169
+ SourceUserResolutionResultV1: {
1170
+ identity: components["schemas"]["SourceUserIdentityV1"];
1171
+ /** @constant */
1172
+ status: "resolved";
1173
+ userId: string;
1174
+ } | {
1175
+ identity: components["schemas"]["SourceUserIdentityV1"];
1176
+ /** @enum {string} */
1177
+ status: "unmapped" | "ineligible" | "ambiguous";
1178
+ userId: null;
1179
+ };
1180
+ SourceUserResolutionRequestV1: {
1181
+ /** @constant */
1182
+ schemaVersion: 1;
1183
+ clientOrgId: string;
1184
+ identities: components["schemas"]["SourceUserIdentityV1"][];
1185
+ };
1186
+ SourceUserResolutionResponseV1: {
1187
+ /** @constant */
1188
+ schemaVersion: 1;
1189
+ clientOrgId: string;
1190
+ results: components["schemas"]["SourceUserResolutionResultV1"][];
1191
+ /** @description Concrete eligible Users, deduplicated across every requested source identity. */
1192
+ users: components["schemas"]["InboxTargetResolutionUserV1"][];
1193
+ };
1134
1194
  /** @description Read-time state specific to the authenticated viewer. */
1135
1195
  ViewerState: {
1136
1196
  unreadCount: number;
@@ -1364,8 +1424,52 @@ export interface components {
1364
1424
  /** Format: date-time */
1365
1425
  occurredAt: string;
1366
1426
  body?: components["schemas"]["HydratedText"] | null;
1427
+ /**
1428
+ * @description Media carried by this Interaction — the photo of the damage, the insurance document, the voice note. Before this field an Interaction could say what was written and never that anything was attached, so a reader saw an empty bubble where a Customer had sent a picture.
1429
+ * ABSENT AND EMPTY MEAN THE SAME THING and a consumer must not distinguish them. Optional only to keep this addition a minor version; a producer that predates DASH-342 simply omits it.
1430
+ * AN UNATTACHED INTERACTION IS THE ORDINARY CASE. Most SMS carries no media, and every call, RO event and internal comment carries none by construction, so an empty list is not a hydration gap. A gap is reported the way every other one is, on the attachment's own `availability`.
1431
+ * CARRIES NO URL, deliberately. Minting a fetch credential for every attachment on every read spends the hydration budget on media nobody scrolls to, and bakes an expiry into a response a client may cache. A reader asks for one attachment's URL when it is about to show that attachment.
1432
+ */
1433
+ attachments?: components["schemas"]["InteractionAttachmentV1"][];
1434
+ availability: components["schemas"]["Availability"];
1435
+ };
1436
+ /**
1437
+ * @description One piece of media on an Interaction, described well enough to render a card for it without fetching a byte.
1438
+ * THE KIND IS PUBLISHED RATHER THAN DERIVED. A consumer that classifies media by testing whether its content type starts with `image/` shows a download chip for a photograph the moment a provider omits the type or sends `application/octet-stream`, which it does routinely. The system that mastered the record knows the filename and the source as well as the declared type, so it decides once, here, and every consumer agrees.
1439
+ */
1440
+ InteractionAttachmentV1: {
1441
+ /**
1442
+ * Format: uuid
1443
+ * @description Stable identifier for this attachment, addressable at the attachment-url read. Stable across reads of the same Interaction so a client may cache against it, and opaque, so the storage key it resolves to is never published to a browser.
1444
+ */
1445
+ id: string;
1446
+ /**
1447
+ * @description How to present it. FILE is the honest answer for anything with no inline player — a PDF, a contact card — and also for media whose type could not be determined, which renders as a named file rather than as a broken image.
1448
+ * @enum {string}
1449
+ */
1450
+ kind: "IMAGE" | "VIDEO" | "AUDIO" | "FILE";
1451
+ /** @description The declared MIME type, or null when the source recorded none. That null is why `kind` exists, and `kind` is not derived from this. */
1452
+ contentType?: string | null;
1453
+ /** @description Original filename, when the source recorded one. */
1454
+ fileName?: string | null;
1455
+ /** @description Size in bytes, when the source recorded one. */
1456
+ byteSize?: number | null;
1457
+ /** @description Whether this attachment can currently be fetched. One whose stored object has aged out, or whose metadata predates the storage key, is present and unavailable rather than absent: a reader must be able to say that something was sent and cannot be shown, which is a different thing from nothing having been sent. */
1367
1458
  availability: components["schemas"]["Availability"];
1368
1459
  };
1460
+ /**
1461
+ * @description A short-lived authorized URL for one attachment's bytes.
1462
+ * DELIBERATELY SHORT-LIVED, AND DELIBERATELY NOT PART OF THE INTERACTION READ. The URL is a credential: whoever holds it can fetch the bytes without passing back through this API. A client reads it when it is about to show the attachment rather than storing it, and treats a rejection from the storage host as "ask again" rather than as an error to show somebody.
1463
+ */
1464
+ InteractionAttachmentUrlV1: {
1465
+ /** @description Fetch the bytes from here. Do not persist it. */
1466
+ url: string;
1467
+ /**
1468
+ * Format: date-time
1469
+ * @description When the URL stops working. Published so a client can re-read before it lapses rather than discovering the expiry as a failed image load.
1470
+ */
1471
+ expiresAt: string;
1472
+ };
1369
1473
  MentionRef: {
1370
1474
  /** Format: uuid */
1371
1475
  id: string;
@@ -1685,6 +1789,8 @@ export interface components {
1685
1789
  senderUserExternalId?: string;
1686
1790
  /** @enum {string} */
1687
1791
  lineType?: "pam" | "rooftop" | "advisor";
1792
+ /** @description Verified recipient advisor User for an inbound Customer SMS to an advisor-owned line. This is not the sender and must be resolved within clientOrgId before routing. */
1793
+ recipientUserExternalId?: string;
1688
1794
  dynamoLocator?: components["schemas"]["ProducerDynamoLocatorV1"];
1689
1795
  };
1690
1796
  ProducerRepairOrderTransitionV1: {
@@ -1701,6 +1807,7 @@ export interface components {
1701
1807
  /** Format: uuid */
1702
1808
  customerId: string;
1703
1809
  advisorUserId?: string | null;
1810
+ advisorIdentity?: components["schemas"]["SourceUserIdentityV1"];
1704
1811
  sourceEventId: string;
1705
1812
  /** Format: date-time */
1706
1813
  sourceOccurredAt: string;
@@ -2340,6 +2447,16 @@ export interface components {
2340
2447
  "application/json": components["schemas"]["CommandResult"];
2341
2448
  };
2342
2449
  };
2450
+ /** @description A short-lived authorized URL for the attachment's bytes. */
2451
+ InteractionAttachmentUrlIssued: {
2452
+ headers: {
2453
+ "x-correlation-id": components["headers"]["CorrelationId"];
2454
+ [name: string]: unknown;
2455
+ };
2456
+ content: {
2457
+ "application/json": components["schemas"]["InteractionAttachmentUrlV1"];
2458
+ };
2459
+ };
2343
2460
  /** @description Applied or idempotently replayed internal-comment result. */
2344
2461
  InternalCommentApplied: {
2345
2462
  headers: {
@@ -2507,6 +2624,8 @@ export interface components {
2507
2624
  /** @description Authorized rooftop context. For commands this value must match body.clientOrgId; neither value is trusted without DASH-233 resolution. */
2508
2625
  ClientOrgId: string;
2509
2626
  ConversationId: string;
2627
+ InteractionId: string;
2628
+ AttachmentId: string;
2510
2629
  StaffUserId: string;
2511
2630
  };
2512
2631
  requestBodies: {
@@ -2998,6 +3117,32 @@ export interface operations {
2998
3117
  503: components["responses"]["ServiceUnavailable"];
2999
3118
  };
3000
3119
  };
3120
+ getInboxInteractionAttachmentUrl: {
3121
+ parameters: {
3122
+ query?: never;
3123
+ header: {
3124
+ /** @description Authorized rooftop context. For commands this value must match body.clientOrgId; neither value is trusted without DASH-233 resolution. */
3125
+ "x-client-org-id": components["parameters"]["ClientOrgId"];
3126
+ };
3127
+ path: {
3128
+ conversationId: components["parameters"]["ConversationId"];
3129
+ interactionId: components["parameters"]["InteractionId"];
3130
+ attachmentId: components["parameters"]["AttachmentId"];
3131
+ };
3132
+ cookie?: never;
3133
+ };
3134
+ requestBody?: never;
3135
+ responses: {
3136
+ 200: components["responses"]["InteractionAttachmentUrlIssued"];
3137
+ 400: components["responses"]["BadRequest"];
3138
+ 401: components["responses"]["Unauthorized"];
3139
+ 403: components["responses"]["Forbidden"];
3140
+ 404: components["responses"]["NotFound"];
3141
+ 500: components["responses"]["InternalError"];
3142
+ 501: components["responses"]["NotImplemented"];
3143
+ 503: components["responses"]["ServiceUnavailable"];
3144
+ };
3145
+ };
3001
3146
  searchInboxContacts: {
3002
3147
  parameters: {
3003
3148
  query?: {