@anchrd/intel-contract 0.13.0 → 0.15.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.
@@ -0,0 +1,310 @@
1
+ import { z } from "zod";
2
+ import { IdempotencyKey, IntelId, IsoDateTime } from "./contract.js";
3
+ // What this installation is equipped to do — deployment facts, never the caller's permissions
4
+ // (those stay behind each door, where `/session` deliberately does not carry them). `agentRuntime`
5
+ // says whether an agent Worker is bound at all (#190): without it the UI offers no "New agent" and
6
+ // an agent node explains itself instead of rendering views that could only end in a 503.
7
+ // The fourth kind is `table` (#40), the fifth is `agent` (#139) and the sixth is `board` (#285).
8
+ // Each is a kind of node, not a kind of thing: it hangs in the same folder tree, inherits the same
9
+ // folder grants, carries the same immutable versions and the same R2 body as a document
10
+ // (ADR-0004 §1, ADR-0005 §1). Only the media type and the operations below differ.
11
+ //
12
+ // ⚠️ `agent` being optional is load-bearing (ADR-0005 §1): an installation without a single agent
13
+ // node is complete, not unfinished, and nothing here asks anyone to classify a document as a skill
14
+ // or a policy in order to file it. The same holds for `board`: it is a file somebody may make, not
15
+ // a place the tree grows a special corner for — which is exactly why a board is one node carrying
16
+ // its tasks and not a folder that only tasks may live in (#285).
17
+ export const NodeKind = z.enum(["folder", "document", "attachment", "table"]);
18
+ export const Node = z.strictObject({
19
+ id: IntelId,
20
+ parentId: IntelId.nullable(),
21
+ kind: NodeKind,
22
+ title: z.string().min(1).max(240),
23
+ description: z.string().max(2_000).nullable(),
24
+ ownerId: IntelId,
25
+ currentVersionId: IntelId.nullable(),
26
+ createdAt: IsoDateTime,
27
+ updatedAt: IsoDateTime,
28
+ archivedAt: IsoDateTime.nullable(),
29
+ });
30
+ // What one table version carries (#135). An `append` holds only the rows one write added; a
31
+ // `snapshot` holds the complete table — header and every row — so reading starts at the newest
32
+ // snapshot and everything before it is history rather than content. Defining a table writes the
33
+ // first snapshot; updating, deleting, and redefining write the later ones. Documents and
34
+ // attachments carry `null`: each of their versions is complete by construction, and the word would
35
+ // say nothing about them.
36
+ export const NodeVersionSegment = z.enum(["append", "snapshot"]);
37
+ export const NodeVersion = z.strictObject({
38
+ id: IntelId,
39
+ nodeId: IntelId,
40
+ sequence: z.number().int().positive(),
41
+ contentKey: z.string().min(1),
42
+ mediaType: z.string().min(1).max(160),
43
+ contentHash: z.string().regex(/^[a-f0-9]{64}$/),
44
+ size: z.number().int().nonnegative(),
45
+ segment: NodeVersionSegment.nullable(),
46
+ createdBy: IntelId,
47
+ createdAt: IsoDateTime,
48
+ });
49
+ export const ListNodesInput = z.strictObject({
50
+ parentId: IntelId.nullable()
51
+ .default(null)
52
+ .describe("Folder to list the direct children of. `null` lists the top level."),
53
+ includeArchived: z
54
+ .boolean()
55
+ .default(false)
56
+ .describe("Include archived nodes beside the live ones instead of hiding them."),
57
+ // ⚠️ Overrides `parentId` rather than narrowing beside it: what is archived is asked for across
58
+ // the whole tree, because that is the only useful question. Somebody looking for what they threw
59
+ // away does not know which folder it was in — if they did, they would not be looking (#113).
60
+ // A separate flag rather than a third state on `includeArchived`, so no existing caller changes
61
+ // meaning — and `.optional()` rather than `.default(false)` for the same reason `ListFlowsInput`
62
+ // carries it that way: a default makes the field required in the PARSED type, and every existing
63
+ // caller would have to answer a question it is not asking.
64
+ archivedOnly: z
65
+ .boolean()
66
+ .optional()
67
+ .describe("List only archived nodes, across the whole tree. Overrides parentId rather than narrowing it: somebody looking for what they threw away does not know which folder it was in."),
68
+ });
69
+ export const GetNodeInput = z.strictObject({
70
+ nodeId: IntelId.describe("Node to read, from node_list or search."),
71
+ });
72
+ // One pinned version of one node (#147). Both IDs, always: a version ID alone would let anyone
73
+ // holding an ID read content whose node-level ACL they never passed, and a citation names both.
74
+ export const GetNodeVersionInput = z.strictObject({
75
+ nodeId: IntelId.describe("Node the version belongs to. Required even though the version id is unique: access is decided on the node."),
76
+ versionId: IntelId.describe("Version to read, from node_version_list or a search citation."),
77
+ });
78
+ export const CreateNodeInput = z.strictObject({
79
+ parentId: IntelId.nullable()
80
+ .default(null)
81
+ .describe("Folder to file the new node in. `null` puts it at the top level."),
82
+ kind: NodeKind.describe("What the node is. A folder holds others and has no content; document, attachment and table each carry their own body, written afterwards by node_version_create, node_attachment_create or node_table_create."),
83
+ title: z
84
+ .string()
85
+ .trim()
86
+ .min(1)
87
+ .max(240)
88
+ .describe("What the node is called. Shown in the tree and searched."),
89
+ description: z
90
+ .string()
91
+ .trim()
92
+ .max(2_000)
93
+ .nullable()
94
+ .default(null)
95
+ .describe("Optional sentence about the node, for readers rather than for search ranking."),
96
+ idempotencyKey: IdempotencyKey,
97
+ });
98
+ /**
99
+ * The version a write is made against, in the one form both writers of node content take it.
100
+ *
101
+ * ⚠️ Nullable and required are not the same thing, and here they stand together (#437). `null` is
102
+ * how a node that has no version yet is addressed, and it is the only way to write its first
103
+ * content; leaving the field out says nothing at all and is refused. Whoever leaves it out is
104
+ * almost always holding a node created one call earlier, and the plain type error they used to get
105
+ * — "expected string, received undefined" — reads as "this field must be an id", about a field that
106
+ * cannot have one yet. Both refusals therefore name both ways instead.
107
+ *
108
+ * ⚠️ It stays required once a version exists, and that is what it is for: a mismatch is answered
109
+ * with a `409` rather than by overwriting somebody else's newer version.
110
+ *
111
+ * ⚠️ The bounds remain `IntelId`'s. The repeated `min(1)` adds no rule — it only puts the sentence
112
+ * on the second value that gets tried after `undefined`, the empty string.
113
+ *
114
+ * ⚠️ The sentence says what the field TAKES, not what the caller did wrong. It answers a wrong type
115
+ * as well as an absent field, and "is required" would be false about the first — which would be
116
+ * this same ticket one corner further on. A value that is merely too long keeps Zod's own `Too
117
+ * big`: that one is already a true statement about what was sent.
118
+ */
119
+ function baseVersion(rule) {
120
+ return z.union([IntelId.min(1, { error: rule }), z.null()], { error: rule });
121
+ }
122
+ export const SaveNodeVersionInput = z.strictObject({
123
+ nodeId: IntelId.describe("Document node to append a version to."),
124
+ baseVersionId: baseVersion("baseVersionId takes the `currentVersionId` from node_get, or null when the node has no version yet — and it has to be sent.").describe("The version this edit was made against — `currentVersionId` from node_get. If the node has moved on since, the call is refused rather than overwriting the newer version; pass `null` only for a node that has no version yet."),
125
+ content: z
126
+ .string()
127
+ .max(10_000_000)
128
+ .describe("The complete new content. Versions are whole documents, not patches."),
129
+ mediaType: z
130
+ .string()
131
+ .min(1)
132
+ .max(160)
133
+ .default("text/markdown")
134
+ .describe("Media type of `content`. Leave at text/markdown unless writing another format."),
135
+ idempotencyKey: IdempotencyKey,
136
+ });
137
+ export const SaveAttachmentInput = z.strictObject({
138
+ nodeId: IntelId.describe("Attachment node to append bytes to."),
139
+ baseVersionId: baseVersion("baseVersionId takes the `currentVersionId` from node_get, or null for the first upload — and it has to be sent.").describe("The version these bytes replace — `currentVersionId` from node_get, or `null` for the first upload. A stale value is refused rather than overwriting."),
140
+ contentBase64: z
141
+ .string()
142
+ .min(1)
143
+ .max(20_000_000)
144
+ .describe("The file, base64-encoded. Around 15 MB of bytes; larger files take the HTTP door, which streams."),
145
+ mediaType: z
146
+ .string()
147
+ .min(1)
148
+ .max(160)
149
+ .describe("Media type of the decoded bytes, e.g. application/pdf."),
150
+ idempotencyKey: IdempotencyKey,
151
+ });
152
+ export const UpdateNodeInput = z
153
+ .strictObject({
154
+ nodeId: IntelId.describe("Node to change."),
155
+ baseUpdatedAt: IsoDateTime.describe("`updatedAt` as node_get last reported it. A newer value on the server means somebody else changed the node first and the call is refused."),
156
+ title: z
157
+ .string()
158
+ .trim()
159
+ .min(1)
160
+ .max(240)
161
+ .optional()
162
+ .describe("New title. Omit to leave it as it is."),
163
+ description: z
164
+ .string()
165
+ .trim()
166
+ .max(2_000)
167
+ .nullable()
168
+ .optional()
169
+ .describe("New description, or `null` to clear it. Omit to leave it as it is."),
170
+ parentId: IntelId.nullable()
171
+ .optional()
172
+ .describe("Folder to move the node into, or `null` for the top level. Omit to leave it where it is."),
173
+ idempotencyKey: IdempotencyKey,
174
+ })
175
+ .refine((input) => input.title !== undefined || input.description !== undefined || input.parentId !== undefined, { message: "At least one change is required" });
176
+ export const ArchiveNodeInput = z.strictObject({
177
+ nodeId: IntelId.describe("Node to archive or restore."),
178
+ baseUpdatedAt: IsoDateTime.describe("`updatedAt` as node_get last reported it. A newer value on the server means somebody else changed the node first and the call is refused."),
179
+ archived: z
180
+ .boolean()
181
+ .describe("`true` archives the node, `false` restores it. Archiving hides a node from listings and search; nothing is deleted and every version stays readable."),
182
+ idempotencyKey: IdempotencyKey,
183
+ });
184
+ // ⚠️ `withChildren` belongs to the LEVEL, not to the node (#59). Whether something has children
185
+ // THIS reader may see is not a property of the thing — two readers get different answers. As a
186
+ // field on the node, every other place that returns a node would have to compute it as well or
187
+ // lie; as a list beside the entries it costs only the one answer that needs it.
188
+ export const NodeList = z.strictObject({
189
+ items: z.array(Node),
190
+ withChildren: z.array(IntelId).default([]),
191
+ });
192
+ export const NodeVersionList = z.strictObject({ items: z.array(NodeVersion) });
193
+ export const NodeDocument = z.strictObject({
194
+ node: Node,
195
+ version: NodeVersion.nullable(),
196
+ content: z.string().nullable(),
197
+ });
198
+ export const NodeAttachment = z.strictObject({
199
+ node: Node,
200
+ version: NodeVersion,
201
+ resourceUri: z.string().regex(/^intel:\/\/nodes\/[^/]+\/attachment$/),
202
+ });
203
+ // The table as a grid rather than as text: the server owns the one CSV reader, so no surface has to
204
+ // grow a second one that would disagree with it about quoting.
205
+ export const NodeTable = z.strictObject({
206
+ node: Node,
207
+ columns: z.array(z.string()),
208
+ rows: z.array(z.array(z.string())),
209
+ // The newest append, or `null` while the table has no header yet.
210
+ versionId: IntelId.nullable(),
211
+ });
212
+ export const NodeLinkRelation = z.enum(["references", "related", "depends_on", "implements"]);
213
+ // Where the link came from. `text` links are derived from a document's content and are rewritten
214
+ // whenever it is saved; `manual` links were made in the dialog #41 removed and are now history.
215
+ //
216
+ // ⚠️ This is provenance, never a second sort of relationship. Nothing offers the reader a choice
217
+ // between them, and nothing may start writing `manual` again — that would be the two ways of saying
218
+ // one thing that #41 exists to end. It exists so that saving a document cannot delete a link
219
+ // somebody made before there was another way to make one.
220
+ export const NodeLinkOrigin = z.enum(["text", "manual"]);
221
+ export const NodeLink = z.strictObject({
222
+ id: IntelId,
223
+ sourceNodeId: IntelId,
224
+ targetNodeId: IntelId,
225
+ relation: NodeLinkRelation,
226
+ origin: NodeLinkOrigin,
227
+ label: z.string().trim().min(1).max(120).nullable(),
228
+ createdBy: IntelId,
229
+ createdAt: IsoDateTime,
230
+ });
231
+ export const NodeLinkList = z.strictObject({ items: z.array(NodeLink) });
232
+ // The inline element a document link is, inside a BlockNote document (#41).
233
+ //
234
+ // ⚠️ The ID and nothing else. No title and no path travel with it: a stored title would go stale
235
+ // the moment the target is renamed, a stored path the moment it is moved — and either one would
236
+ // put a name the reader may not see into a document they may.
237
+ export const DocumentLinkInlineType = "documentLink";
238
+ export const ResolveNodeLinksInput = z.strictObject({
239
+ nodeIds: z
240
+ .array(IntelId)
241
+ .min(1)
242
+ .max(200)
243
+ .describe("The link targets to name, as found in a document's documentLink elements. Unreachable and deleted targets are simply absent from the answer, so a shorter list than asked for is normal."),
244
+ });
245
+ export const ResolvedNodeLink = z.strictObject({
246
+ nodeId: IntelId,
247
+ title: z.string().min(1).max(240),
248
+ });
249
+ // ⚠️ Only what the asking reader may see is in here, and an unreachable target is simply absent —
250
+ // never a row with an empty title, never a count, never a "restricted" marker. The list is what one
251
+ // side of a document link is drawn from, and an entry that says "something is here" is exactly the
252
+ // leak this schema has to make impossible to write by accident. Deleted and unreadable therefore
253
+ // look identical from the outside, which is the point.
254
+ export const ResolveNodeLinksResult = z.strictObject({
255
+ items: z.array(ResolvedNodeLink),
256
+ });
257
+ export const NodeGraphInput = z.strictObject({
258
+ limit: z
259
+ .number()
260
+ .int()
261
+ .min(1)
262
+ .max(500)
263
+ .default(250)
264
+ .describe("How many nodes the graph may carry. The links returned are the ones between them."),
265
+ });
266
+ export const NodeGraph = z.strictObject({
267
+ nodes: z.array(Node),
268
+ links: z.array(NodeLink),
269
+ });
270
+ export const BlockNoteMediaType = "application/vnd.anchrd.intel.blocknote+json";
271
+ export const BlockNoteDocument = z.strictObject({
272
+ format: z.literal("blocknote"),
273
+ schemaVersion: z.literal(1),
274
+ blocks: z.array(z.record(z.string(), z.unknown())),
275
+ markdown: z.string(),
276
+ });
277
+ // `scopeId` is a cut, never a grant (#126): it narrows an answer the actor is already entitled to
278
+ // and can only ever remove rows. Without it the search stays global over everything visible, which
279
+ // is why it is optional rather than nullable — an absent field and `null` would otherwise be two
280
+ // spellings of the same request.
281
+ export const SearchInput = z.strictObject({
282
+ query: z
283
+ .string()
284
+ .trim()
285
+ .min(1)
286
+ .max(500)
287
+ .describe("What to look for, in the reader's own words. Matched both lexically and semantically, so a question works as well as keywords."),
288
+ limit: z
289
+ .number()
290
+ .int()
291
+ .min(1)
292
+ .max(50)
293
+ .default(10)
294
+ .describe("How many citations to return, best first."),
295
+ scopeId: IntelId.optional().describe("Optional folder node id. When given, only nodes filed in that folder or beneath it are searched."),
296
+ });
297
+ export const NodeCitation = z.strictObject({
298
+ nodeId: IntelId,
299
+ versionId: IntelId,
300
+ title: z.string(),
301
+ passage: z.string(),
302
+ source: z.string(),
303
+ freshness: IsoDateTime,
304
+ score: z.number().min(0).max(1),
305
+ match: z.enum(["lexical", "semantic", "hybrid"]),
306
+ });
307
+ export const SearchResult = z.strictObject({
308
+ items: z.array(NodeCitation),
309
+ });
310
+ export const ReindexResult = z.strictObject({ queued: z.number().int().nonnegative() });
@@ -0,0 +1,142 @@
1
+ import { z } from "zod";
2
+ export declare const ResourceVerb: z.ZodEnum<{
3
+ read: "read";
4
+ write: "write";
5
+ execute: "execute";
6
+ share: "share";
7
+ }>;
8
+ export type ResourceVerb = z.infer<typeof ResourceVerb>;
9
+ export declare const SharePrincipal: z.ZodDiscriminatedUnion<[z.ZodObject<{
10
+ type: z.ZodLiteral<"user">;
11
+ id: z.ZodString;
12
+ }, z.core.$strict>, z.ZodObject<{
13
+ type: z.ZodLiteral<"email">;
14
+ email: z.ZodEmail;
15
+ }, z.core.$strict>, z.ZodObject<{
16
+ type: z.ZodLiteral<"organization">;
17
+ }, z.core.$strict>], "type">;
18
+ export type SharePrincipal = z.infer<typeof SharePrincipal>;
19
+ export declare const ListGrantsInput: z.ZodObject<{
20
+ resourceId: z.ZodString;
21
+ }, z.core.$strict>;
22
+ export type ListGrantsInput = z.infer<typeof ListGrantsInput>;
23
+ export declare const ResourceGrant: z.ZodObject<{
24
+ id: z.ZodString;
25
+ resourceId: z.ZodString;
26
+ principal: z.ZodDiscriminatedUnion<[z.ZodObject<{
27
+ type: z.ZodLiteral<"user">;
28
+ id: z.ZodString;
29
+ }, z.core.$strict>, z.ZodObject<{
30
+ type: z.ZodLiteral<"email">;
31
+ email: z.ZodEmail;
32
+ }, z.core.$strict>, z.ZodObject<{
33
+ type: z.ZodLiteral<"organization">;
34
+ }, z.core.$strict>], "type">;
35
+ verb: z.ZodEnum<{
36
+ read: "read";
37
+ write: "write";
38
+ execute: "execute";
39
+ share: "share";
40
+ }>;
41
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
42
+ createdBy: z.ZodString;
43
+ createdAt: z.ZodISODateTime;
44
+ }, z.core.$strict>;
45
+ export type ResourceGrant = z.infer<typeof ResourceGrant>;
46
+ export declare const ShareInput: z.ZodObject<{
47
+ resourceId: z.ZodString;
48
+ principal: z.ZodDiscriminatedUnion<[z.ZodObject<{
49
+ type: z.ZodLiteral<"user">;
50
+ id: z.ZodString;
51
+ }, z.core.$strict>, z.ZodObject<{
52
+ type: z.ZodLiteral<"email">;
53
+ email: z.ZodEmail;
54
+ }, z.core.$strict>, z.ZodObject<{
55
+ type: z.ZodLiteral<"organization">;
56
+ }, z.core.$strict>], "type">;
57
+ verb: z.ZodEnum<{
58
+ read: "read";
59
+ write: "write";
60
+ execute: "execute";
61
+ share: "share";
62
+ }>;
63
+ expiresAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
64
+ idempotencyKey: z.ZodString;
65
+ }, z.core.$strict>;
66
+ export type ShareInput = z.infer<typeof ShareInput>;
67
+ export declare const RevokeGrantInput: z.ZodObject<{
68
+ resourceId: z.ZodString;
69
+ grantId: z.ZodString;
70
+ idempotencyKey: z.ZodString;
71
+ }, z.core.$strict>;
72
+ export type RevokeGrantInput = z.infer<typeof RevokeGrantInput>;
73
+ export declare const UnreadableNodes: z.ZodObject<{
74
+ titles: z.ZodArray<z.ZodString>;
75
+ hidden: z.ZodNumber;
76
+ }, z.core.$strict>;
77
+ export type UnreadableNodes = z.infer<typeof UnreadableNodes>;
78
+ export declare const ShareResult: z.ZodObject<{
79
+ grant: z.ZodObject<{
80
+ id: z.ZodString;
81
+ resourceId: z.ZodString;
82
+ principal: z.ZodDiscriminatedUnion<[z.ZodObject<{
83
+ type: z.ZodLiteral<"user">;
84
+ id: z.ZodString;
85
+ }, z.core.$strict>, z.ZodObject<{
86
+ type: z.ZodLiteral<"email">;
87
+ email: z.ZodEmail;
88
+ }, z.core.$strict>, z.ZodObject<{
89
+ type: z.ZodLiteral<"organization">;
90
+ }, z.core.$strict>], "type">;
91
+ verb: z.ZodEnum<{
92
+ read: "read";
93
+ write: "write";
94
+ execute: "execute";
95
+ share: "share";
96
+ }>;
97
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
98
+ createdBy: z.ZodString;
99
+ createdAt: z.ZodISODateTime;
100
+ }, z.core.$strict>;
101
+ unreadable: z.ZodObject<{
102
+ titles: z.ZodArray<z.ZodString>;
103
+ hidden: z.ZodNumber;
104
+ }, z.core.$strict>;
105
+ }, z.core.$strict>;
106
+ export type ShareResult = z.infer<typeof ShareResult>;
107
+ export declare const ResourceGrantList: z.ZodObject<{
108
+ resourceId: z.ZodString;
109
+ applicableVerbs: z.ZodArray<z.ZodEnum<{
110
+ read: "read";
111
+ write: "write";
112
+ execute: "execute";
113
+ share: "share";
114
+ }>>;
115
+ items: z.ZodArray<z.ZodObject<{
116
+ id: z.ZodString;
117
+ resourceId: z.ZodString;
118
+ principal: z.ZodDiscriminatedUnion<[z.ZodObject<{
119
+ type: z.ZodLiteral<"user">;
120
+ id: z.ZodString;
121
+ }, z.core.$strict>, z.ZodObject<{
122
+ type: z.ZodLiteral<"email">;
123
+ email: z.ZodEmail;
124
+ }, z.core.$strict>, z.ZodObject<{
125
+ type: z.ZodLiteral<"organization">;
126
+ }, z.core.$strict>], "type">;
127
+ verb: z.ZodEnum<{
128
+ read: "read";
129
+ write: "write";
130
+ execute: "execute";
131
+ share: "share";
132
+ }>;
133
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
134
+ createdBy: z.ZodString;
135
+ createdAt: z.ZodISODateTime;
136
+ }, z.core.$strict>>;
137
+ }, z.core.$strict>;
138
+ export type ResourceGrantList = z.infer<typeof ResourceGrantList>;
139
+ export declare const RevokeGrantResult: z.ZodObject<{
140
+ revoked: z.ZodBoolean;
141
+ }, z.core.$strict>;
142
+ export type RevokeGrantResult = z.infer<typeof RevokeGrantResult>;
@@ -0,0 +1,67 @@
1
+ import { z } from "zod";
2
+ import { IdempotencyKey, IntelId, IsoDateTime } from "./contract.js";
3
+ // ⚠️ There is no `ContextPolicy`, and it is not coming back in this shape (#76). It said whether a
4
+ // document should be pinned into a context, be found by relevance, or be named explicitly — an
5
+ // instruction to a retrieval Intel does not perform. Intel hands out references and the agent
6
+ // fetches what it needs (D24), so nothing here could ever have read it, and nothing did.
7
+ //
8
+ // Semantic search stays: as an MCP tool the agent calls, over everything or over one area.
9
+ // One verb per grant, granted independently (ADR-0004 §2). Not a ladder: seeing a process must be
10
+ // separable from being allowed to start it, and `execute` is meaningful only where a flow can live.
11
+ export const ResourceVerb = z.enum(["read", "write", "execute", "share"]);
12
+ export const SharePrincipal = z.discriminatedUnion("type", [
13
+ z.strictObject({ type: z.literal("user"), id: IntelId }),
14
+ z.strictObject({ type: z.literal("email"), email: z.email() }),
15
+ z.strictObject({ type: z.literal("organization") }),
16
+ ]);
17
+ export const ListGrantsInput = z.strictObject({
18
+ resourceId: IntelId.describe("Node whose direct grants to list. Access inherited from a folder above is not a grant on this node and is not listed here."),
19
+ });
20
+ export const ResourceGrant = z.strictObject({
21
+ id: IntelId,
22
+ resourceId: IntelId,
23
+ principal: SharePrincipal,
24
+ verb: ResourceVerb,
25
+ expiresAt: IsoDateTime.nullable(),
26
+ createdBy: IntelId,
27
+ createdAt: IsoDateTime,
28
+ });
29
+ export const ShareInput = z.strictObject({
30
+ resourceId: IntelId.describe("Node to grant access to. A grant on a folder is inherited by everything beneath it, which is the usual way to share a whole area."),
31
+ principal: SharePrincipal.describe("Who gets the access: a Gate user by id, someone by verified email address, or the whole organization."),
32
+ verb: ResourceVerb.describe("What they may do. Each verb is granted on its own and none implies another: `read` reads, `write` writes, `execute` runs a flow, `share` passes access on. Seeing a process is deliberately separable from being allowed to start it."),
33
+ expiresAt: IsoDateTime.nullable()
34
+ .default(null)
35
+ .describe("When the grant stops working, or `null` for one that does not expire on its own."),
36
+ idempotencyKey: IdempotencyKey,
37
+ });
38
+ export const RevokeGrantInput = z.strictObject({
39
+ resourceId: IntelId.describe("Node the grant sits on. Named alongside the grant id so access is decided on the node."),
40
+ grantId: IntelId.describe("The grant to withdraw, from node_grant_list."),
41
+ idempotencyKey: IdempotencyKey,
42
+ });
43
+ // What a grant does not cover, reported to whoever just made it. A flow in the shared folder may
44
+ // read a document outside it, and the run is re-authorized against the person running it — so the
45
+ // grant can be complete and the flow still stop for them (ADR-0004 §4).
46
+ //
47
+ // ⚠️ `titles` holds only the documents the sharer may see; everything else is in `hidden` as a
48
+ // number. A warning must not become a way of reading titles out of the tree.
49
+ export const UnreadableNodes = z.strictObject({
50
+ titles: z.array(z.string().min(1).max(240)),
51
+ hidden: z.number().int().nonnegative(),
52
+ });
53
+ // The grant is in the answer, so the warning cannot be mistaken for a refusal: it is written first
54
+ // and described afterwards. Blocking would force everyone who uses a central policy document to
55
+ // duplicate it, which is the opposite of what one tree is for (ADR-0004 §4).
56
+ export const ShareResult = z.strictObject({
57
+ grant: ResourceGrant,
58
+ unreadable: UnreadableNodes,
59
+ });
60
+ // `applicableVerbs` travels with the list because the answer is the business layer's, not the
61
+ // screen's: a document has nothing to execute, so `execute` is not offered on one (ADR-0004 §2).
62
+ export const ResourceGrantList = z.strictObject({
63
+ resourceId: IntelId,
64
+ applicableVerbs: z.array(ResourceVerb).min(1),
65
+ items: z.array(ResourceGrant),
66
+ });
67
+ export const RevokeGrantResult = z.strictObject({ revoked: z.boolean() });
@@ -0,0 +1,162 @@
1
+ import { z } from "zod";
2
+ export declare const TableMediaType = "text/csv";
3
+ export declare const TableColumn: z.ZodString;
4
+ export declare const TableCell: z.ZodString;
5
+ export declare const TableRow: z.ZodArray<z.ZodString>;
6
+ export declare const DefineTableInput: z.ZodObject<{
7
+ nodeId: z.ZodString;
8
+ columns: z.ZodArray<z.ZodString>;
9
+ idempotencyKey: z.ZodString;
10
+ }, z.core.$strict>;
11
+ export type DefineTableInput = z.infer<typeof DefineTableInput>;
12
+ export declare const AppendTableRowsInput: z.ZodObject<{
13
+ nodeId: z.ZodString;
14
+ rows: z.ZodArray<z.ZodArray<z.ZodString>>;
15
+ idempotencyKey: z.ZodString;
16
+ }, z.core.$strict>;
17
+ export type AppendTableRowsInput = z.infer<typeof AppendTableRowsInput>;
18
+ export declare const GetTableInput: z.ZodObject<{
19
+ nodeId: z.ZodString;
20
+ }, z.core.$strict>;
21
+ export type GetTableInput = z.infer<typeof GetTableInput>;
22
+ export declare const AppendTableRowsResult: z.ZodObject<{
23
+ node: z.ZodObject<{
24
+ id: z.ZodString;
25
+ parentId: z.ZodNullable<z.ZodString>;
26
+ kind: z.ZodEnum<{
27
+ folder: "folder";
28
+ document: "document";
29
+ table: "table";
30
+ attachment: "attachment";
31
+ }>;
32
+ title: z.ZodString;
33
+ description: z.ZodNullable<z.ZodString>;
34
+ ownerId: z.ZodString;
35
+ currentVersionId: z.ZodNullable<z.ZodString>;
36
+ createdAt: z.ZodISODateTime;
37
+ updatedAt: z.ZodISODateTime;
38
+ archivedAt: z.ZodNullable<z.ZodISODateTime>;
39
+ }, z.core.$strict>;
40
+ version: z.ZodObject<{
41
+ id: z.ZodString;
42
+ nodeId: z.ZodString;
43
+ sequence: z.ZodNumber;
44
+ contentKey: z.ZodString;
45
+ mediaType: z.ZodString;
46
+ contentHash: z.ZodString;
47
+ size: z.ZodNumber;
48
+ segment: z.ZodNullable<z.ZodEnum<{
49
+ append: "append";
50
+ snapshot: "snapshot";
51
+ }>>;
52
+ createdBy: z.ZodString;
53
+ createdAt: z.ZodISODateTime;
54
+ }, z.core.$strict>;
55
+ appended: z.ZodNumber;
56
+ }, z.core.$strict>;
57
+ export type AppendTableRowsResult = z.infer<typeof AppendTableRowsResult>;
58
+ export declare const TableRowPosition: z.ZodNumber;
59
+ export declare const UpdateTableRowsInput: z.ZodObject<{
60
+ nodeId: z.ZodString;
61
+ baseVersionId: z.ZodString;
62
+ updates: z.ZodArray<z.ZodObject<{
63
+ position: z.ZodNumber;
64
+ row: z.ZodArray<z.ZodString>;
65
+ }, z.core.$strict>>;
66
+ idempotencyKey: z.ZodString;
67
+ }, z.core.$strict>;
68
+ export type UpdateTableRowsInput = z.infer<typeof UpdateTableRowsInput>;
69
+ export declare const UpdateTableRowsResult: z.ZodObject<{
70
+ node: z.ZodObject<{
71
+ id: z.ZodString;
72
+ parentId: z.ZodNullable<z.ZodString>;
73
+ kind: z.ZodEnum<{
74
+ folder: "folder";
75
+ document: "document";
76
+ table: "table";
77
+ attachment: "attachment";
78
+ }>;
79
+ title: z.ZodString;
80
+ description: z.ZodNullable<z.ZodString>;
81
+ ownerId: z.ZodString;
82
+ currentVersionId: z.ZodNullable<z.ZodString>;
83
+ createdAt: z.ZodISODateTime;
84
+ updatedAt: z.ZodISODateTime;
85
+ archivedAt: z.ZodNullable<z.ZodISODateTime>;
86
+ }, z.core.$strict>;
87
+ version: z.ZodObject<{
88
+ id: z.ZodString;
89
+ nodeId: z.ZodString;
90
+ sequence: z.ZodNumber;
91
+ contentKey: z.ZodString;
92
+ mediaType: z.ZodString;
93
+ contentHash: z.ZodString;
94
+ size: z.ZodNumber;
95
+ segment: z.ZodNullable<z.ZodEnum<{
96
+ append: "append";
97
+ snapshot: "snapshot";
98
+ }>>;
99
+ createdBy: z.ZodString;
100
+ createdAt: z.ZodISODateTime;
101
+ }, z.core.$strict>;
102
+ updated: z.ZodNumber;
103
+ }, z.core.$strict>;
104
+ export type UpdateTableRowsResult = z.infer<typeof UpdateTableRowsResult>;
105
+ export declare const DeleteTableRowsInput: z.ZodObject<{
106
+ nodeId: z.ZodString;
107
+ baseVersionId: z.ZodString;
108
+ positions: z.ZodArray<z.ZodNumber>;
109
+ idempotencyKey: z.ZodString;
110
+ }, z.core.$strict>;
111
+ export type DeleteTableRowsInput = z.infer<typeof DeleteTableRowsInput>;
112
+ export declare const DeleteTableRowsResult: z.ZodObject<{
113
+ node: z.ZodObject<{
114
+ id: z.ZodString;
115
+ parentId: z.ZodNullable<z.ZodString>;
116
+ kind: z.ZodEnum<{
117
+ folder: "folder";
118
+ document: "document";
119
+ table: "table";
120
+ attachment: "attachment";
121
+ }>;
122
+ title: z.ZodString;
123
+ description: z.ZodNullable<z.ZodString>;
124
+ ownerId: z.ZodString;
125
+ currentVersionId: z.ZodNullable<z.ZodString>;
126
+ createdAt: z.ZodISODateTime;
127
+ updatedAt: z.ZodISODateTime;
128
+ archivedAt: z.ZodNullable<z.ZodISODateTime>;
129
+ }, z.core.$strict>;
130
+ version: z.ZodObject<{
131
+ id: z.ZodString;
132
+ nodeId: z.ZodString;
133
+ sequence: z.ZodNumber;
134
+ contentKey: z.ZodString;
135
+ mediaType: z.ZodString;
136
+ contentHash: z.ZodString;
137
+ size: z.ZodNumber;
138
+ segment: z.ZodNullable<z.ZodEnum<{
139
+ append: "append";
140
+ snapshot: "snapshot";
141
+ }>>;
142
+ createdBy: z.ZodString;
143
+ createdAt: z.ZodISODateTime;
144
+ }, z.core.$strict>;
145
+ deleted: z.ZodNumber;
146
+ }, z.core.$strict>;
147
+ export type DeleteTableRowsResult = z.infer<typeof DeleteTableRowsResult>;
148
+ export declare const RedefineTableColumn: z.ZodObject<{
149
+ name: z.ZodString;
150
+ source: z.ZodDefault<z.ZodNullable<z.ZodString>>;
151
+ }, z.core.$strict>;
152
+ export type RedefineTableColumn = z.infer<typeof RedefineTableColumn>;
153
+ export declare const RedefineTableInput: z.ZodObject<{
154
+ nodeId: z.ZodString;
155
+ baseVersionId: z.ZodString;
156
+ columns: z.ZodArray<z.ZodObject<{
157
+ name: z.ZodString;
158
+ source: z.ZodDefault<z.ZodNullable<z.ZodString>>;
159
+ }, z.core.$strict>>;
160
+ idempotencyKey: z.ZodString;
161
+ }, z.core.$strict>;
162
+ export type RedefineTableInput = z.infer<typeof RedefineTableInput>;