@anchrd/intel-contract 0.21.0 → 0.22.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/dist/contract/bundle.d.ts +43 -0
- package/dist/contract/bundle.js +42 -6
- package/dist/contract/contract.d.ts +36 -0
- package/dist/contract/contract.js +32 -0
- package/dist/contract/node.js +7 -1
- package/dist/contract/share.d.ts +8 -0
- package/dist/contract/share.js +21 -5
- package/package.json +1 -1
|
@@ -57,11 +57,30 @@ export declare const BundleManifestEntry: z.ZodObject<{
|
|
|
57
57
|
}>>;
|
|
58
58
|
}, z.core.$strict>;
|
|
59
59
|
export type BundleManifestEntry = z.infer<typeof BundleManifestEntry>;
|
|
60
|
+
/**
|
|
61
|
+
* What an export leaves out on purpose, named so a bundle says it rather than a reader guessing:
|
|
62
|
+
* version history, grants/shares, flow runs, and archived nodes are not in any bundle (#136).
|
|
63
|
+
*
|
|
64
|
+
* ⚠️ `unpublished-flow-changes` is the FIFTH, and it is the one exception to ADR-0006's own
|
|
65
|
+
* headline (#585). A bundle carries the current state of everything — except a flow that has been
|
|
66
|
+
* published, which travels as its PUBLISHED graph. Edits made after that publication are in no
|
|
67
|
+
* bundle, and they are not history: they are the newest state there is. The word exists because the
|
|
68
|
+
* loss is only acceptable while it is named, and `version-history` does not name it — a reader who
|
|
69
|
+
* saw only that word would expect the newest graph and get one that is deliberately older.
|
|
70
|
+
*
|
|
71
|
+
* ⚠️ These are WIRE values: an older reader refuses a bundle naming an exclusion it does not know,
|
|
72
|
+
* the same way it would refuse an unknown `kind`. The enum grows only for something an installation
|
|
73
|
+
* genuinely leaves behind, never as a place to note a nicety (ADR-0006, #433). Growing it costs the
|
|
74
|
+
* direction nobody migrates in — a bundle written HERE is refused by an installation older than
|
|
75
|
+
* this line, while every bundle written before it still parses, which is the direction 0.22.0's
|
|
76
|
+
* rebuild actually runs.
|
|
77
|
+
*/
|
|
60
78
|
export declare const BundleExclusion: z.ZodEnum<{
|
|
61
79
|
"version-history": "version-history";
|
|
62
80
|
grants: "grants";
|
|
63
81
|
"flow-runs": "flow-runs";
|
|
64
82
|
"archived-nodes": "archived-nodes";
|
|
83
|
+
"unpublished-flow-changes": "unpublished-flow-changes";
|
|
65
84
|
}>;
|
|
66
85
|
export type BundleExclusion = z.infer<typeof BundleExclusion>;
|
|
67
86
|
export declare const BundleManifest: z.ZodObject<{
|
|
@@ -92,13 +111,37 @@ export declare const BundleManifest: z.ZodObject<{
|
|
|
92
111
|
grants: "grants";
|
|
93
112
|
"flow-runs": "flow-runs";
|
|
94
113
|
"archived-nodes": "archived-nodes";
|
|
114
|
+
"unpublished-flow-changes": "unpublished-flow-changes";
|
|
95
115
|
}>>;
|
|
96
116
|
}, z.core.$strict>;
|
|
97
117
|
export type BundleManifest = z.infer<typeof BundleManifest>;
|
|
118
|
+
/**
|
|
119
|
+
* What one import made. Import always creates new nodes — no merge, no overwrite, no restored IDs
|
|
120
|
+
* (#137, phase 1) — so the answer is counts and the new roots, never a diff. `replayed` marks the
|
|
121
|
+
* idempotent second answer to the same key: nothing was created twice.
|
|
122
|
+
*
|
|
123
|
+
* ⚠️ `excluded` is what the IMPORT knows about itself, never what the bundle claimed (ADR-0006,
|
|
124
|
+
* #433). A subtree moved between installations arrives with one version per node, no grants and no
|
|
125
|
+
* runs, and until now nothing said so at the moment somebody could still act on it — the word stood
|
|
126
|
+
* only in a `manifest.json` inside the zip that had already been written.
|
|
127
|
+
*
|
|
128
|
+
* It is deliberately NOT read back out of that manifest. A hand-written bundle saying `excluded: []`
|
|
129
|
+
* would then make the import report that nothing was left behind, and the import would launder
|
|
130
|
+
* somebody else's claim into an answer that sounds like its own — the trap `absence` is bound
|
|
131
|
+
* against in `BundleManifestEntry` above (#534, #560). The five exclusions hold for every import
|
|
132
|
+
* this build performs, with a manifest or from a naked folder, so this is a constant of the code.
|
|
133
|
+
*/
|
|
98
134
|
export declare const BundleImportResult: z.ZodObject<{
|
|
99
135
|
nodes: z.ZodNumber;
|
|
100
136
|
flows: z.ZodNumber;
|
|
101
137
|
rootNodeIds: z.ZodArray<z.ZodString>;
|
|
102
138
|
replayed: z.ZodBoolean;
|
|
139
|
+
excluded: z.ZodArray<z.ZodEnum<{
|
|
140
|
+
"version-history": "version-history";
|
|
141
|
+
grants: "grants";
|
|
142
|
+
"flow-runs": "flow-runs";
|
|
143
|
+
"archived-nodes": "archived-nodes";
|
|
144
|
+
"unpublished-flow-changes": "unpublished-flow-changes";
|
|
145
|
+
}>>;
|
|
103
146
|
}, z.core.$strict>;
|
|
104
147
|
export type BundleImportResult = z.infer<typeof BundleImportResult>;
|
package/dist/contract/bundle.js
CHANGED
|
@@ -79,9 +79,31 @@ export const BundleManifestEntry = z
|
|
|
79
79
|
message: "Only a table or attachment entry may declare an absence",
|
|
80
80
|
path: ["absence"],
|
|
81
81
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
/**
|
|
83
|
+
* What an export leaves out on purpose, named so a bundle says it rather than a reader guessing:
|
|
84
|
+
* version history, grants/shares, flow runs, and archived nodes are not in any bundle (#136).
|
|
85
|
+
*
|
|
86
|
+
* ⚠️ `unpublished-flow-changes` is the FIFTH, and it is the one exception to ADR-0006's own
|
|
87
|
+
* headline (#585). A bundle carries the current state of everything — except a flow that has been
|
|
88
|
+
* published, which travels as its PUBLISHED graph. Edits made after that publication are in no
|
|
89
|
+
* bundle, and they are not history: they are the newest state there is. The word exists because the
|
|
90
|
+
* loss is only acceptable while it is named, and `version-history` does not name it — a reader who
|
|
91
|
+
* saw only that word would expect the newest graph and get one that is deliberately older.
|
|
92
|
+
*
|
|
93
|
+
* ⚠️ These are WIRE values: an older reader refuses a bundle naming an exclusion it does not know,
|
|
94
|
+
* the same way it would refuse an unknown `kind`. The enum grows only for something an installation
|
|
95
|
+
* genuinely leaves behind, never as a place to note a nicety (ADR-0006, #433). Growing it costs the
|
|
96
|
+
* direction nobody migrates in — a bundle written HERE is refused by an installation older than
|
|
97
|
+
* this line, while every bundle written before it still parses, which is the direction 0.22.0's
|
|
98
|
+
* rebuild actually runs.
|
|
99
|
+
*/
|
|
100
|
+
export const BundleExclusion = z.enum([
|
|
101
|
+
"version-history",
|
|
102
|
+
"grants",
|
|
103
|
+
"flow-runs",
|
|
104
|
+
"archived-nodes",
|
|
105
|
+
"unpublished-flow-changes",
|
|
106
|
+
]);
|
|
85
107
|
export const BundleManifest = z.strictObject({
|
|
86
108
|
version: z.literal(1),
|
|
87
109
|
exportedAt: IsoDateTime,
|
|
@@ -92,12 +114,26 @@ export const BundleManifest = z.strictObject({
|
|
|
92
114
|
excluded: z.array(BundleExclusion),
|
|
93
115
|
});
|
|
94
116
|
// ── Bundle import (#137) ────────────────────────────────────────────────────────────────────────
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
117
|
+
/**
|
|
118
|
+
* What one import made. Import always creates new nodes — no merge, no overwrite, no restored IDs
|
|
119
|
+
* (#137, phase 1) — so the answer is counts and the new roots, never a diff. `replayed` marks the
|
|
120
|
+
* idempotent second answer to the same key: nothing was created twice.
|
|
121
|
+
*
|
|
122
|
+
* ⚠️ `excluded` is what the IMPORT knows about itself, never what the bundle claimed (ADR-0006,
|
|
123
|
+
* #433). A subtree moved between installations arrives with one version per node, no grants and no
|
|
124
|
+
* runs, and until now nothing said so at the moment somebody could still act on it — the word stood
|
|
125
|
+
* only in a `manifest.json` inside the zip that had already been written.
|
|
126
|
+
*
|
|
127
|
+
* It is deliberately NOT read back out of that manifest. A hand-written bundle saying `excluded: []`
|
|
128
|
+
* would then make the import report that nothing was left behind, and the import would launder
|
|
129
|
+
* somebody else's claim into an answer that sounds like its own — the trap `absence` is bound
|
|
130
|
+
* against in `BundleManifestEntry` above (#534, #560). The five exclusions hold for every import
|
|
131
|
+
* this build performs, with a manifest or from a naked folder, so this is a constant of the code.
|
|
132
|
+
*/
|
|
98
133
|
export const BundleImportResult = z.strictObject({
|
|
99
134
|
nodes: z.number().int().nonnegative(),
|
|
100
135
|
flows: z.number().int().nonnegative(),
|
|
101
136
|
rootNodeIds: z.array(IntelId),
|
|
102
137
|
replayed: z.boolean(),
|
|
138
|
+
excluded: z.array(BundleExclusion),
|
|
103
139
|
});
|
|
@@ -38,6 +38,38 @@ export declare const IdempotencyKey: z.ZodString;
|
|
|
38
38
|
export declare function baseVersion(rule: string): z.ZodUnion<readonly [z.ZodString, z.ZodNull]>;
|
|
39
39
|
export declare const UI_LANGUAGES: readonly ["en", "de", "es"];
|
|
40
40
|
export type UiLanguage = (typeof UI_LANGUAGES)[number];
|
|
41
|
+
/**
|
|
42
|
+
* A set of things the reader is only partly entitled to see: the ones they may see BY NAME, the
|
|
43
|
+
* rest as a NUMBER (ADR-0004 §3). Never the titles of the rest, in any field, ever — a warning or a
|
|
44
|
+
* refusal must not become a way of reading the tree.
|
|
45
|
+
*
|
|
46
|
+
* ⚠️ It lives here rather than in `share.ts` because two domains state it: a grant says what it
|
|
47
|
+
* does not reach (`UnreadableNodes`), and a refusal says who is still calling in
|
|
48
|
+
* (`ProblemDetails.callers`, #448). `contract.ts` may not import from `share.ts` — the graph
|
|
49
|
+
* between these files has to stay acyclic — and a copy would be a second place for one rule to
|
|
50
|
+
* drift, which is what `IdempotencyKey` and `baseVersion` above exist against.
|
|
51
|
+
*/
|
|
52
|
+
export declare const NamedOrCounted: z.ZodObject<{
|
|
53
|
+
titles: z.ZodArray<z.ZodString>;
|
|
54
|
+
hidden: z.ZodNumber;
|
|
55
|
+
}, z.core.$strict>;
|
|
56
|
+
export type NamedOrCounted = z.infer<typeof NamedOrCounted>;
|
|
57
|
+
/**
|
|
58
|
+
* ⚠️ `callers` is the one member here that is not about every problem, and it is deliberate (#448).
|
|
59
|
+
* RFC 9457 allows extension members for exactly this: `folder_execute_in_use` refuses to narrow a
|
|
60
|
+
* library folder while flows from outside still call into it, and the CALLERS are the only thing
|
|
61
|
+
* that makes the refusal actionable. They used to exist only inside `detail` — an English sentence
|
|
62
|
+
* built on the server — so a German or Spanish surface could do nothing but print it verbatim, and
|
|
63
|
+
* no surface could shorten it or link the titles.
|
|
64
|
+
*
|
|
65
|
+
* The split is the point: the server decides WHAT is named and what is only counted, because that
|
|
66
|
+
* is an authorization answer nobody else can give; the surface decides how the sentence READS,
|
|
67
|
+
* because that is a language answer no server can give.
|
|
68
|
+
*
|
|
69
|
+
* `detail` keeps its sentence rather than emptying out — MCP hands a model prose and has nothing to
|
|
70
|
+
* formulate with, and an empty `detail` beside a new field would be the worst of the three states.
|
|
71
|
+
* It is absent on every other problem, so a reader must not treat its presence as guaranteed.
|
|
72
|
+
*/
|
|
41
73
|
export declare const ProblemDetails: z.ZodObject<{
|
|
42
74
|
type: z.ZodString;
|
|
43
75
|
status: z.ZodNumber;
|
|
@@ -45,6 +77,10 @@ export declare const ProblemDetails: z.ZodObject<{
|
|
|
45
77
|
detail: z.ZodOptional<z.ZodString>;
|
|
46
78
|
instance: z.ZodOptional<z.ZodString>;
|
|
47
79
|
code: z.ZodOptional<z.ZodString>;
|
|
80
|
+
callers: z.ZodOptional<z.ZodObject<{
|
|
81
|
+
titles: z.ZodArray<z.ZodString>;
|
|
82
|
+
hidden: z.ZodNumber;
|
|
83
|
+
}, z.core.$strict>>;
|
|
48
84
|
}, z.core.$strict>;
|
|
49
85
|
export type ProblemDetails = z.infer<typeof ProblemDetails>;
|
|
50
86
|
export declare const SessionUser: z.ZodObject<{
|
|
@@ -57,6 +57,37 @@ export function baseVersion(rule) {
|
|
|
57
57
|
// `i18n.unit.ts` compares it against the catalogs actually built in; a language listed here without
|
|
58
58
|
// a file gives a red run there instead of a UI that starts on a catalog which does not exist.
|
|
59
59
|
export const UI_LANGUAGES = ["en", "de", "es"];
|
|
60
|
+
/**
|
|
61
|
+
* A set of things the reader is only partly entitled to see: the ones they may see BY NAME, the
|
|
62
|
+
* rest as a NUMBER (ADR-0004 §3). Never the titles of the rest, in any field, ever — a warning or a
|
|
63
|
+
* refusal must not become a way of reading the tree.
|
|
64
|
+
*
|
|
65
|
+
* ⚠️ It lives here rather than in `share.ts` because two domains state it: a grant says what it
|
|
66
|
+
* does not reach (`UnreadableNodes`), and a refusal says who is still calling in
|
|
67
|
+
* (`ProblemDetails.callers`, #448). `contract.ts` may not import from `share.ts` — the graph
|
|
68
|
+
* between these files has to stay acyclic — and a copy would be a second place for one rule to
|
|
69
|
+
* drift, which is what `IdempotencyKey` and `baseVersion` above exist against.
|
|
70
|
+
*/
|
|
71
|
+
export const NamedOrCounted = z.strictObject({
|
|
72
|
+
titles: z.array(z.string().min(1).max(240)),
|
|
73
|
+
hidden: z.number().int().nonnegative(),
|
|
74
|
+
});
|
|
75
|
+
/**
|
|
76
|
+
* ⚠️ `callers` is the one member here that is not about every problem, and it is deliberate (#448).
|
|
77
|
+
* RFC 9457 allows extension members for exactly this: `folder_execute_in_use` refuses to narrow a
|
|
78
|
+
* library folder while flows from outside still call into it, and the CALLERS are the only thing
|
|
79
|
+
* that makes the refusal actionable. They used to exist only inside `detail` — an English sentence
|
|
80
|
+
* built on the server — so a German or Spanish surface could do nothing but print it verbatim, and
|
|
81
|
+
* no surface could shorten it or link the titles.
|
|
82
|
+
*
|
|
83
|
+
* The split is the point: the server decides WHAT is named and what is only counted, because that
|
|
84
|
+
* is an authorization answer nobody else can give; the surface decides how the sentence READS,
|
|
85
|
+
* because that is a language answer no server can give.
|
|
86
|
+
*
|
|
87
|
+
* `detail` keeps its sentence rather than emptying out — MCP hands a model prose and has nothing to
|
|
88
|
+
* formulate with, and an empty `detail` beside a new field would be the worst of the three states.
|
|
89
|
+
* It is absent on every other problem, so a reader must not treat its presence as guaranteed.
|
|
90
|
+
*/
|
|
60
91
|
export const ProblemDetails = z.strictObject({
|
|
61
92
|
type: z.string(),
|
|
62
93
|
status: z.number().int().min(400).max(599),
|
|
@@ -64,6 +95,7 @@ export const ProblemDetails = z.strictObject({
|
|
|
64
95
|
detail: z.string().optional(),
|
|
65
96
|
instance: z.string().optional(),
|
|
66
97
|
code: z.string().optional(),
|
|
98
|
+
callers: NamedOrCounted.optional(),
|
|
67
99
|
});
|
|
68
100
|
// Who the caller is, as Gate resolved it from the bearer: no token, and no capability list.
|
|
69
101
|
//
|
package/dist/contract/node.js
CHANGED
|
@@ -170,7 +170,13 @@ export const PurgeNodeInput = z.strictObject({
|
|
|
170
170
|
nodeId: IntelId.describe("Node to delete for good. It must already be archived — a living node has no path into nothing."),
|
|
171
171
|
idempotencyKey: IdempotencyKey,
|
|
172
172
|
});
|
|
173
|
-
|
|
173
|
+
// The question `PurgeNodeInput` cannot be asked afterwards: what goes with it, while it is all
|
|
174
|
+
// still there to be counted. Described since #586, because the count reached MCP that day — and a
|
|
175
|
+
// surface that may delete without being able to look first is the state `destructive.md` calls a
|
|
176
|
+
// confirmation that cannot name what disappears.
|
|
177
|
+
export const PurgeNodePreviewInput = z.strictObject({
|
|
178
|
+
nodeId: IntelId.describe("Archived node a purge would delete. Answers how many items would go with it and how many documents link to it from outside, and changes nothing. A node that is not archived is refused here for the same reason node_purge refuses it."),
|
|
179
|
+
});
|
|
174
180
|
export const PurgeNodePreview = z.strictObject({
|
|
175
181
|
inboundLinks: z.number().int().nonnegative(),
|
|
176
182
|
totalItems: z.number().int().positive(),
|
package/dist/contract/share.d.ts
CHANGED
|
@@ -24,6 +24,14 @@ export declare const ListFlowGrantsInput: z.ZodObject<{
|
|
|
24
24
|
flowId: z.ZodString;
|
|
25
25
|
}, z.core.$strict>;
|
|
26
26
|
export type ListFlowGrantsInput = z.infer<typeof ListFlowGrantsInput>;
|
|
27
|
+
export declare const ListEffectiveAccessInput: z.ZodObject<{
|
|
28
|
+
resourceId: z.ZodString;
|
|
29
|
+
}, z.core.$strict>;
|
|
30
|
+
export type ListEffectiveAccessInput = z.infer<typeof ListEffectiveAccessInput>;
|
|
31
|
+
export declare const ListFlowEffectiveAccessInput: z.ZodObject<{
|
|
32
|
+
flowId: z.ZodString;
|
|
33
|
+
}, z.core.$strict>;
|
|
34
|
+
export type ListFlowEffectiveAccessInput = z.infer<typeof ListFlowEffectiveAccessInput>;
|
|
27
35
|
export declare const ResourceGrant: z.ZodObject<{
|
|
28
36
|
id: z.ZodString;
|
|
29
37
|
resourceId: z.ZodString;
|
package/dist/contract/share.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { IdempotencyKey, IntelId, IsoDateTime } from "./contract.js";
|
|
2
|
+
import { IdempotencyKey, IntelId, IsoDateTime, NamedOrCounted } from "./contract.js";
|
|
3
3
|
// ⚠️ There is no `ContextPolicy`, and it is not coming back in this shape (#76). It said whether a
|
|
4
4
|
// document should be pinned into a context, be found by relevance, or be named explicitly — an
|
|
5
5
|
// instruction to a retrieval Intel does not perform. Intel hands out references and the agent
|
|
@@ -23,6 +23,21 @@ export const ListGrantsInput = z.strictObject({
|
|
|
23
23
|
export const ListFlowGrantsInput = z.strictObject({
|
|
24
24
|
flowId: IntelId.describe("Flow whose direct grants to list. Access inherited from the folder it is filed in is not a grant on this flow and is not listed here."),
|
|
25
25
|
});
|
|
26
|
+
// ⚠️ A DIFFERENT question from the two above, not a fuller answer to them (#586). The `*GrantsInput`
|
|
27
|
+
// pair asks what sits ON this one resource; these two ask who REACHES it once inheritance is
|
|
28
|
+
// resolved — every grant along the folders above plus the owners, who need no grant row at all. On
|
|
29
|
+
// the everyday resource, whose access comes from the folder it is filed in, the first answer is
|
|
30
|
+
// empty and this one is not, so a caller that reaches for the wrong one is told "nobody" about
|
|
31
|
+
// something half the organization can open.
|
|
32
|
+
//
|
|
33
|
+
// Two inputs rather than one widened `resourceId`, for the reason the pair above gives: the id
|
|
34
|
+
// names a different table, and the queries behind them are two statements over two sets of tables.
|
|
35
|
+
export const ListEffectiveAccessInput = z.strictObject({
|
|
36
|
+
resourceId: IntelId.describe("Node to answer for. The answer crosses the folders above it and names owners as well as grants, so it is not the list node_grant_list gives."),
|
|
37
|
+
});
|
|
38
|
+
export const ListFlowEffectiveAccessInput = z.strictObject({
|
|
39
|
+
flowId: IntelId.describe("Flow to answer for. The answer includes what the folder it is filed in passes down and names owners as well as grants, so it is not the list flow_grant_list gives."),
|
|
40
|
+
});
|
|
26
41
|
export const ResourceGrant = z.strictObject({
|
|
27
42
|
id: IntelId,
|
|
28
43
|
resourceId: IntelId,
|
|
@@ -71,10 +86,11 @@ export const RevokeFlowGrantInput = z.strictObject({
|
|
|
71
86
|
//
|
|
72
87
|
// ⚠️ `titles` holds only the documents the sharer may see; everything else is in `hidden` as a
|
|
73
88
|
// number. A warning must not become a way of reading titles out of the tree.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
89
|
+
//
|
|
90
|
+
// It IS `NamedOrCounted` — one schema, under the name this domain calls it by. The shape moved to
|
|
91
|
+
// `contract.ts` when a refusal started carrying it too (#448); it is not restated here, because two
|
|
92
|
+
// declarations of one rule are two places for it to drift.
|
|
93
|
+
export const UnreadableNodes = NamedOrCounted;
|
|
78
94
|
// The grant is in the answer, so the warning cannot be mistaken for a refusal: it is written first
|
|
79
95
|
// and described afterwards. Blocking would force everyone who uses a central policy document to
|
|
80
96
|
// duplicate it, which is the opposite of what one tree is for (ADR-0004 §4).
|