@canonmsg/backend-contracts 7.0.0 → 8.0.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.
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readCanonicalPolicy = readCanonicalPolicy;
4
- /**
5
- * Read a stored policy field, defaulting to the value Canon assigns on account
6
- * creation. Anything unrecognized — missing, misspelled, or the retired
7
- * `'private'` enum — reads as 'approval-required'. This must never widen to
8
- * 'open'.
9
- */
10
- function readCanonicalPolicy(value) {
11
- if (value === 'open' || value === 'approval-required' || value === 'owner-only') {
12
- return value;
13
- }
14
- return 'approval-required';
15
- }
@@ -1,114 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readGroupInviteRequirements = readGroupInviteRequirements;
4
- exports.serializeContactRequest = serializeContactRequest;
5
- function readGroupInviteRequirements(value) {
6
- const record = isRecord(value) ? value : null;
7
- if (typeof record?.policyApproval !== 'boolean'
8
- || typeof record.ownerSessionSetup !== 'boolean') {
9
- throw new TypeError('Invalid group invite requirements');
10
- }
11
- return {
12
- policyApproval: record.policyApproval,
13
- ownerSessionSetup: record.ownerSessionSetup,
14
- };
15
- }
16
- function isRecord(value) {
17
- return typeof value === 'object' && value !== null && !Array.isArray(value);
18
- }
19
- function normalizeTimestamp(value) {
20
- if (value instanceof Date)
21
- return value.toISOString();
22
- if (isRecord(value) && typeof value.toDate === 'function') {
23
- const result = value.toDate();
24
- if (result instanceof Date)
25
- return result.toISOString();
26
- }
27
- return null;
28
- }
29
- function normalizeStatus(value) {
30
- if (value === 'pending'
31
- || value === 'approved'
32
- || value === 'rejected'
33
- || value === 'expired') {
34
- return value;
35
- }
36
- return 'pending';
37
- }
38
- function serializeContactRequest(requestId, data) {
39
- if (typeof data.approverId !== 'string' || data.approverId.length === 0) {
40
- return null;
41
- }
42
- if (typeof data.requesterId !== 'string' || data.requesterId.length === 0) {
43
- return null;
44
- }
45
- if (typeof data.targetId !== 'string' || data.targetId.length === 0) {
46
- return null;
47
- }
48
- if (typeof data.targetName !== 'string' || data.targetName.trim().length === 0) {
49
- return null;
50
- }
51
- if (data.targetAvatarUrl !== null && data.targetAvatarUrl !== undefined && typeof data.targetAvatarUrl !== 'string') {
52
- return null;
53
- }
54
- if (data.targetUserType !== 'human' && data.targetUserType !== 'ai_agent') {
55
- return null;
56
- }
57
- if (data.targetUserType === 'ai_agent'
58
- && (typeof data.targetOwnerId !== 'string' || data.targetOwnerId.length === 0)) {
59
- return null;
60
- }
61
- const kindValue = typeof data.kind === 'string' ? data.kind : null;
62
- if (kindValue !== 'dm' && kindValue !== 'group_invite') {
63
- return null;
64
- }
65
- let groupContext = null;
66
- if (kindValue === 'group_invite') {
67
- const ctx = isRecord(data.groupContext) ? data.groupContext : null;
68
- const conversationId = typeof ctx?.conversationId === 'string'
69
- ? ctx.conversationId.trim()
70
- : '';
71
- if (!conversationId) {
72
- return null;
73
- }
74
- groupContext = {
75
- conversationId,
76
- groupName: typeof ctx?.groupName === 'string' ? ctx.groupName : null,
77
- };
78
- }
79
- const payload = {
80
- id: requestId,
81
- requesterId: data.requesterId,
82
- requesterName: typeof data.requesterName === 'string' ? data.requesterName : 'Unknown',
83
- requesterAvatarUrl: typeof data.requesterAvatarUrl === 'string' ? data.requesterAvatarUrl : null,
84
- targetId: data.targetId,
85
- targetName: data.targetName.trim(),
86
- targetAvatarUrl: typeof data.targetAvatarUrl === 'string' ? data.targetAvatarUrl : null,
87
- targetUserType: data.targetUserType,
88
- approverId: data.approverId,
89
- // Free-form request content is owner-review material. This shared DTO is
90
- // delivered to the target agent over REST/SSE, so it must never cross the
91
- // admission boundary before the human approver accepts the reach-out.
92
- message: null,
93
- status: normalizeStatus(data.status),
94
- kind: kindValue,
95
- createdAt: normalizeTimestamp(data.createdAt),
96
- resolvedAt: normalizeTimestamp(data.resolvedAt),
97
- expiresAt: normalizeTimestamp(data.expiresAt),
98
- };
99
- if (groupContext) {
100
- let requirements;
101
- try {
102
- requirements = readGroupInviteRequirements(data.requirements);
103
- }
104
- catch {
105
- return null;
106
- }
107
- payload.groupContext = groupContext;
108
- payload.requirements = requirements;
109
- }
110
- if (data.targetUserType === 'ai_agent') {
111
- payload.targetOwnerId = data.targetOwnerId;
112
- }
113
- return payload;
114
- }
@@ -1,36 +0,0 @@
1
- export type SerializedContactRequestStatus = 'pending' | 'approved' | 'rejected' | 'expired';
2
- /**
3
- * Independent gates that must be satisfied before a pending group invite can
4
- * add its target.
5
- */
6
- export interface GroupInviteRequirements {
7
- policyApproval: boolean;
8
- ownerSessionSetup: boolean;
9
- }
10
- export declare function readGroupInviteRequirements(value: unknown): GroupInviteRequirements;
11
- export interface SerializedContactRequest {
12
- id: string;
13
- requesterId: string;
14
- requesterName: string;
15
- requesterAvatarUrl: string | null;
16
- targetId: string;
17
- targetName: string;
18
- targetAvatarUrl: string | null;
19
- targetUserType: 'human' | 'ai_agent';
20
- targetOwnerId?: string | null;
21
- approverId: string;
22
- /** Always null on agent-facing DTOs; free-form content stays in authorized review storage. */
23
- message: string | null;
24
- status: SerializedContactRequestStatus;
25
- kind: 'dm' | 'group_invite';
26
- groupContext?: {
27
- conversationId: string;
28
- groupName: string | null;
29
- };
30
- /** Present for group_invite payloads; omitted for DM requests. */
31
- requirements?: GroupInviteRequirements;
32
- createdAt: string | null;
33
- resolvedAt?: string | null;
34
- expiresAt?: string | null;
35
- }
36
- export declare function serializeContactRequest(requestId: string, data: Record<string, unknown>): SerializedContactRequest | null;
@@ -1,110 +0,0 @@
1
- export function readGroupInviteRequirements(value) {
2
- const record = isRecord(value) ? value : null;
3
- if (typeof record?.policyApproval !== 'boolean'
4
- || typeof record.ownerSessionSetup !== 'boolean') {
5
- throw new TypeError('Invalid group invite requirements');
6
- }
7
- return {
8
- policyApproval: record.policyApproval,
9
- ownerSessionSetup: record.ownerSessionSetup,
10
- };
11
- }
12
- function isRecord(value) {
13
- return typeof value === 'object' && value !== null && !Array.isArray(value);
14
- }
15
- function normalizeTimestamp(value) {
16
- if (value instanceof Date)
17
- return value.toISOString();
18
- if (isRecord(value) && typeof value.toDate === 'function') {
19
- const result = value.toDate();
20
- if (result instanceof Date)
21
- return result.toISOString();
22
- }
23
- return null;
24
- }
25
- function normalizeStatus(value) {
26
- if (value === 'pending'
27
- || value === 'approved'
28
- || value === 'rejected'
29
- || value === 'expired') {
30
- return value;
31
- }
32
- return 'pending';
33
- }
34
- export function serializeContactRequest(requestId, data) {
35
- if (typeof data.approverId !== 'string' || data.approverId.length === 0) {
36
- return null;
37
- }
38
- if (typeof data.requesterId !== 'string' || data.requesterId.length === 0) {
39
- return null;
40
- }
41
- if (typeof data.targetId !== 'string' || data.targetId.length === 0) {
42
- return null;
43
- }
44
- if (typeof data.targetName !== 'string' || data.targetName.trim().length === 0) {
45
- return null;
46
- }
47
- if (data.targetAvatarUrl !== null && data.targetAvatarUrl !== undefined && typeof data.targetAvatarUrl !== 'string') {
48
- return null;
49
- }
50
- if (data.targetUserType !== 'human' && data.targetUserType !== 'ai_agent') {
51
- return null;
52
- }
53
- if (data.targetUserType === 'ai_agent'
54
- && (typeof data.targetOwnerId !== 'string' || data.targetOwnerId.length === 0)) {
55
- return null;
56
- }
57
- const kindValue = typeof data.kind === 'string' ? data.kind : null;
58
- if (kindValue !== 'dm' && kindValue !== 'group_invite') {
59
- return null;
60
- }
61
- let groupContext = null;
62
- if (kindValue === 'group_invite') {
63
- const ctx = isRecord(data.groupContext) ? data.groupContext : null;
64
- const conversationId = typeof ctx?.conversationId === 'string'
65
- ? ctx.conversationId.trim()
66
- : '';
67
- if (!conversationId) {
68
- return null;
69
- }
70
- groupContext = {
71
- conversationId,
72
- groupName: typeof ctx?.groupName === 'string' ? ctx.groupName : null,
73
- };
74
- }
75
- const payload = {
76
- id: requestId,
77
- requesterId: data.requesterId,
78
- requesterName: typeof data.requesterName === 'string' ? data.requesterName : 'Unknown',
79
- requesterAvatarUrl: typeof data.requesterAvatarUrl === 'string' ? data.requesterAvatarUrl : null,
80
- targetId: data.targetId,
81
- targetName: data.targetName.trim(),
82
- targetAvatarUrl: typeof data.targetAvatarUrl === 'string' ? data.targetAvatarUrl : null,
83
- targetUserType: data.targetUserType,
84
- approverId: data.approverId,
85
- // Free-form request content is owner-review material. This shared DTO is
86
- // delivered to the target agent over REST/SSE, so it must never cross the
87
- // admission boundary before the human approver accepts the reach-out.
88
- message: null,
89
- status: normalizeStatus(data.status),
90
- kind: kindValue,
91
- createdAt: normalizeTimestamp(data.createdAt),
92
- resolvedAt: normalizeTimestamp(data.resolvedAt),
93
- expiresAt: normalizeTimestamp(data.expiresAt),
94
- };
95
- if (groupContext) {
96
- let requirements;
97
- try {
98
- requirements = readGroupInviteRequirements(data.requirements);
99
- }
100
- catch {
101
- return null;
102
- }
103
- payload.groupContext = groupContext;
104
- payload.requirements = requirements;
105
- }
106
- if (data.targetUserType === 'ai_agent') {
107
- payload.targetOwnerId = data.targetOwnerId;
108
- }
109
- return payload;
110
- }