@canonmsg/backend-contracts 5.4.1 → 6.1.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.
- package/dist/apiErrors.d.ts +1 -0
- package/dist/apiErrors.js +1 -0
- package/dist/canon-verbs.limits.json +2 -1
- package/dist/canon-verbs.schema.json +24 -1
- package/dist/cjs/apiErrors.js +4 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/media.js +25 -0
- package/dist/cjs/verbContract.js +2 -0
- package/dist/cjs/verbSchemas.js +12 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/media.d.ts +15 -0
- package/dist/media.js +25 -0
- package/dist/verbContract.d.ts +10 -1
- package/dist/verbContract.js +2 -0
- package/dist/verbSchemas.d.ts +15 -0
- package/dist/verbSchemas.js +12 -1
- package/package.json +2 -2
- package/dist/cjs/contactSources.js +0 -45
- package/dist/contactSources.d.ts +0 -31
- package/dist/contactSources.js +0 -41
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const MESSAGE_ADMISSION_REQUIRED_CODE: "MESSAGE_ADMISSION_REQUIRED";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MESSAGE_ADMISSION_REQUIRED_CODE = 'MESSAGE_ADMISSION_REQUIRED';
|
|
@@ -64,7 +64,8 @@
|
|
|
64
64
|
"runtimeOptionValue": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
|
|
65
65
|
"workspaceOptionId": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
|
|
66
66
|
"runtimeHandleKey": "^[A-Za-z0-9_.:-]{1,80}$",
|
|
67
|
-
"runtimeControlId": "^[A-Za-z0-9_-]{1,80}$"
|
|
67
|
+
"runtimeControlId": "^[A-Za-z0-9_-]{1,80}$",
|
|
68
|
+
"resumableUploadId": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
|
|
68
69
|
},
|
|
69
70
|
"byteSemantics": {
|
|
70
71
|
"send_to.text": "utf8_bytes<=messageTextBytes",
|
|
@@ -107,7 +107,12 @@
|
|
|
107
107
|
"url": {
|
|
108
108
|
"type": "string",
|
|
109
109
|
"minLength": 1,
|
|
110
|
-
"description": "Must come from
|
|
110
|
+
"description": "Must come from a canonical Canon upload/finalization response or the GIF picker — server allowlist, fail-closed (functions/src/utils/mediaUploadSafety.ts)."
|
|
111
|
+
},
|
|
112
|
+
"uploadId": {
|
|
113
|
+
"type": "string",
|
|
114
|
+
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
|
|
115
|
+
"description": "Server-issued resumable identity. Preserve it from finalization so the durable message transaction can validate and retain initially temporary media."
|
|
111
116
|
},
|
|
112
117
|
"mimeType": {
|
|
113
118
|
"type": "string"
|
|
@@ -130,6 +135,24 @@
|
|
|
130
135
|
"durationMs": {
|
|
131
136
|
"type": "number",
|
|
132
137
|
"minimum": 0
|
|
138
|
+
},
|
|
139
|
+
"thumbnailUrl": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"minLength": 1
|
|
142
|
+
},
|
|
143
|
+
"processingStatus": {
|
|
144
|
+
"enum": [
|
|
145
|
+
"processing",
|
|
146
|
+
"ready",
|
|
147
|
+
"failed"
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
"processingErrorCode": {
|
|
151
|
+
"enum": [
|
|
152
|
+
"invalid_video",
|
|
153
|
+
"video_limits_exceeded",
|
|
154
|
+
"video_processing_failed"
|
|
155
|
+
]
|
|
133
156
|
}
|
|
134
157
|
}
|
|
135
158
|
},
|
package/dist/cjs/index.js
CHANGED
|
@@ -24,11 +24,11 @@ __exportStar(require("./turnProtocol.js"), exports);
|
|
|
24
24
|
__exportStar(require("./agentBehaviorPolicy.js"), exports);
|
|
25
25
|
__exportStar(require("./agentSearch.js"), exports);
|
|
26
26
|
__exportStar(require("./contactRequest.js"), exports);
|
|
27
|
-
__exportStar(require("./contactSources.js"), exports);
|
|
28
27
|
__exportStar(require("./verbContract.js"), exports);
|
|
29
28
|
__exportStar(require("./verbSchemas.js"), exports);
|
|
30
29
|
__exportStar(require("./verbWire.js"), exports);
|
|
31
30
|
__exportStar(require("./accessPolicy.js"), exports);
|
|
31
|
+
__exportStar(require("./apiErrors.js"), exports);
|
|
32
32
|
__exportStar(require("./firestoreValues.js"), exports);
|
|
33
33
|
__exportStar(require("./moderation.js"), exports);
|
|
34
34
|
__exportStar(require("./selfContext.js"), exports);
|
package/dist/cjs/media.js
CHANGED
|
@@ -83,19 +83,44 @@ function normalizeStoredAttachments(value) {
|
|
|
83
83
|
if (typeof candidate.url !== 'string' || candidate.url.length === 0) {
|
|
84
84
|
return null;
|
|
85
85
|
}
|
|
86
|
+
if (candidate.uploadId !== undefined
|
|
87
|
+
&& (typeof candidate.uploadId !== 'string'
|
|
88
|
+
|| !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(candidate.uploadId))) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
86
91
|
const sizeBytes = normalizeAttachmentNumber(candidate.sizeBytes);
|
|
87
92
|
const width = normalizeAttachmentNumber(candidate.width);
|
|
88
93
|
const height = normalizeAttachmentNumber(candidate.height);
|
|
89
94
|
const durationMs = normalizeAttachmentNumber(candidate.durationMs);
|
|
95
|
+
const processingStatus = candidate.processingStatus;
|
|
96
|
+
if (processingStatus !== undefined
|
|
97
|
+
&& processingStatus !== 'processing'
|
|
98
|
+
&& processingStatus !== 'ready'
|
|
99
|
+
&& processingStatus !== 'failed') {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const processingErrorCode = candidate.processingErrorCode;
|
|
103
|
+
if (processingErrorCode !== undefined
|
|
104
|
+
&& processingErrorCode !== 'invalid_video'
|
|
105
|
+
&& processingErrorCode !== 'video_limits_exceeded'
|
|
106
|
+
&& processingErrorCode !== 'video_processing_failed') {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
90
109
|
attachments.push({
|
|
91
110
|
kind: candidate.kind,
|
|
92
111
|
url: candidate.url,
|
|
112
|
+
...(candidate.uploadId ? { uploadId: candidate.uploadId } : {}),
|
|
93
113
|
...(typeof candidate.mimeType === 'string' && candidate.mimeType ? { mimeType: candidate.mimeType } : {}),
|
|
94
114
|
...(typeof candidate.fileName === 'string' && candidate.fileName ? { fileName: candidate.fileName } : {}),
|
|
95
115
|
...(sizeBytes !== undefined ? { sizeBytes } : {}),
|
|
96
116
|
...(width !== undefined ? { width } : {}),
|
|
97
117
|
...(height !== undefined ? { height } : {}),
|
|
98
118
|
...(durationMs !== undefined ? { durationMs } : {}),
|
|
119
|
+
...(typeof candidate.thumbnailUrl === 'string' && candidate.thumbnailUrl
|
|
120
|
+
? { thumbnailUrl: candidate.thumbnailUrl }
|
|
121
|
+
: {}),
|
|
122
|
+
...(processingStatus !== undefined ? { processingStatus } : {}),
|
|
123
|
+
...(processingErrorCode !== undefined ? { processingErrorCode } : {}),
|
|
99
124
|
});
|
|
100
125
|
}
|
|
101
126
|
return attachments.length > 0 ? attachments : [];
|
package/dist/cjs/verbContract.js
CHANGED
|
@@ -82,6 +82,8 @@ exports.VERB_ID_PATTERNS = {
|
|
|
82
82
|
workspaceOptionId: '^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$',
|
|
83
83
|
runtimeHandleKey: '^[A-Za-z0-9_.:-]{1,80}$',
|
|
84
84
|
runtimeControlId: '^[A-Za-z0-9_-]{1,80}$',
|
|
85
|
+
/** UUID issued by Canon's resumable-media session endpoint. */
|
|
86
|
+
resumableUploadId: '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$',
|
|
85
87
|
};
|
|
86
88
|
/**
|
|
87
89
|
* Server-enforced limits, single-sourced. Each value cites its enforcement
|
package/dist/cjs/verbSchemas.js
CHANGED
|
@@ -93,15 +93,26 @@ const mediaAttachmentDef = {
|
|
|
93
93
|
url: {
|
|
94
94
|
type: 'string',
|
|
95
95
|
minLength: 1,
|
|
96
|
-
description: 'Must come from
|
|
96
|
+
description: 'Must come from a canonical Canon upload/finalization response or the GIF picker — server '
|
|
97
97
|
+ 'allowlist, fail-closed (functions/src/utils/mediaUploadSafety.ts).',
|
|
98
98
|
},
|
|
99
|
+
uploadId: {
|
|
100
|
+
type: 'string',
|
|
101
|
+
pattern: verbContract_js_1.VERB_ID_PATTERNS.resumableUploadId,
|
|
102
|
+
description: 'Server-issued resumable identity. Preserve it from finalization so the durable message '
|
|
103
|
+
+ 'transaction can validate and retain initially temporary media.',
|
|
104
|
+
},
|
|
99
105
|
mimeType: { type: 'string' },
|
|
100
106
|
fileName: { type: 'string' },
|
|
101
107
|
sizeBytes: { type: 'number', minimum: 0 },
|
|
102
108
|
width: { type: 'number', minimum: 0 },
|
|
103
109
|
height: { type: 'number', minimum: 0 },
|
|
104
110
|
durationMs: { type: 'number', minimum: 0 },
|
|
111
|
+
thumbnailUrl: { type: 'string', minLength: 1 },
|
|
112
|
+
processingStatus: { enum: ['processing', 'ready', 'failed'] },
|
|
113
|
+
processingErrorCode: {
|
|
114
|
+
enum: ['invalid_video', 'video_limits_exceeded', 'video_processing_failed'],
|
|
115
|
+
},
|
|
105
116
|
},
|
|
106
117
|
};
|
|
107
118
|
const turnMetadataDef = {
|
package/dist/index.d.ts
CHANGED
|
@@ -8,11 +8,11 @@ export * from './turnProtocol.js';
|
|
|
8
8
|
export * from './agentBehaviorPolicy.js';
|
|
9
9
|
export * from './agentSearch.js';
|
|
10
10
|
export * from './contactRequest.js';
|
|
11
|
-
export * from './contactSources.js';
|
|
12
11
|
export * from './verbContract.js';
|
|
13
12
|
export * from './verbSchemas.js';
|
|
14
13
|
export * from './verbWire.js';
|
|
15
14
|
export * from './accessPolicy.js';
|
|
15
|
+
export * from './apiErrors.js';
|
|
16
16
|
export * from './firestoreValues.js';
|
|
17
17
|
export * from './moderation.js';
|
|
18
18
|
export * from './selfContext.js';
|
package/dist/index.js
CHANGED
|
@@ -8,11 +8,11 @@ export * from './turnProtocol.js';
|
|
|
8
8
|
export * from './agentBehaviorPolicy.js';
|
|
9
9
|
export * from './agentSearch.js';
|
|
10
10
|
export * from './contactRequest.js';
|
|
11
|
-
export * from './contactSources.js';
|
|
12
11
|
export * from './verbContract.js';
|
|
13
12
|
export * from './verbSchemas.js';
|
|
14
13
|
export * from './verbWire.js';
|
|
15
14
|
export * from './accessPolicy.js';
|
|
15
|
+
export * from './apiErrors.js';
|
|
16
16
|
export * from './firestoreValues.js';
|
|
17
17
|
export * from './moderation.js';
|
|
18
18
|
export * from './selfContext.js';
|
package/dist/media.d.ts
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
export type MediaAttachmentKind = 'image' | 'audio' | 'video' | 'file';
|
|
2
|
+
/** Lifecycle for newly uploaded videos that are normalized server-side. */
|
|
3
|
+
export type VideoProcessingStatus = 'processing' | 'ready' | 'failed';
|
|
4
|
+
/** Stable, display-safe reasons for a terminal video processing failure. */
|
|
5
|
+
export type VideoProcessingErrorCode = 'invalid_video' | 'video_limits_exceeded' | 'video_processing_failed';
|
|
2
6
|
export interface MediaAttachment {
|
|
3
7
|
kind: MediaAttachmentKind;
|
|
4
8
|
url: string;
|
|
9
|
+
/**
|
|
10
|
+
* Server-issued identity for a finalized resumable upload. The send path
|
|
11
|
+
* uses this to retain temporary canonical media atomically with the message.
|
|
12
|
+
* Legacy/base64 uploads intentionally omit it.
|
|
13
|
+
*/
|
|
14
|
+
uploadId?: string;
|
|
5
15
|
mimeType?: string;
|
|
6
16
|
fileName?: string;
|
|
7
17
|
sizeBytes?: number;
|
|
8
18
|
width?: number;
|
|
9
19
|
height?: number;
|
|
10
20
|
durationMs?: number;
|
|
21
|
+
/** Server-generated poster for a normalized video. */
|
|
22
|
+
thumbnailUrl?: string;
|
|
23
|
+
/** Missing means a legacy attachment that is immediately playable. */
|
|
24
|
+
processingStatus?: VideoProcessingStatus;
|
|
25
|
+
processingErrorCode?: VideoProcessingErrorCode;
|
|
11
26
|
}
|
|
12
27
|
export declare function inferMediaAttachmentKind(mimeType: string): MediaAttachmentKind;
|
|
13
28
|
export declare function getStoredFileExtension(input: {
|
package/dist/media.js
CHANGED
|
@@ -75,19 +75,44 @@ export function normalizeStoredAttachments(value) {
|
|
|
75
75
|
if (typeof candidate.url !== 'string' || candidate.url.length === 0) {
|
|
76
76
|
return null;
|
|
77
77
|
}
|
|
78
|
+
if (candidate.uploadId !== undefined
|
|
79
|
+
&& (typeof candidate.uploadId !== 'string'
|
|
80
|
+
|| !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(candidate.uploadId))) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
78
83
|
const sizeBytes = normalizeAttachmentNumber(candidate.sizeBytes);
|
|
79
84
|
const width = normalizeAttachmentNumber(candidate.width);
|
|
80
85
|
const height = normalizeAttachmentNumber(candidate.height);
|
|
81
86
|
const durationMs = normalizeAttachmentNumber(candidate.durationMs);
|
|
87
|
+
const processingStatus = candidate.processingStatus;
|
|
88
|
+
if (processingStatus !== undefined
|
|
89
|
+
&& processingStatus !== 'processing'
|
|
90
|
+
&& processingStatus !== 'ready'
|
|
91
|
+
&& processingStatus !== 'failed') {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const processingErrorCode = candidate.processingErrorCode;
|
|
95
|
+
if (processingErrorCode !== undefined
|
|
96
|
+
&& processingErrorCode !== 'invalid_video'
|
|
97
|
+
&& processingErrorCode !== 'video_limits_exceeded'
|
|
98
|
+
&& processingErrorCode !== 'video_processing_failed') {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
82
101
|
attachments.push({
|
|
83
102
|
kind: candidate.kind,
|
|
84
103
|
url: candidate.url,
|
|
104
|
+
...(candidate.uploadId ? { uploadId: candidate.uploadId } : {}),
|
|
85
105
|
...(typeof candidate.mimeType === 'string' && candidate.mimeType ? { mimeType: candidate.mimeType } : {}),
|
|
86
106
|
...(typeof candidate.fileName === 'string' && candidate.fileName ? { fileName: candidate.fileName } : {}),
|
|
87
107
|
...(sizeBytes !== undefined ? { sizeBytes } : {}),
|
|
88
108
|
...(width !== undefined ? { width } : {}),
|
|
89
109
|
...(height !== undefined ? { height } : {}),
|
|
90
110
|
...(durationMs !== undefined ? { durationMs } : {}),
|
|
111
|
+
...(typeof candidate.thumbnailUrl === 'string' && candidate.thumbnailUrl
|
|
112
|
+
? { thumbnailUrl: candidate.thumbnailUrl }
|
|
113
|
+
: {}),
|
|
114
|
+
...(processingStatus !== undefined ? { processingStatus } : {}),
|
|
115
|
+
...(processingErrorCode !== undefined ? { processingErrorCode } : {}),
|
|
91
116
|
});
|
|
92
117
|
}
|
|
93
118
|
return attachments.length > 0 ? attachments : [];
|
package/dist/verbContract.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ export declare const VERB_ID_PATTERNS: {
|
|
|
77
77
|
readonly workspaceOptionId: "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$";
|
|
78
78
|
readonly runtimeHandleKey: "^[A-Za-z0-9_.:-]{1,80}$";
|
|
79
79
|
readonly runtimeControlId: "^[A-Za-z0-9_-]{1,80}$";
|
|
80
|
+
/** UUID issued by Canon's resumable-media session endpoint. */
|
|
81
|
+
readonly resumableUploadId: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$";
|
|
80
82
|
};
|
|
81
83
|
/**
|
|
82
84
|
* Server-enforced limits, single-sourced. Each value cites its enforcement
|
|
@@ -246,14 +248,19 @@ export declare const VERB_NATIVE_METADATA_KEYS: readonly ["runtime", "method", "
|
|
|
246
248
|
export declare function normalizeVerbNativeMetadata(value: unknown): VerbNativeMetadata | undefined;
|
|
247
249
|
export interface VerbMediaAttachment {
|
|
248
250
|
kind: 'image' | 'audio' | 'video' | 'file';
|
|
249
|
-
/** Must come from
|
|
251
|
+
/** Must come from a canonical Canon upload/finalization response or the GIF picker. */
|
|
250
252
|
url: string;
|
|
253
|
+
/** Server-issued resumable identity; preserve it so durable sends retain temporary media. */
|
|
254
|
+
uploadId?: string;
|
|
251
255
|
mimeType?: string;
|
|
252
256
|
fileName?: string;
|
|
253
257
|
sizeBytes?: number;
|
|
254
258
|
width?: number;
|
|
255
259
|
height?: number;
|
|
256
260
|
durationMs?: number;
|
|
261
|
+
thumbnailUrl?: string;
|
|
262
|
+
processingStatus?: 'processing' | 'ready' | 'failed';
|
|
263
|
+
processingErrorCode?: 'invalid_video' | 'video_limits_exceeded' | 'video_processing_failed';
|
|
257
264
|
}
|
|
258
265
|
/**
|
|
259
266
|
* Well-known turn-protocol keys inside the free-form metadata envelope
|
|
@@ -846,6 +853,8 @@ export declare const CANON_VERB_LIMITS_ARTIFACT: {
|
|
|
846
853
|
readonly workspaceOptionId: "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$";
|
|
847
854
|
readonly runtimeHandleKey: "^[A-Za-z0-9_.:-]{1,80}$";
|
|
848
855
|
readonly runtimeControlId: "^[A-Za-z0-9_-]{1,80}$";
|
|
856
|
+
/** UUID issued by Canon's resumable-media session endpoint. */
|
|
857
|
+
readonly resumableUploadId: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$";
|
|
849
858
|
};
|
|
850
859
|
readonly byteSemantics: {
|
|
851
860
|
readonly 'send_to.text': "utf8_bytes<=messageTextBytes";
|
package/dist/verbContract.js
CHANGED
|
@@ -76,6 +76,8 @@ export const VERB_ID_PATTERNS = {
|
|
|
76
76
|
workspaceOptionId: '^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$',
|
|
77
77
|
runtimeHandleKey: '^[A-Za-z0-9_.:-]{1,80}$',
|
|
78
78
|
runtimeControlId: '^[A-Za-z0-9_-]{1,80}$',
|
|
79
|
+
/** UUID issued by Canon's resumable-media session endpoint. */
|
|
80
|
+
resumableUploadId: '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$',
|
|
79
81
|
};
|
|
80
82
|
/**
|
|
81
83
|
* Server-enforced limits, single-sourced. Each value cites its enforcement
|
package/dist/verbSchemas.d.ts
CHANGED
|
@@ -253,6 +253,11 @@ export declare const CANON_VERBS_JSON_SCHEMA: {
|
|
|
253
253
|
readonly minLength: 1;
|
|
254
254
|
readonly description: string;
|
|
255
255
|
};
|
|
256
|
+
readonly uploadId: {
|
|
257
|
+
readonly type: "string";
|
|
258
|
+
readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$";
|
|
259
|
+
readonly description: string;
|
|
260
|
+
};
|
|
256
261
|
readonly mimeType: {
|
|
257
262
|
readonly type: "string";
|
|
258
263
|
};
|
|
@@ -275,6 +280,16 @@ export declare const CANON_VERBS_JSON_SCHEMA: {
|
|
|
275
280
|
readonly type: "number";
|
|
276
281
|
readonly minimum: 0;
|
|
277
282
|
};
|
|
283
|
+
readonly thumbnailUrl: {
|
|
284
|
+
readonly type: "string";
|
|
285
|
+
readonly minLength: 1;
|
|
286
|
+
};
|
|
287
|
+
readonly processingStatus: {
|
|
288
|
+
readonly enum: readonly ["processing", "ready", "failed"];
|
|
289
|
+
};
|
|
290
|
+
readonly processingErrorCode: {
|
|
291
|
+
readonly enum: readonly ["invalid_video", "video_limits_exceeded", "video_processing_failed"];
|
|
292
|
+
};
|
|
278
293
|
};
|
|
279
294
|
};
|
|
280
295
|
readonly turnMetadata: {
|
package/dist/verbSchemas.js
CHANGED
|
@@ -88,15 +88,26 @@ const mediaAttachmentDef = {
|
|
|
88
88
|
url: {
|
|
89
89
|
type: 'string',
|
|
90
90
|
minLength: 1,
|
|
91
|
-
description: 'Must come from
|
|
91
|
+
description: 'Must come from a canonical Canon upload/finalization response or the GIF picker — server '
|
|
92
92
|
+ 'allowlist, fail-closed (functions/src/utils/mediaUploadSafety.ts).',
|
|
93
93
|
},
|
|
94
|
+
uploadId: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
pattern: VERB_ID_PATTERNS.resumableUploadId,
|
|
97
|
+
description: 'Server-issued resumable identity. Preserve it from finalization so the durable message '
|
|
98
|
+
+ 'transaction can validate and retain initially temporary media.',
|
|
99
|
+
},
|
|
94
100
|
mimeType: { type: 'string' },
|
|
95
101
|
fileName: { type: 'string' },
|
|
96
102
|
sizeBytes: { type: 'number', minimum: 0 },
|
|
97
103
|
width: { type: 'number', minimum: 0 },
|
|
98
104
|
height: { type: 'number', minimum: 0 },
|
|
99
105
|
durationMs: { type: 'number', minimum: 0 },
|
|
106
|
+
thumbnailUrl: { type: 'string', minLength: 1 },
|
|
107
|
+
processingStatus: { enum: ['processing', 'ready', 'failed'] },
|
|
108
|
+
processingErrorCode: {
|
|
109
|
+
enum: ['invalid_video', 'video_limits_exceeded', 'video_processing_failed'],
|
|
110
|
+
},
|
|
100
111
|
},
|
|
101
112
|
};
|
|
102
113
|
const turnMetadataDef = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/backend-contracts",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Canon backend contract helpers shared by Functions and stream-service",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@canonmsg/rich-cards": "^0.10.
|
|
46
|
+
"@canonmsg/rich-cards": "^0.10.2",
|
|
47
47
|
"@types/node": "^22.0.0",
|
|
48
48
|
"ajv": "^8.20.0",
|
|
49
49
|
"typescript": "~5.7.0",
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ADMISSION_GRANTING_SOURCES = void 0;
|
|
4
|
-
exports.isAdmissionGrantingContactSource = isAdmissionGrantingContactSource;
|
|
5
|
-
/**
|
|
6
|
-
* Sources that represent a user-initiated relationship which grants admission
|
|
7
|
-
* past `inboundPolicy: 'approval-required'` and
|
|
8
|
-
* `groupJoinPolicy: 'approval-required'`.
|
|
9
|
-
*
|
|
10
|
-
* - `contact_request`: an explicit approval flow.
|
|
11
|
-
* - `direct_add`: the user added the other side directly.
|
|
12
|
-
* - `link` / `qr`: out-of-band invitations that imply consent.
|
|
13
|
-
* - `group`: established by being in a shared group.
|
|
14
|
-
* - `phone_book`: included intentionally — if a human has a registered Canon
|
|
15
|
-
* user in their device contacts, that is enough to start a human-human DM
|
|
16
|
-
* without a separate Canon request.
|
|
17
|
-
* - `open_inbound_message`: the unified source written when a delivered direct
|
|
18
|
-
* interaction reaches an `inboundPolicy: 'open'` recipient. The recipient
|
|
19
|
-
* consented to open inbound; the resulting mutual contact is real.
|
|
20
|
-
*
|
|
21
|
-
* Hard caps (`owner-only`, blocks, inactive agent) override admission grants
|
|
22
|
-
* regardless of source — ordering lives in `functions/src/utils/access.ts`
|
|
23
|
-
* (`evaluatePolicy` / `buildPolicyContext`).
|
|
24
|
-
*/
|
|
25
|
-
const ADMISSION_GRANTING_CONTACT_SOURCES = [
|
|
26
|
-
'contact_request',
|
|
27
|
-
'direct_add',
|
|
28
|
-
'link',
|
|
29
|
-
'qr',
|
|
30
|
-
'group',
|
|
31
|
-
'phone_book',
|
|
32
|
-
'open_inbound_message',
|
|
33
|
-
];
|
|
34
|
-
exports.ADMISSION_GRANTING_SOURCES = new Set(ADMISSION_GRANTING_CONTACT_SOURCES);
|
|
35
|
-
/**
|
|
36
|
-
* Returns true if a contact-doc source counts as an admission-granting
|
|
37
|
-
* relationship. `null` / `undefined` (no doc, or doc with a missing source)
|
|
38
|
-
* both return `false` — every contact doc must have an explicit source after
|
|
39
|
-
* the cleanup.
|
|
40
|
-
*/
|
|
41
|
-
function isAdmissionGrantingContactSource(source) {
|
|
42
|
-
if (source === null || source === undefined)
|
|
43
|
-
return false;
|
|
44
|
-
return exports.ADMISSION_GRANTING_SOURCES.has(source);
|
|
45
|
-
}
|
package/dist/contactSources.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sources that represent a user-initiated relationship which grants admission
|
|
3
|
-
* past `inboundPolicy: 'approval-required'` and
|
|
4
|
-
* `groupJoinPolicy: 'approval-required'`.
|
|
5
|
-
*
|
|
6
|
-
* - `contact_request`: an explicit approval flow.
|
|
7
|
-
* - `direct_add`: the user added the other side directly.
|
|
8
|
-
* - `link` / `qr`: out-of-band invitations that imply consent.
|
|
9
|
-
* - `group`: established by being in a shared group.
|
|
10
|
-
* - `phone_book`: included intentionally — if a human has a registered Canon
|
|
11
|
-
* user in their device contacts, that is enough to start a human-human DM
|
|
12
|
-
* without a separate Canon request.
|
|
13
|
-
* - `open_inbound_message`: the unified source written when a delivered direct
|
|
14
|
-
* interaction reaches an `inboundPolicy: 'open'` recipient. The recipient
|
|
15
|
-
* consented to open inbound; the resulting mutual contact is real.
|
|
16
|
-
*
|
|
17
|
-
* Hard caps (`owner-only`, blocks, inactive agent) override admission grants
|
|
18
|
-
* regardless of source — ordering lives in `functions/src/utils/access.ts`
|
|
19
|
-
* (`evaluatePolicy` / `buildPolicyContext`).
|
|
20
|
-
*/
|
|
21
|
-
declare const ADMISSION_GRANTING_CONTACT_SOURCES: readonly ["contact_request", "direct_add", "link", "qr", "group", "phone_book", "open_inbound_message"];
|
|
22
|
-
export type AdmissionGrantingContactSource = (typeof ADMISSION_GRANTING_CONTACT_SOURCES)[number];
|
|
23
|
-
export declare const ADMISSION_GRANTING_SOURCES: ReadonlySet<AdmissionGrantingContactSource>;
|
|
24
|
-
/**
|
|
25
|
-
* Returns true if a contact-doc source counts as an admission-granting
|
|
26
|
-
* relationship. `null` / `undefined` (no doc, or doc with a missing source)
|
|
27
|
-
* both return `false` — every contact doc must have an explicit source after
|
|
28
|
-
* the cleanup.
|
|
29
|
-
*/
|
|
30
|
-
export declare function isAdmissionGrantingContactSource(source: string | null | undefined): boolean;
|
|
31
|
-
export {};
|
package/dist/contactSources.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sources that represent a user-initiated relationship which grants admission
|
|
3
|
-
* past `inboundPolicy: 'approval-required'` and
|
|
4
|
-
* `groupJoinPolicy: 'approval-required'`.
|
|
5
|
-
*
|
|
6
|
-
* - `contact_request`: an explicit approval flow.
|
|
7
|
-
* - `direct_add`: the user added the other side directly.
|
|
8
|
-
* - `link` / `qr`: out-of-band invitations that imply consent.
|
|
9
|
-
* - `group`: established by being in a shared group.
|
|
10
|
-
* - `phone_book`: included intentionally — if a human has a registered Canon
|
|
11
|
-
* user in their device contacts, that is enough to start a human-human DM
|
|
12
|
-
* without a separate Canon request.
|
|
13
|
-
* - `open_inbound_message`: the unified source written when a delivered direct
|
|
14
|
-
* interaction reaches an `inboundPolicy: 'open'` recipient. The recipient
|
|
15
|
-
* consented to open inbound; the resulting mutual contact is real.
|
|
16
|
-
*
|
|
17
|
-
* Hard caps (`owner-only`, blocks, inactive agent) override admission grants
|
|
18
|
-
* regardless of source — ordering lives in `functions/src/utils/access.ts`
|
|
19
|
-
* (`evaluatePolicy` / `buildPolicyContext`).
|
|
20
|
-
*/
|
|
21
|
-
const ADMISSION_GRANTING_CONTACT_SOURCES = [
|
|
22
|
-
'contact_request',
|
|
23
|
-
'direct_add',
|
|
24
|
-
'link',
|
|
25
|
-
'qr',
|
|
26
|
-
'group',
|
|
27
|
-
'phone_book',
|
|
28
|
-
'open_inbound_message',
|
|
29
|
-
];
|
|
30
|
-
export const ADMISSION_GRANTING_SOURCES = new Set(ADMISSION_GRANTING_CONTACT_SOURCES);
|
|
31
|
-
/**
|
|
32
|
-
* Returns true if a contact-doc source counts as an admission-granting
|
|
33
|
-
* relationship. `null` / `undefined` (no doc, or doc with a missing source)
|
|
34
|
-
* both return `false` — every contact doc must have an explicit source after
|
|
35
|
-
* the cleanup.
|
|
36
|
-
*/
|
|
37
|
-
export function isAdmissionGrantingContactSource(source) {
|
|
38
|
-
if (source === null || source === undefined)
|
|
39
|
-
return false;
|
|
40
|
-
return ADMISSION_GRANTING_SOURCES.has(source);
|
|
41
|
-
}
|