@opencxh/domain 1.97.0 → 1.99.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.
@@ -22,7 +22,7 @@ export interface BaseActivity {
22
22
  channelId?: string;
23
23
  providerId: string;
24
24
  author: {
25
- type: "user" | "contact" | "system";
25
+ type: "user" | "contact" | "system" | "app";
26
26
  /** Provider/account-id (Microsoft user-id, SIP account-id, etc.). */
27
27
  id?: string;
28
28
  name: string;
@@ -6,4 +6,5 @@ export interface AiAccount {
6
6
  isDefaultLlm?: boolean;
7
7
  isDefaultStt?: boolean;
8
8
  isDefaultTts?: boolean;
9
+ isDefaultEmbedding?: boolean;
9
10
  }
@@ -19,6 +19,11 @@ export type DimensionId = string;
19
19
  export type HandledBy = "teammate" | "autopilot" | "ai_assistant";
20
20
  /** How the frontend turns a raw dimension key into a display label. */
21
21
  export type DimensionLabelSource = "user" | "team" | "inbox" | "channel" | "topic" | "raw";
22
+ /** A value->label pair for a bounded dimension, carried in the dimension declaration itself. */
23
+ export interface DimensionOption {
24
+ value: string;
25
+ label: string;
26
+ }
22
27
  export interface DimensionDefinition {
23
28
  id: DimensionId;
24
29
  label: string;
@@ -29,6 +34,13 @@ export interface DimensionDefinition {
29
34
  */
30
35
  multiValued?: boolean;
31
36
  labelSource?: DimensionLabelSource;
37
+ /**
38
+ * Bounded value->label set declared by the owning source. When present, the frontend resolves this
39
+ * dimension's value labels straight from the catalog — no per-dimension code, no source-specific
40
+ * fetch. This is how a source (any app) federates its own dimension labels; unbounded/entity-backed
41
+ * dims (agent, team, channel) omit this and are resolved by id-lookup instead.
42
+ */
43
+ options?: DimensionOption[];
32
44
  }
33
45
  /**
34
46
  * Shared base dimensions — any source app may emit facts on these. Kept un-namespaced on purpose.
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1,41 @@
1
+ import { MutationAuthor } from '../../platform/author';
2
+ /**
3
+ * Who wrote an attribute value. Doubles as the idempotency axis: each
4
+ * (resource, key, source) is one row, so re-writing by the same source replaces
5
+ * in place while different sources (a human vs the AI) keep their own value
6
+ * without clobbering each other. Derived from MutationAuthor; `id` is the user-id
7
+ * or app-name, absent for `system`.
8
+ */
9
+ export interface AttributeSourceRef {
10
+ type: MutationAuthor["type"];
11
+ id?: string;
12
+ }
13
+ /**
14
+ * A single key/value fact attached to any resource (interaction, contact,
15
+ * activity, ...), addressed polymorphically by (resourceType, resourceId) - the
16
+ * same ResourceRef shape read-state uses. Keywords, summary, sentiment and future
17
+ * custom fields are all just keys; a new key costs zero schema changes.
18
+ */
19
+ export interface Attribute {
20
+ id: string;
21
+ organizationId: string;
22
+ resourceType: string;
23
+ resourceId: string;
24
+ key: string;
25
+ /** JSON scalar | array | object; readers interpret per key. */
26
+ value: unknown;
27
+ source: AttributeSourceRef;
28
+ createdAt?: number;
29
+ updatedAt?: number;
30
+ }
31
+ /** One (key,value) to set on a resource. */
32
+ export interface AttributeInput {
33
+ key: string;
34
+ value: unknown;
35
+ }
36
+ /** POST /attribute/:type/:id body. */
37
+ export interface SetAttributesRequest {
38
+ attributes: AttributeInput[];
39
+ }
40
+ /** Collapsed key -> value view after applying source precedence (user > app > system). */
41
+ export type ResolvedAttributes = Record<string, unknown>;
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1,40 @@
1
+ export type CustomFieldType = "text" | "select";
2
+ /** A selectable option for a `select` field. `label` falls back to `value` when absent. */
3
+ export interface CustomFieldOption {
4
+ value: string;
5
+ label?: string;
6
+ }
7
+ /**
8
+ * An org-defined custom field. It gives an attribute key meaning (label, type,
9
+ * dropdown options) so users can fill it in on a resource; the value itself lives
10
+ * in the generic Attribute store keyed by `key`. Empty `teamIds` = visible on every
11
+ * team's conversations; otherwise only on conversations owned by one of those teams.
12
+ */
13
+ export interface CustomFieldDef {
14
+ id: string;
15
+ organizationId: string;
16
+ /** Stable machine key, equals the Attribute key. Constrained to [a-z0-9_]+ (a dot would read as a nested form path). */
17
+ key: string;
18
+ label: string;
19
+ type: CustomFieldType;
20
+ /** For `select`: the allowed options. The stored attribute value is the option's `value`. */
21
+ options?: CustomFieldOption[];
22
+ /** `select` only: multi-select — the stored value becomes a string[]. */
23
+ multiValued?: boolean;
24
+ /** Resource kinds this field applies to, e.g. ["interaction"]. */
25
+ appliesTo: string[];
26
+ /** Empty/absent = all teams; otherwise only shown when the resource belongs to one of these teams. */
27
+ teamIds?: string[];
28
+ /**
29
+ * When true, this field becomes an analytics dimension `comms.cf.<key>`: every conversation-level
30
+ * metric can be grouped/filtered by its value. Opt-in to avoid turning free-text fields into
31
+ * high-cardinality dimensions.
32
+ */
33
+ reportable?: boolean;
34
+ required?: boolean;
35
+ description?: string;
36
+ /** Display order in the fields panel. */
37
+ order: number;
38
+ createdAt?: number;
39
+ updatedAt?: number;
40
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './entities/activity';
2
2
  export * from './entities/analytics';
3
+ export * from './entities/attribute';
3
4
  export * from './entities/playbook';
4
5
  export * from './entities/kb';
5
6
  export * from './entities/topic';
@@ -12,6 +13,7 @@ export * from './entities/mcp';
12
13
  export * from './entities/channel';
13
14
  export * from './entities/communication';
14
15
  export * from './entities/contact';
16
+ export * from './entities/custom-field-def';
15
17
  export * from './entities/calendar-event';
16
18
  export * from './entities/draft';
17
19
  export * from './entities/inbox';
@@ -28,6 +30,7 @@ export * from './entities/webhook';
28
30
  export * from './text/message';
29
31
  export * from './platform/ai-tools';
30
32
  export * from './platform/api';
33
+ export * from './platform/author';
31
34
  export * from './platform/common';
32
35
  export * from './platform/capabilities';
33
36
  export * from './platform/context';
@@ -41,6 +44,7 @@ export * from './platform/manifest';
41
44
  export * from './platform/menu';
42
45
  export * from './platform/reactive';
43
46
  export * from './platform/routing';
47
+ export * from './platform/scope';
44
48
  export * from './platform/sdk';
45
49
  export * from './platform/settings';
46
50
  export * from './platform/service-registry';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Wie een mutatie heeft uitgevoerd — voor attributie op de timeline en in
3
+ * analytics. Server-side afgeleid uit de request (zie `resolveAuthor` in
4
+ * `@opencxh/platform-api`). De shape sluit aan op `BaseActivity.author`, zodat
5
+ * een author direct als activity-author kan worden weggeschreven.
6
+ *
7
+ * - `user` — ingelogde gebruiker; `id` is de user-id (analytics-attributie).
8
+ * - `app` — een provider/integratie-app (bv. een playbook dat als de `ai`-app
9
+ * muteert); `id` is de app-naam. De timeline toont dan de app
10
+ * i.p.v. een anonieme "System".
11
+ * - `system` — geen geïdentificeerde actor (cron, achtergrondjob).
12
+ */
13
+ export type MutationAuthor = {
14
+ type: "user";
15
+ id: string;
16
+ name: string;
17
+ } | {
18
+ type: "app";
19
+ id: string;
20
+ name: string;
21
+ } | {
22
+ type: "system";
23
+ name: string;
24
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Cross-app scope-authorization contract. A resource is addressed by an opaque
3
+ * scopeKey ("<kind>:<ref>", e.g. "interaction:abc"); the app that owns that kind
4
+ * answers "may this user access it?" over the `scope` provider role. Consumed by
5
+ * the AI live-assistant (conversation access) and, from fase 2, the attribute store.
6
+ * Implementation: authorizeScope / assertScopeAccess in @opencxh/platform-api.
7
+ */
8
+ /** Access decision + whether the scope anchor is team-shared + the SSE audience. */
9
+ export interface ScopeAuth {
10
+ allowed: boolean;
11
+ shared?: boolean;
12
+ audience?: string[];
13
+ }
14
+ /** GET /provider/scope/describe response: the scopeKey prefixes an app owns. */
15
+ export interface ScopeDescribe {
16
+ kinds: string[];
17
+ }
18
+ /** POST /provider/scope/authorize body. userId omitted = trusted system caller. */
19
+ export interface ScopeAuthorizeRequest {
20
+ scopeKey: string;
21
+ userId?: string;
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencxh/domain",
3
- "version": "1.97.0",
3
+ "version": "1.99.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",