@canonmsg/backend-contracts 2.2.0 → 2.3.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.
@@ -667,7 +667,7 @@
667
667
  "expiresAt": {
668
668
  "type": "integer",
669
669
  "minimum": 0,
670
- "description": "Absolute epoch-ms deadline. The REST interaction creators REQUIRE a deadline (and /runtime-input/request also requires kind): bindings must fill defaults and convert timeoutMs into expiresAt before calling the endpoint."
670
+ "description": "Absolute epoch-ms deadline. The REST interaction creators REQUIRE a deadline (input interactions also require input subtype kind): bindings must fill defaults and convert timeoutMs into expiresAt before calling the endpoint."
671
671
  }
672
672
  }
673
673
  },
@@ -836,7 +836,7 @@
836
836
  "expiresAt": {
837
837
  "type": "integer",
838
838
  "minimum": 0,
839
- "description": "Absolute epoch-ms deadline. The REST interaction creators REQUIRE a deadline (and /runtime-input/request also requires kind): bindings must fill defaults and convert timeoutMs into expiresAt before calling the endpoint."
839
+ "description": "Absolute epoch-ms deadline. The REST interaction creators REQUIRE a deadline (input interactions also require input subtype kind): bindings must fill defaults and convert timeoutMs into expiresAt before calling the endpoint."
840
840
  }
841
841
  }
842
842
  },
@@ -951,7 +951,7 @@
951
951
  }
952
952
  },
953
953
  "check_approval_result": {
954
- "description": "'unknown' is NOT a denial — only 'resolved' carries a decision. Canonical statuses map from the /runtime-approval/consume wire as: allow/deny -> resolved.decision, timeout -> expired, pending -> pending, HTTP 404 RUNTIME_APPROVAL_NOT_FOUND -> unknown.",
954
+ "description": "'unknown' is NOT a denial — only 'resolved' carries a decision. Canonical statuses map from the approval interaction consume result as: allow/deny -> resolved.decision, timeout -> expired, pending -> pending, HTTP 404 RUNTIME_APPROVAL_NOT_FOUND -> unknown.",
955
955
  "oneOf": [
956
956
  {
957
957
  "type": "object",
@@ -1108,7 +1108,7 @@
1108
1108
  "expiresAt": {
1109
1109
  "type": "integer",
1110
1110
  "minimum": 0,
1111
- "description": "Absolute epoch-ms deadline. The REST interaction creators REQUIRE a deadline (and /runtime-input/request also requires kind): bindings must fill defaults and convert timeoutMs into expiresAt before calling the endpoint."
1111
+ "description": "Absolute epoch-ms deadline. The REST interaction creators REQUIRE a deadline (input interactions also require input subtype kind): bindings must fill defaults and convert timeoutMs into expiresAt before calling the endpoint."
1112
1112
  }
1113
1113
  }
1114
1114
  },
@@ -74,7 +74,10 @@ function serializeContactRequest(requestId, data) {
74
74
  targetAvatarUrl: typeof data.targetAvatarUrl === 'string' ? data.targetAvatarUrl : null,
75
75
  targetUserType: data.targetUserType,
76
76
  approverId: data.approverId,
77
- message: typeof data.message === 'string' ? data.message : null,
77
+ // Free-form request content is owner-review material. This shared DTO is
78
+ // delivered to the target agent over REST/SSE, so it must never cross the
79
+ // admission boundary before the human approver accepts the reach-out.
80
+ message: null,
78
81
  status: normalizeStatus(data.status),
79
82
  kind: kindValue,
80
83
  createdAt: normalizeTimestamp(data.createdAt),
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CANON_ENVIRONMENT_CONTRACTS = void 0;
4
+ exports.getCanonEnvironmentContract = getCanonEnvironmentContract;
5
+ exports.CANON_ENVIRONMENT_CONTRACTS = Object.freeze({
6
+ 'canon-dev-v1': Object.freeze({
7
+ name: 'dev',
8
+ projectId: 'canonmail-dev',
9
+ region: 'europe-west1',
10
+ }),
11
+ 'canon-prod-v1': Object.freeze({
12
+ name: 'prod',
13
+ projectId: 'canonmail-prod',
14
+ region: 'europe-west1',
15
+ }),
16
+ 'canon-legacy-v1': Object.freeze({
17
+ name: 'legacy',
18
+ projectId: 'project-007a8e71-ba01-49e6-8aa',
19
+ region: 'us-central1',
20
+ }),
21
+ });
22
+ function getCanonEnvironmentContract(value) {
23
+ const environmentId = value.trim();
24
+ const contract = exports.CANON_ENVIRONMENT_CONTRACTS[environmentId];
25
+ if (!contract) {
26
+ throw new Error(`Unsupported Canon environment ID: ${value}`);
27
+ }
28
+ return Object.freeze({ environmentId, ...contract });
29
+ }
package/dist/cjs/index.js CHANGED
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./diffRedaction.js"), exports);
18
+ __exportStar(require("./environment.js"), exports);
18
19
  __exportStar(require("./media.js"), exports);
19
20
  __exportStar(require("./message.js"), exports);
20
21
  __exportStar(require("./runtimeCardFields.js"), exports);
@@ -270,7 +270,7 @@ const timeoutFields = (maxMs, ceilingNote) => ({
270
270
  type: 'integer',
271
271
  minimum: 0,
272
272
  description: 'Absolute epoch-ms deadline. The REST interaction creators REQUIRE a deadline '
273
- + '(and /runtime-input/request also requires kind): bindings must fill defaults '
273
+ + '(input interactions also require input subtype kind): bindings must fill defaults '
274
274
  + 'and convert timeoutMs into expiresAt before calling the endpoint.',
275
275
  },
276
276
  });
@@ -544,7 +544,7 @@ const check_approval_input = {
544
544
  };
545
545
  const check_approval_result = {
546
546
  description: "'unknown' is NOT a denial — only 'resolved' carries a decision. Canonical statuses map "
547
- + 'from the /runtime-approval/consume wire as: allow/deny -> resolved.decision, timeout -> '
547
+ + 'from the approval interaction consume result as: allow/deny -> resolved.decision, timeout -> '
548
548
  + 'expired, pending -> pending, HTTP 404 RUNTIME_APPROVAL_NOT_FOUND -> unknown.',
549
549
  oneOf: [
550
550
  {
@@ -10,6 +10,7 @@ export interface SerializedContactRequest {
10
10
  targetUserType: 'human' | 'ai_agent';
11
11
  targetOwnerId?: string | null;
12
12
  approverId: string;
13
+ /** Always null on agent-facing DTOs; free-form content stays in authorized review storage. */
13
14
  message: string | null;
14
15
  status: SerializedContactRequestStatus;
15
16
  kind: 'dm' | 'group_invite';
@@ -71,7 +71,10 @@ export function serializeContactRequest(requestId, data) {
71
71
  targetAvatarUrl: typeof data.targetAvatarUrl === 'string' ? data.targetAvatarUrl : null,
72
72
  targetUserType: data.targetUserType,
73
73
  approverId: data.approverId,
74
- message: typeof data.message === 'string' ? data.message : null,
74
+ // Free-form request content is owner-review material. This shared DTO is
75
+ // delivered to the target agent over REST/SSE, so it must never cross the
76
+ // admission boundary before the human approver accepts the reach-out.
77
+ message: null,
75
78
  status: normalizeStatus(data.status),
76
79
  kind: kindValue,
77
80
  createdAt: normalizeTimestamp(data.createdAt),
@@ -0,0 +1,25 @@
1
+ export declare const CANON_ENVIRONMENT_CONTRACTS: Readonly<{
2
+ readonly 'canon-dev-v1': Readonly<{
3
+ name: "dev";
4
+ projectId: "canonmail-dev";
5
+ region: "europe-west1";
6
+ }>;
7
+ readonly 'canon-prod-v1': Readonly<{
8
+ name: "prod";
9
+ projectId: "canonmail-prod";
10
+ region: "europe-west1";
11
+ }>;
12
+ readonly 'canon-legacy-v1': Readonly<{
13
+ name: "legacy";
14
+ projectId: "project-007a8e71-ba01-49e6-8aa";
15
+ region: "us-central1";
16
+ }>;
17
+ }>;
18
+ export type CanonEnvironmentId = keyof typeof CANON_ENVIRONMENT_CONTRACTS;
19
+ export type CanonEnvironmentName = (typeof CANON_ENVIRONMENT_CONTRACTS)[CanonEnvironmentId]['name'];
20
+ export type CanonEnvironmentContract = {
21
+ [EnvironmentId in CanonEnvironmentId]: {
22
+ environmentId: EnvironmentId;
23
+ } & (typeof CANON_ENVIRONMENT_CONTRACTS)[EnvironmentId];
24
+ }[CanonEnvironmentId];
25
+ export declare function getCanonEnvironmentContract(value: string): CanonEnvironmentContract;
@@ -0,0 +1,25 @@
1
+ export const CANON_ENVIRONMENT_CONTRACTS = Object.freeze({
2
+ 'canon-dev-v1': Object.freeze({
3
+ name: 'dev',
4
+ projectId: 'canonmail-dev',
5
+ region: 'europe-west1',
6
+ }),
7
+ 'canon-prod-v1': Object.freeze({
8
+ name: 'prod',
9
+ projectId: 'canonmail-prod',
10
+ region: 'europe-west1',
11
+ }),
12
+ 'canon-legacy-v1': Object.freeze({
13
+ name: 'legacy',
14
+ projectId: 'project-007a8e71-ba01-49e6-8aa',
15
+ region: 'us-central1',
16
+ }),
17
+ });
18
+ export function getCanonEnvironmentContract(value) {
19
+ const environmentId = value.trim();
20
+ const contract = CANON_ENVIRONMENT_CONTRACTS[environmentId];
21
+ if (!contract) {
22
+ throw new Error(`Unsupported Canon environment ID: ${value}`);
23
+ }
24
+ return Object.freeze({ environmentId, ...contract });
25
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './diffRedaction.js';
2
+ export * from './environment.js';
2
3
  export * from './media.js';
3
4
  export * from './message.js';
4
5
  export * from './runtimeCardFields.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './diffRedaction.js';
2
+ export * from './environment.js';
2
3
  export * from './media.js';
3
4
  export * from './message.js';
4
5
  export * from './runtimeCardFields.js';
@@ -265,7 +265,7 @@ const timeoutFields = (maxMs, ceilingNote) => ({
265
265
  type: 'integer',
266
266
  minimum: 0,
267
267
  description: 'Absolute epoch-ms deadline. The REST interaction creators REQUIRE a deadline '
268
- + '(and /runtime-input/request also requires kind): bindings must fill defaults '
268
+ + '(input interactions also require input subtype kind): bindings must fill defaults '
269
269
  + 'and convert timeoutMs into expiresAt before calling the endpoint.',
270
270
  },
271
271
  });
@@ -539,7 +539,7 @@ const check_approval_input = {
539
539
  };
540
540
  const check_approval_result = {
541
541
  description: "'unknown' is NOT a denial — only 'resolved' carries a decision. Canonical statuses map "
542
- + 'from the /runtime-approval/consume wire as: allow/deny -> resolved.decision, timeout -> '
542
+ + 'from the approval interaction consume result as: allow/deny -> resolved.decision, timeout -> '
543
543
  + 'expired, pending -> pending, HTTP 404 RUNTIME_APPROVAL_NOT_FOUND -> unknown.',
544
544
  oneOf: [
545
545
  {
@@ -54,7 +54,7 @@ export interface VerbWireTurn {
54
54
  * plaintext for routing + mention-piercing pushes (D3); `contactUserId` on
55
55
  * share_contact reveals who was shared (explicitly accepted for v1);
56
56
  * `sessionConfig` may carry workspace ids — borderline, revisit with the
57
- * session-state encryption decision.
57
+ * session-configuration encryption decision.
58
58
  */
59
59
  export interface CanonVerbWireEnvelope {
60
60
  conversationId?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/backend-contracts",
3
- "version": "2.2.0",
3
+ "version": "2.3.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.8.1",
46
+ "@canonmsg/rich-cards": "^0.8.2",
47
47
  "@types/node": "^22.0.0",
48
48
  "ajv": "^8.20.0",
49
49
  "typescript": "~5.7.0",