@company-semantics/contracts 62.4.0 → 62.6.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 +5 -5
- package/src/__tests__/iso-datetime.test.ts +71 -0
- package/src/admin/direct-grants.ts +4 -3
- package/src/api/generated-spec-hash.ts +2 -2
- package/src/api/generated.ts +14 -3
- package/src/api/primitives.ts +44 -0
- package/src/chat/README.md +1 -1
- package/src/chat/index.ts +0 -1
- package/src/chat/schemas.ts +20 -26
- package/src/execution/README.md +1 -0
- package/src/execution/schemas.ts +3 -2
- package/src/execution/sse.ts +2 -1
- package/src/identity/README.md +1 -0
- package/src/identity/identity-link.ts +3 -2
- package/src/impersonation/schemas.ts +7 -6
- package/src/integrations/README.md +1 -1
- package/src/integrations/schemas.ts +2 -1
- package/src/meetings/schemas.ts +4 -3
- package/src/org/occupancy.ts +3 -2
- package/src/org/reasoning-review.ts +2 -1
- package/src/org/reconciliation.ts +4 -3
- package/src/org/schemas.ts +4 -4
- package/src/org/sync-run.ts +3 -2
- package/src/permissions/permission-introspection.ts +2 -1
- package/src/permissions/share-api.ts +2 -1
- package/src/security/org-secrets.ts +4 -3
- package/src/user-events/schemas.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@company-semantics/contracts",
|
|
3
|
-
"version": "62.
|
|
3
|
+
"version": "62.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -139,8 +139,8 @@
|
|
|
139
139
|
"node": "22.x"
|
|
140
140
|
},
|
|
141
141
|
"dependencies": {
|
|
142
|
-
"@slack/types": "^3.
|
|
143
|
-
"zod": "^4.
|
|
142
|
+
"@slack/types": "^3.1.0",
|
|
143
|
+
"zod": "^4.5.2"
|
|
144
144
|
},
|
|
145
145
|
"devDependencies": {
|
|
146
146
|
"@eslint/js": "^10.0.1",
|
|
@@ -149,13 +149,13 @@
|
|
|
149
149
|
"culori": "^4.0.2",
|
|
150
150
|
"eslint": "^10.9.0",
|
|
151
151
|
"husky": "^9.1.7",
|
|
152
|
-
"lint-staged": "^17.
|
|
152
|
+
"lint-staged": "^17.4.1",
|
|
153
153
|
"markdownlint-cli2": "^0.23.2",
|
|
154
154
|
"openapi-typescript": "^7.13.0",
|
|
155
155
|
"prettier": "^3.9.6",
|
|
156
156
|
"tsx": "^4.23.12",
|
|
157
157
|
"typescript": "^5.8.3",
|
|
158
|
-
"typescript-eslint": "^8.
|
|
158
|
+
"typescript-eslint": "^8.68.0",
|
|
159
159
|
"vite": "^8.2.2",
|
|
160
160
|
"vitest": "^4.1.11",
|
|
161
161
|
"yaml": "^2.9.0"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ISO_DATETIME_OFFSET_PATTERN,
|
|
6
|
+
ISO_DATETIME_PATTERN,
|
|
7
|
+
IsoDateTime,
|
|
8
|
+
IsoDateTimeWithOffset,
|
|
9
|
+
} from "../api/primitives";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* These are drift alarms, not unit tests.
|
|
13
|
+
*
|
|
14
|
+
* `IsoDateTime` delegates to zod's built-in RFC 3339 regex, and zod is advanced
|
|
15
|
+
* automatically by Dependabot inside a grouped `minor`/`patch` bump. That is
|
|
16
|
+
* exactly how the seconds-optional -> seconds-mandatory tightening reached
|
|
17
|
+
* production undocumented (backend #520). If zod moves this regex again, the
|
|
18
|
+
* documented format of every `format: date-time` field on the public API moves
|
|
19
|
+
* with it — so it fails here first and gets ratified deliberately.
|
|
20
|
+
*
|
|
21
|
+
* If one of these fails: do not update the constant to make it green. Work out
|
|
22
|
+
* what zod changed, decide whether we want it, and record the decision.
|
|
23
|
+
*/
|
|
24
|
+
describe("the RFC 3339 wire contract is pinned, not inherited", () => {
|
|
25
|
+
it("emits the pinned pattern for the Z-only form", () => {
|
|
26
|
+
expect(z.toJSONSchema(IsoDateTime, { io: "input" }).pattern).toBe(
|
|
27
|
+
ISO_DATETIME_PATTERN,
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("emits the pinned pattern for the offset-allowing form", () => {
|
|
32
|
+
expect(z.toJSONSchema(IsoDateTimeWithOffset, { io: "input" }).pattern).toBe(
|
|
33
|
+
ISO_DATETIME_OFFSET_PATTERN,
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("still emits format: date-time, which the pattern alone would not carry", () => {
|
|
38
|
+
expect(z.toJSONSchema(IsoDateTime, { io: "input" }).format).toBe(
|
|
39
|
+
"date-time",
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("seconds are mandatory (ADR-CONTRACTS-156)", () => {
|
|
45
|
+
it.each([
|
|
46
|
+
"2026-09-01T12:00:00Z",
|
|
47
|
+
"2026-09-01T12:00:00.000Z",
|
|
48
|
+
"2024-02-29T23:59:59Z",
|
|
49
|
+
])("accepts %s", (value) => {
|
|
50
|
+
expect(IsoDateTime.safeParse(value).success).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it.each(["2026-09-01T12:00Z", "2026-09-01T12Z", "2026-09-01"])(
|
|
54
|
+
"rejects %s",
|
|
55
|
+
(value) => {
|
|
56
|
+
expect(IsoDateTime.safeParse(value).success).toBe(false);
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
it("rejects a numeric offset on the Z-only form", () => {
|
|
61
|
+
expect(IsoDateTime.safeParse("2026-09-01T12:00:00+02:00").success).toBe(
|
|
62
|
+
false,
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("accepts a numeric offset on the offset-allowing form", () => {
|
|
67
|
+
expect(
|
|
68
|
+
IsoDateTimeWithOffset.safeParse("2026-09-01T12:00:00+02:00").success,
|
|
69
|
+
).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
* direct-grant-audit-trail and the `direct-grant-audit` CI guard).
|
|
8
8
|
*/
|
|
9
9
|
import { z } from "zod";
|
|
10
|
+
import { IsoDateTime } from "../api/primitives";
|
|
10
11
|
|
|
11
12
|
export const DirectGrantCreate = z.object({
|
|
12
13
|
subject_id: z.string().uuid(),
|
|
13
14
|
scope_pattern: z.string(),
|
|
14
15
|
resource_filter: z.record(z.string(), z.unknown()).optional(),
|
|
15
|
-
expires_at:
|
|
16
|
+
expires_at: IsoDateTime.optional(),
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
export type DirectGrantCreate = z.infer<typeof DirectGrantCreate>;
|
|
@@ -24,8 +25,8 @@ export const DirectGrant = z.object({
|
|
|
24
25
|
scope_pattern: z.string(),
|
|
25
26
|
source: z.literal("direct"),
|
|
26
27
|
granted_by: z.string().uuid(),
|
|
27
|
-
granted_at:
|
|
28
|
-
expires_at:
|
|
28
|
+
granted_at: IsoDateTime,
|
|
29
|
+
expires_at: IsoDateTime.nullable(),
|
|
29
30
|
});
|
|
30
31
|
|
|
31
32
|
export type DirectGrant = z.infer<typeof DirectGrant>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
|
|
2
|
-
export const SPEC_HASH = '
|
|
3
|
-
export const SPEC_HASH_FULL = '
|
|
2
|
+
export const SPEC_HASH = '52d89a463432' as const;
|
|
3
|
+
export const SPEC_HASH_FULL = '52d89a4634328ae80200c221d6aa25d8c34c9d09208a2c460d82a523ec79144d' as const;
|
package/src/api/generated.ts
CHANGED
|
@@ -4293,6 +4293,12 @@ export interface components {
|
|
|
4293
4293
|
};
|
|
4294
4294
|
/** @enum {string} */
|
|
4295
4295
|
origin?: "user" | "proactive";
|
|
4296
|
+
launch?: {
|
|
4297
|
+
/** @constant */
|
|
4298
|
+
kind: "structure-review";
|
|
4299
|
+
/** Format: uuid */
|
|
4300
|
+
proposalId: string;
|
|
4301
|
+
};
|
|
4296
4302
|
} | {
|
|
4297
4303
|
/** @constant */
|
|
4298
4304
|
trigger: "regenerate-message";
|
|
@@ -4315,6 +4321,12 @@ export interface components {
|
|
|
4315
4321
|
};
|
|
4316
4322
|
/** @enum {string} */
|
|
4317
4323
|
origin?: "user" | "proactive";
|
|
4324
|
+
launch?: {
|
|
4325
|
+
/** @constant */
|
|
4326
|
+
kind: "structure-review";
|
|
4327
|
+
/** Format: uuid */
|
|
4328
|
+
proposalId: string;
|
|
4329
|
+
};
|
|
4318
4330
|
};
|
|
4319
4331
|
ProactiveChatResolution: {
|
|
4320
4332
|
/** @constant */
|
|
@@ -6783,9 +6795,8 @@ export interface components {
|
|
|
6783
6795
|
p95ContextTokens: number;
|
|
6784
6796
|
medianReadsAfterFirstEdit: number;
|
|
6785
6797
|
}[];
|
|
6786
|
-
bySource:
|
|
6798
|
+
bySource: {
|
|
6787
6799
|
source: string;
|
|
6788
|
-
} & {
|
|
6789
6800
|
p95Reads?: number;
|
|
6790
6801
|
p50Reads?: number;
|
|
6791
6802
|
p95ContextTokens?: number;
|
|
@@ -6797,7 +6808,7 @@ export interface components {
|
|
|
6797
6808
|
navMapUsageBySource?: {
|
|
6798
6809
|
[key: string]: number;
|
|
6799
6810
|
};
|
|
6800
|
-
}
|
|
6811
|
+
}[];
|
|
6801
6812
|
trend: {
|
|
6802
6813
|
recent: {
|
|
6803
6814
|
p95Reads?: number;
|
package/src/api/primitives.ts
CHANGED
|
@@ -25,3 +25,47 @@ export type CursorPage<T> = {
|
|
|
25
25
|
hasMore: boolean;
|
|
26
26
|
};
|
|
27
27
|
export type ErrorResponse = z.infer<typeof ErrorResponseSchema>;
|
|
28
|
+
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// The RFC 3339 timestamp contract
|
|
31
|
+
// =============================================================================
|
|
32
|
+
//
|
|
33
|
+
// Every `format: date-time` field on the public API surface is built from one of
|
|
34
|
+
// the two schemas below, so the wire contract has exactly one definition site.
|
|
35
|
+
//
|
|
36
|
+
// The validators delegate to zod's built-in `.datetime()` rather than
|
|
37
|
+
// reimplementing RFC 3339 by hand: that keeps `format: date-time` in the emitted
|
|
38
|
+
// OpenAPI document and avoids a hand-rolled regex drifting from the runtime
|
|
39
|
+
// check. The regex zod produces is therefore an *input* to our published
|
|
40
|
+
// contract, and zod is a transitive dependency that Dependabot advances
|
|
41
|
+
// automatically — so the emitted pattern is pinned below and asserted in
|
|
42
|
+
// `src/__tests__/iso-datetime.test.ts`.
|
|
43
|
+
//
|
|
44
|
+
// That assertion is the point. A zod release that changes this regex changes the
|
|
45
|
+
// documented format of 52 public fields; it must fail a test and be ratified,
|
|
46
|
+
// not land silently inside a grouped `minor`/`patch` bump. See ADR-CONTRACTS-156.
|
|
47
|
+
|
|
48
|
+
/** Emitted `pattern` for {@link IsoDateTime}. Pinned — see the note above. */
|
|
49
|
+
export const ISO_DATETIME_PATTERN =
|
|
50
|
+
"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$";
|
|
51
|
+
|
|
52
|
+
/** Emitted `pattern` for {@link IsoDateTimeWithOffset}. Pinned — see the note above. */
|
|
53
|
+
export const ISO_DATETIME_OFFSET_PATTERN =
|
|
54
|
+
"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$";
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A UTC RFC 3339 timestamp — `2026-09-01T12:00:00.000Z`.
|
|
58
|
+
*
|
|
59
|
+
* Seconds are mandatory. `2026-09-01T12:00Z` is rejected: it is not valid
|
|
60
|
+
* RFC 3339, and the backend has rejected it since zod 4.5.x.
|
|
61
|
+
*/
|
|
62
|
+
export const IsoDateTime = z.string().datetime();
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* An RFC 3339 timestamp that may carry a numeric UTC offset instead of `Z` —
|
|
66
|
+
* `2026-09-01T12:00:00.000+02:00`.
|
|
67
|
+
*
|
|
68
|
+
* Use only where a client legitimately reports local wall-clock time with its
|
|
69
|
+
* offset. Prefer {@link IsoDateTime} for anything the server mints.
|
|
70
|
+
*/
|
|
71
|
+
export const IsoDateTimeWithOffset = z.string().datetime({ offset: true });
|
package/src/chat/README.md
CHANGED
|
@@ -89,7 +89,6 @@ Shared types for chat persistence, sharing, real-time events, and runtime profil
|
|
|
89
89
|
- `InvalidateChatListEventSchema`
|
|
90
90
|
- `InvalidationReason` _(type)_ — Reason for cache invalidation.
|
|
91
91
|
- `InvalidationReasonSchema`
|
|
92
|
-
- `IsoDateString` — ISO 8601 datetime string — the runtime safety net for date serialization.
|
|
93
92
|
- `ListSharesResponse` _(type)_ — Response for GET /api/chats/:chatId/shares
|
|
94
93
|
- `ListSharesResponseSchema` — Response for GET /api/chats/:chatId/shares
|
|
95
94
|
- `ProactiveChatResolution` _(type)_ — Resolving an occurrence id to the CURRENT reader's chat — one of the four bounded states `ready` (with…
|
|
@@ -117,6 +116,7 @@ Shared types for chat persistence, sharing, real-time events, and runtime profil
|
|
|
117
116
|
|
|
118
117
|
**Internal domains:**
|
|
119
118
|
|
|
119
|
+
- `api`
|
|
120
120
|
- `proactive`
|
|
121
121
|
|
|
122
122
|
**External packages:**
|
package/src/chat/index.ts
CHANGED
package/src/chat/schemas.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
// =============================================================================
|
|
4
|
-
// Reusable Primitives
|
|
5
|
-
// =============================================================================
|
|
6
|
-
|
|
7
|
-
/** ISO 8601 datetime string — the runtime safety net for date serialization. */
|
|
8
|
-
export const IsoDateString = z.string().datetime();
|
|
2
|
+
import { IsoDateTime } from "../api/primitives";
|
|
9
3
|
|
|
10
4
|
// =============================================================================
|
|
11
5
|
// Enums
|
|
@@ -78,15 +72,15 @@ export const ChatSummarySchema = z.object({
|
|
|
78
72
|
id: z.string(),
|
|
79
73
|
title: z.string().nullable(),
|
|
80
74
|
messageCount: z.number().int(),
|
|
81
|
-
createdAt:
|
|
82
|
-
updatedAt:
|
|
75
|
+
createdAt: IsoDateTime,
|
|
76
|
+
updatedAt: IsoDateTime,
|
|
83
77
|
isShared: z.boolean(),
|
|
84
78
|
});
|
|
85
79
|
|
|
86
80
|
export const ChatSummaryExtendedSchema = ChatSummarySchema.extend({
|
|
87
|
-
pinnedAt:
|
|
81
|
+
pinnedAt: IsoDateTime.nullable(),
|
|
88
82
|
titleSource: TitleSourceSchema.nullable(),
|
|
89
|
-
titleGeneratedAt:
|
|
83
|
+
titleGeneratedAt: IsoDateTime.nullable(),
|
|
90
84
|
...proactiveChatFields,
|
|
91
85
|
});
|
|
92
86
|
|
|
@@ -129,7 +123,7 @@ export const ChatShareInfoSchema = z.object({
|
|
|
129
123
|
shareUrl: z.string().optional(),
|
|
130
124
|
messageCountAtShare: z.number().int(),
|
|
131
125
|
titleAtShare: z.string(),
|
|
132
|
-
createdAt:
|
|
126
|
+
createdAt: IsoDateTime,
|
|
133
127
|
createdByName: z.string(),
|
|
134
128
|
isRevoked: z.boolean(),
|
|
135
129
|
});
|
|
@@ -137,7 +131,7 @@ export const ChatShareInfoSchema = z.object({
|
|
|
137
131
|
export const SharedChatViewSchema = z.object({
|
|
138
132
|
title: z.string(),
|
|
139
133
|
messages: z.array(SharedChatMessageSchema),
|
|
140
|
-
sharedAt:
|
|
134
|
+
sharedAt: IsoDateTime,
|
|
141
135
|
sharedByName: z.string(),
|
|
142
136
|
visibility: ChatVisibilitySchema,
|
|
143
137
|
});
|
|
@@ -148,7 +142,7 @@ export const SharedChatViewSchema = z.object({
|
|
|
148
142
|
|
|
149
143
|
export const BaseEventSchema = z.object({
|
|
150
144
|
v: z.literal(1),
|
|
151
|
-
timestamp:
|
|
145
|
+
timestamp: IsoDateTime,
|
|
152
146
|
eventId: z.string().optional(),
|
|
153
147
|
});
|
|
154
148
|
|
|
@@ -167,10 +161,10 @@ export const ChatCreatedEventSchema = BaseEventSchema.extend({
|
|
|
167
161
|
interactionId: z.string().optional(),
|
|
168
162
|
title: z.string(),
|
|
169
163
|
titleSource: TitleSourceSchema,
|
|
170
|
-
pinnedAt:
|
|
164
|
+
pinnedAt: IsoDateTime.nullable(),
|
|
171
165
|
messageCount: z.number().int(),
|
|
172
|
-
createdAt:
|
|
173
|
-
updatedAt:
|
|
166
|
+
createdAt: IsoDateTime,
|
|
167
|
+
updatedAt: IsoDateTime,
|
|
174
168
|
isShared: z.boolean(),
|
|
175
169
|
...proactiveChatFields,
|
|
176
170
|
}),
|
|
@@ -182,11 +176,11 @@ export const ChatUpdatedEventSchema = BaseEventSchema.extend({
|
|
|
182
176
|
chatId: z.string(),
|
|
183
177
|
title: z.string(),
|
|
184
178
|
titleSource: TitleSourceSchema.nullable(),
|
|
185
|
-
titleGeneratedAt:
|
|
186
|
-
pinnedAt:
|
|
179
|
+
titleGeneratedAt: IsoDateTime.nullable(),
|
|
180
|
+
pinnedAt: IsoDateTime.nullable(),
|
|
187
181
|
messageCount: z.number().int(),
|
|
188
|
-
createdAt:
|
|
189
|
-
updatedAt:
|
|
182
|
+
createdAt: IsoDateTime,
|
|
183
|
+
updatedAt: IsoDateTime,
|
|
190
184
|
isShared: z.boolean(),
|
|
191
185
|
...proactiveChatFields,
|
|
192
186
|
}),
|
|
@@ -245,7 +239,7 @@ export const ChatMessageSchema = z.object({
|
|
|
245
239
|
content: z.string(),
|
|
246
240
|
parts: z.array(z.unknown()).optional(),
|
|
247
241
|
sequenceNumber: z.number().int(),
|
|
248
|
-
createdAt:
|
|
242
|
+
createdAt: IsoDateTime,
|
|
249
243
|
});
|
|
250
244
|
|
|
251
245
|
// =============================================================================
|
|
@@ -325,11 +319,11 @@ export const ChatDetailSchema = z.object({
|
|
|
325
319
|
id: z.string(),
|
|
326
320
|
title: z.string(),
|
|
327
321
|
interactionId: z.string(),
|
|
328
|
-
pinnedAt:
|
|
322
|
+
pinnedAt: IsoDateTime.nullable().optional(),
|
|
329
323
|
titleSource: TitleSourceSchema.nullable().optional(),
|
|
330
|
-
titleGeneratedAt:
|
|
331
|
-
createdAt:
|
|
332
|
-
updatedAt:
|
|
324
|
+
titleGeneratedAt: IsoDateTime.nullable().optional(),
|
|
325
|
+
createdAt: IsoDateTime,
|
|
326
|
+
updatedAt: IsoDateTime,
|
|
333
327
|
// Opening the detail is what clears `unread`; the detail carries the flag so
|
|
334
328
|
// the reader can tell a first open from a return visit. `proactiveKind` is
|
|
335
329
|
// a list concern (the sidebar row) and does not ride the detail.
|
package/src/execution/README.md
CHANGED
package/src/execution/schemas.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { z } from "zod";
|
|
11
|
+
import { IsoDateTimeWithOffset } from "../api/primitives";
|
|
11
12
|
|
|
12
13
|
import type { ExecutionResultData } from "../message-parts/execution";
|
|
13
14
|
import type { ExecutionKind } from "./kinds";
|
|
@@ -22,8 +23,8 @@ export const ExecutionSummarySchema = z.object({
|
|
|
22
23
|
executionId: z.string().uuid(),
|
|
23
24
|
kind: z.string(),
|
|
24
25
|
status: z.enum(["pending", "succeeded", "failed"]),
|
|
25
|
-
decidedAt:
|
|
26
|
-
completedAt:
|
|
26
|
+
decidedAt: IsoDateTimeWithOffset,
|
|
27
|
+
completedAt: IsoDateTimeWithOffset.optional(),
|
|
27
28
|
target: z.object({ type: z.string() }),
|
|
28
29
|
});
|
|
29
30
|
|
package/src/execution/sse.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { z } from "zod";
|
|
18
|
+
import { IsoDateTimeWithOffset } from "../api/primitives";
|
|
18
19
|
import { ExecutionEventTypeSchema } from "./events";
|
|
19
20
|
import { ExecutionStateSchema } from "./status";
|
|
20
21
|
|
|
@@ -27,7 +28,7 @@ export const ExecutionSseEventSchema = z.object({
|
|
|
27
28
|
/** Coarse actor class that produced the event (e.g. `user`, `system`). */
|
|
28
29
|
actorType: z.string(),
|
|
29
30
|
/** DB insert time of the event, ISO-8601 with offset. */
|
|
30
|
-
createdAt:
|
|
31
|
+
createdAt: IsoDateTimeWithOffset,
|
|
31
32
|
});
|
|
32
33
|
|
|
33
34
|
export type ExecutionSseEvent = z.infer<typeof ExecutionSseEventSchema>;
|
package/src/identity/README.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* @see ADR-CONT-032 for identity vocabulary design rationale
|
|
18
18
|
*/
|
|
19
19
|
import { z } from "zod";
|
|
20
|
+
import { IsoDateTime } from "../api/primitives";
|
|
20
21
|
|
|
21
22
|
// ---------------------------------------------------------------------------
|
|
22
23
|
// IdentityLink — external system id → Person
|
|
@@ -31,8 +32,8 @@ export const IdentityLinkSchema = z.object({
|
|
|
31
32
|
externalId: z.string().min(1),
|
|
32
33
|
// The Person this external identity resolves to (Person.id).
|
|
33
34
|
personId: z.string().uuid(),
|
|
34
|
-
createdAt:
|
|
35
|
-
updatedAt:
|
|
35
|
+
createdAt: IsoDateTime,
|
|
36
|
+
updatedAt: IsoDateTime,
|
|
36
37
|
});
|
|
37
38
|
|
|
38
39
|
export type IdentityLink = z.infer<typeof IdentityLinkSchema>;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { z } from "zod";
|
|
12
|
+
import { IsoDateTimeWithOffset } from "../api/primitives";
|
|
12
13
|
|
|
13
14
|
export const ImpersonationSessionSchema = z.object({
|
|
14
15
|
impersonationSessionId: z.string(),
|
|
@@ -16,9 +17,9 @@ export const ImpersonationSessionSchema = z.object({
|
|
|
16
17
|
targetUserId: z.string(),
|
|
17
18
|
reason: z.string(),
|
|
18
19
|
reasonHash: z.string(),
|
|
19
|
-
startedAt:
|
|
20
|
-
expiresAt:
|
|
21
|
-
endedAt:
|
|
20
|
+
startedAt: IsoDateTimeWithOffset,
|
|
21
|
+
expiresAt: IsoDateTimeWithOffset,
|
|
22
|
+
endedAt: IsoDateTimeWithOffset.nullable(),
|
|
22
23
|
ipAddress: z.string(),
|
|
23
24
|
userAgent: z.string(),
|
|
24
25
|
});
|
|
@@ -48,9 +49,9 @@ export const ImpersonationSessionWireDtoSchema = z
|
|
|
48
49
|
.object({
|
|
49
50
|
id: z.string(),
|
|
50
51
|
targetUserId: z.string(),
|
|
51
|
-
startedAt:
|
|
52
|
-
expiresAt:
|
|
53
|
-
endedAt:
|
|
52
|
+
startedAt: IsoDateTimeWithOffset,
|
|
53
|
+
expiresAt: IsoDateTimeWithOffset,
|
|
54
|
+
endedAt: IsoDateTimeWithOffset.nullable(),
|
|
54
55
|
})
|
|
55
56
|
.strict();
|
|
56
57
|
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* stringified JSON blobs on the schema.
|
|
17
17
|
*/
|
|
18
18
|
import { z } from "zod";
|
|
19
|
+
import { IsoDateTime } from "../api/primitives";
|
|
19
20
|
|
|
20
21
|
// =============================================================================
|
|
21
22
|
// HR connection status
|
|
@@ -87,7 +88,7 @@ export const HrConnectionStatusSchema = z
|
|
|
87
88
|
description:
|
|
88
89
|
"Departments mirrored from the HR provider; null when never synced.",
|
|
89
90
|
}),
|
|
90
|
-
lastSyncAt:
|
|
91
|
+
lastSyncAt: IsoDateTime.nullable().meta({
|
|
91
92
|
description: "ISO timestamp of the last successful sync; null if never.",
|
|
92
93
|
}),
|
|
93
94
|
syncHealth: z.enum(["healthy", "degraded", "error"]).nullable().meta({
|
package/src/meetings/schemas.ts
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* stringified JSON blobs on the schema.
|
|
22
22
|
*/
|
|
23
23
|
import { z } from "zod";
|
|
24
|
+
import { IsoDateTime } from "../api/primitives";
|
|
24
25
|
|
|
25
26
|
// =============================================================================
|
|
26
27
|
// Recording identity
|
|
@@ -237,7 +238,7 @@ export const TranscriptionSessionGrantSchema = z
|
|
|
237
238
|
sessionId: RecordingIdSchema,
|
|
238
239
|
connectUrl: z.string().url(),
|
|
239
240
|
authHeaders: z.record(z.string(), z.string()),
|
|
240
|
-
expiresAt:
|
|
241
|
+
expiresAt: IsoDateTime,
|
|
241
242
|
audioConfig: z.object({
|
|
242
243
|
sampleRateHz: z.literal(16000),
|
|
243
244
|
channels: z.literal(2),
|
|
@@ -279,8 +280,8 @@ export const MeetingMetadataProjectionSchema = z
|
|
|
279
280
|
visibility: MeetingVisibilitySchema,
|
|
280
281
|
status: RecordingStatusSchema,
|
|
281
282
|
quality: RecordingQualitySchema,
|
|
282
|
-
startedAt:
|
|
283
|
-
endedAt:
|
|
283
|
+
startedAt: IsoDateTime,
|
|
284
|
+
endedAt: IsoDateTime.nullable(),
|
|
284
285
|
durationMs: z.number().int().nonnegative(),
|
|
285
286
|
participantUserIds: z.array(z.string().uuid()),
|
|
286
287
|
transcriptAvailable: z.boolean(),
|
package/src/org/occupancy.ts
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* account.
|
|
26
26
|
*/
|
|
27
27
|
import { z } from "zod";
|
|
28
|
+
import { IsoDateTime } from "../api/primitives";
|
|
28
29
|
|
|
29
30
|
import { FactProvenanceSchema } from "./structure-facts";
|
|
30
31
|
|
|
@@ -60,9 +61,9 @@ export const OccupancySchema = z.object({
|
|
|
60
61
|
/** Lifecycle of this hold; only `active` makes the position occupied. */
|
|
61
62
|
status: OccupancyStatusSchema,
|
|
62
63
|
/** ISO start of the hold; `null`/absent when unknown or open-started. */
|
|
63
|
-
startsAt:
|
|
64
|
+
startsAt: IsoDateTime.nullable().optional(),
|
|
64
65
|
/** ISO end of the hold; `null`/absent while the hold is still open. */
|
|
65
|
-
endsAt:
|
|
66
|
+
endsAt: IsoDateTime.nullable().optional(),
|
|
66
67
|
/** Provenance of this occupancy fact (truth hierarchy + supersede model). */
|
|
67
68
|
provenance: FactProvenanceSchema,
|
|
68
69
|
});
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* `inferenceType` and is not part of the stable contract surface.
|
|
21
21
|
*/
|
|
22
22
|
import { z } from "zod";
|
|
23
|
+
import { IsoDateTime } from "../api/primitives";
|
|
23
24
|
|
|
24
25
|
// ---------------------------------------------------------------------------
|
|
25
26
|
// OrgStructureReviewInference — one pending ('review') structure inference
|
|
@@ -43,7 +44,7 @@ export const OrgStructureReviewInferenceSchema = z.object({
|
|
|
43
44
|
/** Human-meaningful WHY the engine proposed this change. */
|
|
44
45
|
reason: z.string(),
|
|
45
46
|
/** ISO timestamp the inference was created. */
|
|
46
|
-
createdAt:
|
|
47
|
+
createdAt: IsoDateTime,
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
export type OrgStructureReviewInference = z.infer<
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
* remove an entry is the two sides agreeing.
|
|
40
40
|
*/
|
|
41
41
|
import { z } from "zod";
|
|
42
|
+
import { IsoDateTime } from "../api/primitives";
|
|
42
43
|
|
|
43
44
|
import { FactSourceTierSchema } from "./structure-facts";
|
|
44
45
|
|
|
@@ -92,7 +93,7 @@ export const OrgDivergenceSchema = z.object({
|
|
|
92
93
|
*/
|
|
93
94
|
reason: z.string().max(2000).nullable(),
|
|
94
95
|
/** ISO timestamp the workspace's current word on this field was recorded. */
|
|
95
|
-
recordedAt:
|
|
96
|
+
recordedAt: IsoDateTime,
|
|
96
97
|
/**
|
|
97
98
|
* ISO timestamp someone in this workspace ACKNOWLEDGED this entry, or `null`.
|
|
98
99
|
*
|
|
@@ -102,7 +103,7 @@ export const OrgDivergenceSchema = z.object({
|
|
|
102
103
|
* the entry — arrives unacknowledged, which is the right default for a
|
|
103
104
|
* statement nobody has read yet.
|
|
104
105
|
*/
|
|
105
|
-
acknowledgedAt:
|
|
106
|
+
acknowledgedAt: IsoDateTime.nullable(),
|
|
106
107
|
/** Who acknowledged it. `null` when nobody has, or when that user is gone. */
|
|
107
108
|
acknowledgedByUserId: z.string().uuid().nullable(),
|
|
108
109
|
});
|
|
@@ -146,7 +147,7 @@ export const ResolveOrgDivergenceResultSchema = z.object({
|
|
|
146
147
|
/** How it was resolved. Local decisions only — see the module docblock. */
|
|
147
148
|
resolution: OrgDivergenceResolutionSchema,
|
|
148
149
|
/** ISO timestamp the decision was recorded in this workspace. */
|
|
149
|
-
resolvedAt:
|
|
150
|
+
resolvedAt: IsoDateTime,
|
|
150
151
|
/**
|
|
151
152
|
* Whether anything was written back to the source system. Pinned to the
|
|
152
153
|
* literal `false`: the HRIS client is read-only and no write scope is
|
package/src/org/schemas.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* - scope-check.ts (GET /api/scope/check, POST /api/scope/check-batch)
|
|
12
12
|
*/
|
|
13
13
|
import { z } from "zod";
|
|
14
|
-
import { CursorPageSchema } from "../api/primitives";
|
|
14
|
+
import { CursorPageSchema, IsoDateTime } from "../api/primitives";
|
|
15
15
|
import { OrgChartRoleSchema } from "../permissions/orgchart-roles";
|
|
16
16
|
import { PositionRefSchema } from "../identity/position-ref";
|
|
17
17
|
|
|
@@ -1757,7 +1757,7 @@ export const OwnerAuthoritySchema = z.object({
|
|
|
1757
1757
|
* the projection read filters `expires_at > now()` — so a present value is
|
|
1758
1758
|
* always in the future.
|
|
1759
1759
|
*/
|
|
1760
|
-
expiresAt:
|
|
1760
|
+
expiresAt: IsoDateTime.nullable().optional(),
|
|
1761
1761
|
});
|
|
1762
1762
|
export type OwnerAuthority = z.infer<typeof OwnerAuthoritySchema>;
|
|
1763
1763
|
|
|
@@ -1817,7 +1817,7 @@ export const CreateDelegationRequestSchema = z.object({
|
|
|
1817
1817
|
* Optional ISO-8601 expiry. Omitted or `null` ⇒ a permanent delegation. The
|
|
1818
1818
|
* UI captures a date and sends end-of-day in the user's timezone.
|
|
1819
1819
|
*/
|
|
1820
|
-
expiresAt:
|
|
1820
|
+
expiresAt: IsoDateTime.nullable().optional(),
|
|
1821
1821
|
/**
|
|
1822
1822
|
* When true, the granted user is emailed a notification (carrying `note` as
|
|
1823
1823
|
* the message). Not persisted — it only gates the side-effect email. Omitted
|
|
@@ -1836,7 +1836,7 @@ export type CreateDelegationRequest = z.infer<
|
|
|
1836
1836
|
* on an existing delegate row.
|
|
1837
1837
|
*/
|
|
1838
1838
|
export const UpdateDelegationRequestSchema = z.object({
|
|
1839
|
-
expiresAt:
|
|
1839
|
+
expiresAt: IsoDateTime.nullable(),
|
|
1840
1840
|
});
|
|
1841
1841
|
export type UpdateDelegationRequest = z.infer<
|
|
1842
1842
|
typeof UpdateDelegationRequestSchema
|
package/src/org/sync-run.ts
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
* nullable string rather than wrapped in a page envelope.
|
|
27
27
|
*/
|
|
28
28
|
import { z } from "zod";
|
|
29
|
+
import { IsoDateTime } from "../api/primitives";
|
|
29
30
|
|
|
30
31
|
// ---------------------------------------------------------------------------
|
|
31
32
|
// SyncRunSummary — the outcome record of one adapter sync run
|
|
@@ -35,9 +36,9 @@ export const SyncRunSummarySchema = z.object({
|
|
|
35
36
|
/** Unique identifier for this sync run within the org graph. */
|
|
36
37
|
id: z.string().uuid(),
|
|
37
38
|
/** ISO start of the run. Always set once a run has begun. */
|
|
38
|
-
startedAt:
|
|
39
|
+
startedAt: IsoDateTime,
|
|
39
40
|
/** ISO end of the run; `null`/absent while the run is still in progress. */
|
|
40
|
-
endedAt:
|
|
41
|
+
endedAt: IsoDateTime.nullable().optional(),
|
|
41
42
|
/** Count of facts examined by the run (the denominator). */
|
|
42
43
|
processed: z.number().int().nonnegative(),
|
|
43
44
|
/** Count of facts that resulted in a real mutation (insert/supersede). */
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* permission_decisions; the UI never re-derives.
|
|
19
19
|
*/
|
|
20
20
|
import { z } from "zod";
|
|
21
|
+
import { IsoDateTime } from "../api/primitives";
|
|
21
22
|
import { AccessLevelSchema } from "./access-levels";
|
|
22
23
|
import { AccessSourceSchema } from "./access-source";
|
|
23
24
|
import { PrincipalSchema } from "./share-api";
|
|
@@ -51,7 +52,7 @@ export const RecentDecisionSchema = z.object({
|
|
|
51
52
|
allow: z.boolean(),
|
|
52
53
|
reason: z.string(),
|
|
53
54
|
source_chain: z.array(AccessSourceSchema),
|
|
54
|
-
decided_at:
|
|
55
|
+
decided_at: IsoDateTime,
|
|
55
56
|
});
|
|
56
57
|
export type RecentDecision = z.infer<typeof RecentDecisionSchema>;
|
|
57
58
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* changing (ADR-CONTRACTS-093).
|
|
22
22
|
*/
|
|
23
23
|
import { z } from "zod";
|
|
24
|
+
import { IsoDateTime } from "../api/primitives";
|
|
24
25
|
import { AccessLevelSchema } from "./access-levels";
|
|
25
26
|
import { AccessSourceSchema } from "./access-source";
|
|
26
27
|
|
|
@@ -77,7 +78,7 @@ export const AclGrantResponseSchema = z.object({
|
|
|
77
78
|
principal: PrincipalSchema,
|
|
78
79
|
access_level: GrantableAccessLevelSchema,
|
|
79
80
|
granted_by_user_id: z.string().uuid(),
|
|
80
|
-
granted_at:
|
|
81
|
+
granted_at: IsoDateTime,
|
|
81
82
|
});
|
|
82
83
|
export type AclGrantResponse = z.infer<typeof AclGrantResponseSchema>;
|
|
83
84
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* `./secret.ts`) before storage / encryption.
|
|
14
14
|
*/
|
|
15
15
|
import { z } from "zod";
|
|
16
|
+
import { IsoDateTime } from "../api/primitives";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Usage class of an org secret. Drives which resolver layer is allowed to read
|
|
@@ -75,10 +76,10 @@ export const OrgSecretSummarySchema = z.object({
|
|
|
75
76
|
maskedPrefix: z.string().min(1).max(64),
|
|
76
77
|
version: z.number().int().positive(),
|
|
77
78
|
enabled: z.boolean(),
|
|
78
|
-
lastUsedAt:
|
|
79
|
+
lastUsedAt: IsoDateTime.nullable(),
|
|
79
80
|
usageCount: z.string(),
|
|
80
|
-
rotatedAt:
|
|
81
|
-
createdAt:
|
|
81
|
+
rotatedAt: IsoDateTime.nullable(),
|
|
82
|
+
createdAt: IsoDateTime,
|
|
82
83
|
});
|
|
83
84
|
export type OrgSecretSummary = z.infer<typeof OrgSecretSummarySchema>;
|
|
84
85
|
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
* stream without first giving it a real commit-ordered log.
|
|
30
30
|
*/
|
|
31
31
|
import { z } from "zod";
|
|
32
|
+
import { IsoDateTime } from "../api/primitives";
|
|
32
33
|
import type { ResourceKey } from "../resource-keys";
|
|
33
34
|
import { isResourceKeyShape } from "../resource-keys";
|
|
34
35
|
|
|
@@ -36,7 +37,6 @@ import { isResourceKeyShape } from "../resource-keys";
|
|
|
36
37
|
* Local, not chat's. `chat/schemas.ts` owns a structurally identical helper;
|
|
37
38
|
* importing it would make a chat frame change a user-events breaking change.
|
|
38
39
|
*/
|
|
39
|
-
const IsoDateString = z.string().datetime();
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Fields every frame carries.
|
|
@@ -47,7 +47,7 @@ const IsoDateString = z.string().datetime();
|
|
|
47
47
|
*/
|
|
48
48
|
export const UserEventBaseSchema = z.object({
|
|
49
49
|
v: z.literal(1),
|
|
50
|
-
timestamp:
|
|
50
|
+
timestamp: IsoDateTime,
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
// =============================================================================
|