@company-semantics/contracts 58.4.0 → 58.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@company-semantics/contracts",
3
- "version": "58.4.0",
3
+ "version": "58.5.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,9 +22,12 @@ import type { ISO8601Timestamp } from "./types";
22
22
 
23
23
  /**
24
24
  * Target of an execution action.
25
- * Currently supports Slack integration; extensible for future integrations.
25
+ * Slack carries an optional workspace qualifier; BambooHR is addressed by
26
+ * connectionId alone (the org has at most one HRIS connection), so its
27
+ * target is bare (ADR-BE-610).
26
28
  */
27
- export type ExecutionTarget = { type: "slack"; workspaceId?: string };
29
+ export type ExecutionTarget =
30
+ { type: "slack"; workspaceId?: string } | { type: "bamboohr" };
28
31
 
29
32
  // =============================================================================
30
33
  // Initiator
@@ -20,6 +20,10 @@ alongside `Meetings`, `Comms`, and `Docs`.
20
20
  its enum mirrors the backend's `ConnectionRevokedReason` exactly — the app
21
21
  `parse`s this projection, so a value missing from the enum throws rather than
22
22
  degrades (ADR-CONTRACTS-138).
23
+ - `credentialState: 'disconnected'` is a user-chosen stop, not a failure
24
+ (backend ADR-BE-610): imported data and sync history remain, `subdomain` and
25
+ `lastSyncAt` stay populated for the Reconnect flow, `connectionId` and
26
+ `revokedReason` are null, and `syncHealth` is null (nothing is broken).
23
27
  - `HrConnectInputSchema` carries only the customer's provider `subdomain`; no
24
28
  secrets or provider credentials live in contracts.
25
29
  - Pure vocabulary — `zod` is the only runtime import (vocabulary-guard).
@@ -33,26 +33,37 @@ export const HrConnectionStatusSchema = z
33
33
  "whenever the integration cannot sync — read `credentialState` to " +
34
34
  "tell a never-connected integration from one whose grant died.",
35
35
  }),
36
- credentialState: z.enum(["usable", "unusable", "absent"]).meta({
37
- description:
38
- "Why the integration is or is not working. 'usable' — a connection " +
39
- "exists and its credential works (`connected` is true). 'unusable' " +
40
- " a connection exists but its credential cannot be used (expired " +
41
- "or revoked grant); previously synced data remains, and the user " +
42
- "must reconnect. 'absent' no connection at all. Distinguishing " +
43
- "'unusable' from 'absent' is the whole point: both leave " +
44
- "`connected` false, but only one of them is the user's fault to fix " +
45
- "by connecting for the first time.",
46
- }),
36
+ credentialState: z
37
+ .enum(["usable", "unusable", "disconnected", "absent"])
38
+ .meta({
39
+ description:
40
+ "Why the integration is or is not working. 'usable' a connection " +
41
+ "exists and its credential works (`connected` is true). 'unusable' " +
42
+ " a connection exists but its credential cannot be used (expired " +
43
+ "or revoked grant); previously synced data remains, and the user " +
44
+ "must reconnect. 'disconnected' the user chose to stop syncing " +
45
+ "(ADR-BE-610): credentials are gone by intent, imported data and " +
46
+ "sync history remain, and Reconnect resumes the same integration " +
47
+ "identity rather than starting over; nothing is broken, so it " +
48
+ "earns neutral treatment, not the needs-attention treatment " +
49
+ "'unusable' gets. 'absent' — no connection at all. The three " +
50
+ "not-connected states all leave `connected` false but ask " +
51
+ "different things of the reader: 'unusable' is 'fix me', " +
52
+ "'disconnected' is 'resume when ready', 'absent' is 'connect for " +
53
+ "the first time'.",
54
+ }),
47
55
  connectionId: z
48
56
  .string()
49
57
  .nullable()
50
58
  .meta({
51
59
  description:
52
60
  "Stable id of the connection row — the handle the app passes to " +
53
- "`integration.disconnect`. Present whenever a connection exists, " +
54
- "including when `credentialState` is 'unusable', so a dead " +
55
- "integration can still be disconnected. Null only when 'absent'.",
61
+ "`integration.disconnect`. Present whenever there is something to " +
62
+ "disconnect, including when `credentialState` is 'unusable', so a " +
63
+ "dead integration can still be disconnected. Null when 'absent' " +
64
+ "and when 'disconnected' — a disconnected row is retained for " +
65
+ "history/identity (ADR-BE-610) but there is no credential left to " +
66
+ "disconnect, so no disconnect handle is offered.",
56
67
  }),
57
68
  subdomain: z
58
69
  .string()
@@ -106,8 +117,9 @@ export const HrConnectionStatusSchema = z
106
117
  "restored there. The distinction matters because the four cases " +
107
118
  "ask different things of the reader: three are 'click Reconnect' " +
108
119
  "and one is 'go fix it in the provider first'. Null whenever " +
109
- "`credentialState` is not 'unusable', and null on a connection " +
110
- "revoked before this field existed.",
120
+ "`credentialState` is not 'unusable' (including 'disconnected', " +
121
+ "which is chosen, not suffered), and null on a connection revoked " +
122
+ "before this field existed.",
111
123
  }),
112
124
  })
113
125
  .meta({