Skip to content

Commit c0935fb

Browse files
Copilothotlong
andcommitted
Add P0 Missing Protocols: Notification, Document, Change Management, External Lookup
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 2579e24 commit c0935fb

10 files changed

Lines changed: 3893 additions & 1 deletion

packages/spec/src/data/document.test.ts

Lines changed: 624 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
import { z } from 'zod';
2+
3+
/**
4+
* Document Version Schema
5+
*
6+
* Represents a single version of a document in a version-controlled system.
7+
* Each version is immutable and maintains its own metadata and download URL.
8+
*
9+
* @example
10+
* ```json
11+
* {
12+
* "versionNumber": 2,
13+
* "createdAt": 1704067200000,
14+
* "createdBy": "user_123",
15+
* "size": 2048576,
16+
* "checksum": "a1b2c3d4e5f6",
17+
* "downloadUrl": "https://storage.example.com/docs/v2/file.pdf",
18+
* "isLatest": true
19+
* }
20+
* ```
21+
*/
22+
export const DocumentVersionSchema = z.object({
23+
/**
24+
* Sequential version number (increments with each new version)
25+
*/
26+
versionNumber: z.number().describe('Version number'),
27+
28+
/**
29+
* Timestamp when this version was created (Unix milliseconds)
30+
*/
31+
createdAt: z.number().describe('Creation timestamp'),
32+
33+
/**
34+
* User ID who created this version
35+
*/
36+
createdBy: z.string().describe('Creator user ID'),
37+
38+
/**
39+
* File size in bytes
40+
*/
41+
size: z.number().describe('File size in bytes'),
42+
43+
/**
44+
* Checksum/hash of the file content (for integrity verification)
45+
*/
46+
checksum: z.string().describe('File checksum'),
47+
48+
/**
49+
* URL to download this specific version
50+
*/
51+
downloadUrl: z.string().url().describe('Download URL'),
52+
53+
/**
54+
* Whether this is the latest version
55+
* @default false
56+
*/
57+
isLatest: z.boolean().optional().default(false).describe('Is latest version'),
58+
});
59+
60+
/**
61+
* Document Template Schema
62+
*
63+
* Defines a reusable document template with dynamic placeholders.
64+
* Templates can be used to generate documents with variable content.
65+
*
66+
* @example
67+
* ```json
68+
* {
69+
* "id": "contract-template",
70+
* "name": "Service Agreement",
71+
* "description": "Standard service agreement template",
72+
* "fileUrl": "https://example.com/templates/contract.docx",
73+
* "fileType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
74+
* "placeholders": [
75+
* {
76+
* "key": "client_name",
77+
* "label": "Client Name",
78+
* "type": "text",
79+
* "required": true
80+
* },
81+
* {
82+
* "key": "contract_date",
83+
* "label": "Contract Date",
84+
* "type": "date",
85+
* "required": true
86+
* }
87+
* ]
88+
* }
89+
* ```
90+
*/
91+
export const DocumentTemplateSchema = z.object({
92+
/**
93+
* Unique identifier for the template
94+
*/
95+
id: z.string().describe('Template ID'),
96+
97+
/**
98+
* Human-readable name of the template
99+
*/
100+
name: z.string().describe('Template name'),
101+
102+
/**
103+
* Optional description of the template's purpose
104+
*/
105+
description: z.string().optional().describe('Template description'),
106+
107+
/**
108+
* URL to the template file
109+
*/
110+
fileUrl: z.string().url().describe('Template file URL'),
111+
112+
/**
113+
* MIME type of the template file
114+
*/
115+
fileType: z.string().describe('File MIME type'),
116+
117+
/**
118+
* List of dynamic placeholders in the template
119+
*/
120+
placeholders: z.array(z.object({
121+
/**
122+
* Placeholder identifier (used in template)
123+
*/
124+
key: z.string().describe('Placeholder key'),
125+
126+
/**
127+
* Human-readable label for the placeholder
128+
*/
129+
label: z.string().describe('Placeholder label'),
130+
131+
/**
132+
* Data type of the placeholder value
133+
*/
134+
type: z.enum(['text', 'number', 'date', 'image']).describe('Placeholder type'),
135+
136+
/**
137+
* Whether this placeholder must be filled
138+
* @default false
139+
*/
140+
required: z.boolean().optional().default(false).describe('Is required'),
141+
})).describe('Template placeholders'),
142+
});
143+
144+
/**
145+
* E-Signature Configuration Schema
146+
*
147+
* Configuration for electronic signature workflows.
148+
* Supports integration with popular e-signature providers.
149+
*
150+
* @example
151+
* ```json
152+
* {
153+
* "provider": "docusign",
154+
* "enabled": true,
155+
* "signers": [
156+
* {
157+
* "email": "client@example.com",
158+
* "name": "John Doe",
159+
* "role": "Client",
160+
* "order": 1
161+
* },
162+
* {
163+
* "email": "manager@example.com",
164+
* "name": "Jane Smith",
165+
* "role": "Manager",
166+
* "order": 2
167+
* }
168+
* ],
169+
* "expirationDays": 30,
170+
* "reminderDays": 7
171+
* }
172+
* ```
173+
*/
174+
export const ESignatureConfigSchema = z.object({
175+
/**
176+
* E-signature service provider
177+
*/
178+
provider: z.enum(['docusign', 'adobe-sign', 'hellosign', 'custom']).describe('E-signature provider'),
179+
180+
/**
181+
* Whether e-signature is enabled for this document
182+
* @default false
183+
*/
184+
enabled: z.boolean().optional().default(false).describe('E-signature enabled'),
185+
186+
/**
187+
* List of signers in signing order
188+
*/
189+
signers: z.array(z.object({
190+
/**
191+
* Signer's email address
192+
*/
193+
email: z.string().email().describe('Signer email'),
194+
195+
/**
196+
* Signer's full name
197+
*/
198+
name: z.string().describe('Signer name'),
199+
200+
/**
201+
* Signer's role in the document
202+
*/
203+
role: z.string().describe('Signer role'),
204+
205+
/**
206+
* Signing order (lower numbers sign first)
207+
*/
208+
order: z.number().describe('Signing order'),
209+
})).describe('Document signers'),
210+
211+
/**
212+
* Days until signature request expires
213+
* @default 30
214+
*/
215+
expirationDays: z.number().optional().default(30).describe('Expiration days'),
216+
217+
/**
218+
* Days between reminder emails
219+
* @default 7
220+
*/
221+
reminderDays: z.number().optional().default(7).describe('Reminder interval days'),
222+
});
223+
224+
/**
225+
* Document Schema
226+
*
227+
* Comprehensive document management protocol supporting versioning,
228+
* templates, e-signatures, and access control.
229+
*
230+
* @example
231+
* ```json
232+
* {
233+
* "id": "doc_123",
234+
* "name": "Service Agreement 2024",
235+
* "description": "Annual service agreement",
236+
* "fileType": "application/pdf",
237+
* "fileSize": 1048576,
238+
* "category": "contracts",
239+
* "tags": ["legal", "2024", "services"],
240+
* "versioning": {
241+
* "enabled": true,
242+
* "versions": [
243+
* {
244+
* "versionNumber": 1,
245+
* "createdAt": 1704067200000,
246+
* "createdBy": "user_123",
247+
* "size": 1048576,
248+
* "checksum": "abc123",
249+
* "downloadUrl": "https://example.com/docs/v1.pdf",
250+
* "isLatest": true
251+
* }
252+
* ],
253+
* "majorVersion": 1,
254+
* "minorVersion": 0
255+
* },
256+
* "access": {
257+
* "isPublic": false,
258+
* "sharedWith": ["user_456", "team_789"],
259+
* "expiresAt": 1735689600000
260+
* },
261+
* "metadata": {
262+
* "author": "John Doe",
263+
* "department": "Legal"
264+
* }
265+
* }
266+
* ```
267+
*/
268+
export const DocumentSchema = z.object({
269+
/**
270+
* Unique document identifier
271+
*/
272+
id: z.string().describe('Document ID'),
273+
274+
/**
275+
* Document name
276+
*/
277+
name: z.string().describe('Document name'),
278+
279+
/**
280+
* Optional document description
281+
*/
282+
description: z.string().optional().describe('Document description'),
283+
284+
/**
285+
* MIME type of the document
286+
*/
287+
fileType: z.string().describe('File MIME type'),
288+
289+
/**
290+
* File size in bytes
291+
*/
292+
fileSize: z.number().describe('File size in bytes'),
293+
294+
/**
295+
* Document category for organization
296+
*/
297+
category: z.string().optional().describe('Document category'),
298+
299+
/**
300+
* Tags for searchability and organization
301+
*/
302+
tags: z.array(z.string()).optional().describe('Document tags'),
303+
304+
/**
305+
* Version control configuration
306+
*/
307+
versioning: z.object({
308+
/**
309+
* Whether versioning is enabled
310+
*/
311+
enabled: z.boolean().describe('Versioning enabled'),
312+
313+
/**
314+
* List of all document versions
315+
*/
316+
versions: z.array(DocumentVersionSchema).describe('Version history'),
317+
318+
/**
319+
* Current major version number
320+
*/
321+
majorVersion: z.number().describe('Major version'),
322+
323+
/**
324+
* Current minor version number
325+
*/
326+
minorVersion: z.number().describe('Minor version'),
327+
}).optional().describe('Version control'),
328+
329+
/**
330+
* Template configuration (if document is generated from template)
331+
*/
332+
template: DocumentTemplateSchema.optional().describe('Document template'),
333+
334+
/**
335+
* E-signature configuration
336+
*/
337+
eSignature: ESignatureConfigSchema.optional().describe('E-signature config'),
338+
339+
/**
340+
* Access control settings
341+
*/
342+
access: z.object({
343+
/**
344+
* Whether document is publicly accessible
345+
* @default false
346+
*/
347+
isPublic: z.boolean().optional().default(false).describe('Public access'),
348+
349+
/**
350+
* List of user/team IDs with access
351+
*/
352+
sharedWith: z.array(z.string()).optional().describe('Shared with'),
353+
354+
/**
355+
* Timestamp when access expires (Unix milliseconds)
356+
*/
357+
expiresAt: z.number().optional().describe('Access expiration'),
358+
}).optional().describe('Access control'),
359+
360+
/**
361+
* Custom metadata fields
362+
*/
363+
metadata: z.record(z.any()).optional().describe('Custom metadata'),
364+
});
365+
366+
// Type exports
367+
export type Document = z.infer<typeof DocumentSchema>;
368+
export type DocumentVersion = z.infer<typeof DocumentVersionSchema>;
369+
export type DocumentTemplate = z.infer<typeof DocumentTemplateSchema>;
370+
export type ESignatureConfig = z.infer<typeof ESignatureConfigSchema>;

0 commit comments

Comments
 (0)