@gmickel/gno 1.27.1 → 1.29.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.
Files changed (195) hide show
  1. package/README.md +46 -20
  2. package/assets/skill/SKILL.md +59 -1
  3. package/browser-extension/artifacts/gno-browser-clipper-v1.29.0.zip +0 -0
  4. package/browser-extension/artifacts/gno-browser-clipper-v1.29.0.zip.sha256 +1 -0
  5. package/browser-extension/dist/chunk-b2zm0jjd.js +50 -0
  6. package/browser-extension/dist/manifest.json +1 -1
  7. package/browser-extension/dist/preview.html +1 -1
  8. package/browser-extension/dist/service-worker.js +6 -6
  9. package/package.json +2 -2
  10. package/spec/cli.md +82 -5
  11. package/spec/db/schema.sql +31 -0
  12. package/spec/mcp.md +71 -0
  13. package/spec/output-schemas/ask.schema.json +156 -1
  14. package/spec/output-schemas/browser-clip-preview.schema.json +30 -0
  15. package/spec/output-schemas/collection-egress-check.schema.json +91 -0
  16. package/spec/output-schemas/collection-egress-policy-set.schema.json +56 -0
  17. package/spec/output-schemas/collection-egress-policy.schema.json +41 -0
  18. package/spec/output-schemas/context-capsule-v1.schema.json +183 -3
  19. package/spec/output-schemas/context-capsule-verification.schema.json +1 -1
  20. package/spec/output-schemas/egress-audit-management.schema.json +88 -0
  21. package/spec/output-schemas/get.schema.json +94 -0
  22. package/spec/output-schemas/mcp-http-error.schema.json +113 -2
  23. package/spec/output-schemas/mcp-job-status.schema.json +28 -0
  24. package/spec/output-schemas/multi-get.schema.json +128 -0
  25. package/spec/output-schemas/publish-artifact.schema.json +32 -0
  26. package/spec/output-schemas/record-import.schema.json +223 -0
  27. package/spec/output-schemas/retrieval-trace-common.schema.json +31 -0
  28. package/spec/output-schemas/retrieval-trace-export.schema.json +3 -0
  29. package/spec/output-schemas/retrieval-trace-qrels.schema.json +3 -0
  30. package/spec/output-schemas/retrieval-trace-summary.schema.json +4 -0
  31. package/spec/output-schemas/search-result.schema.json +94 -0
  32. package/spec/output-schemas/search-results.schema.json +155 -0
  33. package/spec/project-profile.schema.json +66 -0
  34. package/src/app/context-format.ts +1 -1
  35. package/src/app/context-runtime-contract.ts +16 -7
  36. package/src/cli/commands/ask.ts +7 -0
  37. package/src/cli/commands/collection/index.ts +5 -0
  38. package/src/cli/commands/collection/policy.ts +126 -0
  39. package/src/cli/commands/context-build.ts +5 -0
  40. package/src/cli/commands/daemon.ts +45 -3
  41. package/src/cli/commands/egress-audit.ts +68 -0
  42. package/src/cli/commands/embed.ts +2 -0
  43. package/src/cli/commands/get.ts +12 -2
  44. package/src/cli/commands/index-cmd.ts +13 -0
  45. package/src/cli/commands/multi-get.ts +9 -2
  46. package/src/cli/commands/query.ts +12 -0
  47. package/src/cli/commands/replay.ts +13 -3
  48. package/src/cli/commands/shared.ts +28 -0
  49. package/src/cli/commands/update.ts +5 -0
  50. package/src/cli/commands/vsearch.ts +3 -1
  51. package/src/cli/program.ts +127 -0
  52. package/src/config/index.ts +9 -0
  53. package/src/config/project-profile.ts +2 -0
  54. package/src/config/types.ts +66 -0
  55. package/src/converters/adapters/browser-export/adapter.ts +199 -0
  56. package/src/converters/adapters/browser-export/formats.ts +358 -0
  57. package/src/converters/adapters/email/adapter.ts +429 -0
  58. package/src/converters/adapters/email/html.ts +162 -0
  59. package/src/converters/adapters/email/mime.ts +454 -0
  60. package/src/converters/adapters/email/parameters.ts +77 -0
  61. package/src/converters/adapters/ical/adapter.ts +475 -0
  62. package/src/converters/adapters/ical/recurrence.ts +186 -0
  63. package/src/converters/adapters/jsonl/adapter.ts +238 -0
  64. package/src/converters/adapters/jsonl/config.ts +105 -0
  65. package/src/converters/adapters/shared/html-text.ts +165 -0
  66. package/src/converters/adapters/shared/record-utils.ts +79 -0
  67. package/src/converters/adapters/shared/utf8-lines.ts +141 -0
  68. package/src/converters/adapters/transcript/adapter.ts +295 -0
  69. package/src/converters/adapters/transcript/json.ts +184 -0
  70. package/src/converters/adapters/transcript/model.ts +171 -0
  71. package/src/converters/adapters/transcript/text.ts +58 -0
  72. package/src/converters/adapters/transcript/timed.ts +152 -0
  73. package/src/converters/index.ts +11 -1
  74. package/src/converters/mime.ts +8 -0
  75. package/src/converters/pipeline.ts +15 -1
  76. package/src/converters/registry.ts +37 -1
  77. package/src/converters/types.ts +136 -0
  78. package/src/core/browser-clip.ts +16 -1
  79. package/src/core/collection-egress-policy-projection.ts +28 -0
  80. package/src/core/collection-egress-policy-service.ts +443 -0
  81. package/src/core/collection-egress-policy-validation.ts +242 -0
  82. package/src/core/config-mutation.ts +31 -19
  83. package/src/core/context-capsule-schema.ts +198 -1
  84. package/src/core/context-capsule-validation.ts +4 -4
  85. package/src/core/context-capsule-verification.ts +5 -1
  86. package/src/core/context-capsule.ts +177 -112
  87. package/src/core/context-evidence.ts +93 -15
  88. package/src/core/destination-classifier.ts +402 -0
  89. package/src/core/document-capabilities.ts +12 -0
  90. package/src/core/egress-audit.ts +239 -0
  91. package/src/core/egress-authorization.ts +50 -0
  92. package/src/core/egress-enforcement.ts +264 -0
  93. package/src/core/egress-policy.ts +440 -0
  94. package/src/core/egress-provenance.ts +336 -0
  95. package/src/core/job-manager.ts +37 -0
  96. package/src/core/network-boundary-inventory.ts +261 -0
  97. package/src/core/project-profile-apply-state.ts +5 -0
  98. package/src/core/project-profile.ts +4 -0
  99. package/src/core/record-metadata.ts +49 -0
  100. package/src/core/retrieval-qrels.ts +6 -0
  101. package/src/core/retrieval-replay.ts +18 -4
  102. package/src/core/retrieval-trace-export.ts +23 -4
  103. package/src/core/retrieval-trace-management-helpers.ts +1 -0
  104. package/src/core/retrieval-trace-management-types.ts +3 -0
  105. package/src/core/retrieval-trace-management.ts +9 -1
  106. package/src/core/retrieval-trace-session.ts +94 -0
  107. package/src/core/retrieval-trace.ts +22 -0
  108. package/src/ingestion/record-adapter-canonical.ts +433 -0
  109. package/src/ingestion/record-adapter.ts +448 -0
  110. package/src/ingestion/record-container.ts +704 -0
  111. package/src/ingestion/record-path.ts +20 -0
  112. package/src/ingestion/record-sync.ts +70 -0
  113. package/src/ingestion/sync.ts +243 -36
  114. package/src/ingestion/types.ts +71 -1
  115. package/src/ingestion/walker.ts +31 -11
  116. package/src/llm/errors.ts +10 -0
  117. package/src/llm/http-inference.ts +175 -0
  118. package/src/llm/http-policy.ts +537 -0
  119. package/src/llm/httpEmbedding.ts +47 -28
  120. package/src/llm/httpGeneration.ts +31 -18
  121. package/src/llm/httpRerank.ts +30 -18
  122. package/src/llm/index.ts +1 -0
  123. package/src/llm/nodeLlamaCpp/adapter.ts +55 -20
  124. package/src/llm/pinned-http-connection.ts +177 -0
  125. package/src/mcp/context.ts +53 -1
  126. package/src/mcp/http-egress.ts +220 -0
  127. package/src/mcp/http-security.ts +32 -21
  128. package/src/mcp/http-session.ts +13 -2
  129. package/src/mcp/http-transport.ts +96 -6
  130. package/src/mcp/sync-egress.ts +24 -0
  131. package/src/mcp/tools/add-collection.ts +4 -0
  132. package/src/mcp/tools/ask.ts +1 -1
  133. package/src/mcp/tools/context.ts +9 -2
  134. package/src/mcp/tools/egress.ts +247 -0
  135. package/src/mcp/tools/embed.ts +1 -0
  136. package/src/mcp/tools/get.ts +10 -2
  137. package/src/mcp/tools/index-cmd.ts +7 -0
  138. package/src/mcp/tools/index.ts +98 -0
  139. package/src/mcp/tools/multi-get.ts +9 -2
  140. package/src/mcp/tools/query.ts +10 -0
  141. package/src/mcp/tools/remove-collection.ts +4 -0
  142. package/src/mcp/tools/sync.ts +6 -0
  143. package/src/mcp/tools/trace.ts +7 -1
  144. package/src/mcp/tools/vsearch.ts +1 -0
  145. package/src/mcp/tools/workspace-write.ts +2 -0
  146. package/src/pipeline/egress-lineage.ts +124 -0
  147. package/src/pipeline/filters.ts +1 -1
  148. package/src/pipeline/graph-retrieval.ts +7 -4
  149. package/src/pipeline/hybrid.ts +21 -4
  150. package/src/pipeline/result-context.ts +12 -4
  151. package/src/pipeline/search.ts +23 -4
  152. package/src/pipeline/types.ts +6 -0
  153. package/src/pipeline/vsearch.ts +67 -28
  154. package/src/publish/artifact.ts +31 -3
  155. package/src/publish/export-service.ts +25 -0
  156. package/src/sdk/client.ts +119 -2
  157. package/src/sdk/documents.ts +13 -5
  158. package/src/sdk/embed.ts +1 -0
  159. package/src/sdk/types.ts +33 -0
  160. package/src/serve/browse-tree.ts +4 -2
  161. package/src/serve/clipper-capture.ts +5 -1
  162. package/src/serve/closed-json.ts +61 -0
  163. package/src/serve/config-sync.ts +4 -1
  164. package/src/serve/context.ts +1 -0
  165. package/src/serve/doc-events.ts +110 -39
  166. package/src/serve/public/components/CollectionEgressCheckPanel.tsx +411 -0
  167. package/src/serve/public/components/CollectionEgressPolicyEditor.tsx +78 -0
  168. package/src/serve/public/components/CollectionModelDialog.tsx +93 -9
  169. package/src/serve/public/components/EgressAuditPanel.tsx +278 -0
  170. package/src/serve/public/globals.built.css +1 -1
  171. package/src/serve/public/pages/Collections.tsx +3 -0
  172. package/src/serve/resident-request.ts +80 -3
  173. package/src/serve/resident-runtime.ts +63 -1
  174. package/src/serve/routes/api.ts +237 -65
  175. package/src/serve/routes/clipper.ts +64 -1
  176. package/src/serve/routes/mcp.ts +6 -0
  177. package/src/serve/routes/traces.ts +27 -4
  178. package/src/serve/server.ts +118 -7
  179. package/src/store/migrations/022-record-export-lineage.ts +42 -0
  180. package/src/store/migrations/023-collection-egress-policy.ts +61 -0
  181. package/src/store/migrations/024-egress-derived-lineage.ts +121 -0
  182. package/src/store/migrations/025-collection-egress-policy-revision.ts +40 -0
  183. package/src/store/migrations/index.ts +8 -0
  184. package/src/store/retrieval-trace-codec.ts +15 -0
  185. package/src/store/sqlite/adapter.ts +284 -14
  186. package/src/store/sqlite/change-journal-store.ts +41 -2
  187. package/src/store/sqlite/egress-audit-store.ts +485 -0
  188. package/src/store/sqlite/retrieval-trace-management-store.ts +47 -6
  189. package/src/store/sqlite/retrieval-trace-retention.ts +2 -0
  190. package/src/store/sqlite/retrieval-trace-rows.ts +8 -1
  191. package/src/store/sqlite/retrieval-trace-store.ts +104 -5
  192. package/src/store/types.ts +166 -1
  193. package/browser-extension/artifacts/gno-browser-clipper-v1.27.1.zip +0 -0
  194. package/browser-extension/artifacts/gno-browser-clipper-v1.27.1.zip.sha256 +0 -1
  195. package/browser-extension/dist/chunk-vn5f663b.js +0 -50
@@ -0,0 +1,50 @@
1
+ /** Shared current-policy authorization boundary for derived artifacts. */
2
+
3
+ import type { Collection } from "../config/types";
4
+ import type { StorePort, StoreResult } from "../store/types";
5
+ import type {
6
+ EgressAction,
7
+ EgressCallerContext,
8
+ EgressContentClass,
9
+ EgressDestinationZone,
10
+ } from "./egress-policy";
11
+ import type { EgressLineage } from "./egress-provenance";
12
+
13
+ import { err, ok } from "../store/types";
14
+ import { currentEgressSources } from "./collection-egress-policy-service";
15
+ import { EgressAuditService } from "./egress-audit";
16
+ import { evaluateEgressPolicy } from "./egress-policy";
17
+ import { resolveEgressLineage } from "./egress-provenance";
18
+
19
+ export const authorizeCurrentEgress = async (input: {
20
+ store: StorePort;
21
+ config: { collections: readonly Collection[] };
22
+ lineage: EgressLineage;
23
+ action: EgressAction;
24
+ destinationZone: EgressDestinationZone;
25
+ caller: EgressCallerContext;
26
+ contentClass: EgressContentClass;
27
+ }): Promise<StoreResult<EgressLineage>> => {
28
+ const currentLineage = resolveEgressLineage(
29
+ currentEgressSources(
30
+ input.config,
31
+ input.lineage.sources.map(({ collection }) => collection)
32
+ )
33
+ );
34
+ const decision = evaluateEgressPolicy({
35
+ collections: currentLineage.sources,
36
+ action: input.action,
37
+ destination: { zone: input.destinationZone },
38
+ caller: input.caller,
39
+ contentClass: input.contentClass,
40
+ });
41
+ const recorded = await new EgressAuditService(input.store).record({
42
+ decision,
43
+ lineage: currentLineage,
44
+ contentClass: input.contentClass,
45
+ });
46
+ if (!recorded.ok) return recorded;
47
+ return decision.allowed
48
+ ? ok(currentLineage)
49
+ : err("EGRESS_DENIED", "Operation blocked by collection egress policy");
50
+ };
@@ -0,0 +1,264 @@
1
+ /** Shared fail-closed enforcement helpers for content-transfer boundaries. */
2
+
3
+ import type { Collection } from "../config/types";
4
+ import type { StorePort } from "../store/types";
5
+ import type {
6
+ EgressAction,
7
+ EgressCallerContext,
8
+ EgressContentClass,
9
+ EgressDecision,
10
+ EgressDestinationZone,
11
+ } from "./egress-policy";
12
+ import type { EgressLineage, EgressLineageInput } from "./egress-provenance";
13
+
14
+ import { resolveConfiguredEgressPolicy } from "../config/types";
15
+ import { EgressAuditService } from "./egress-audit";
16
+ import { evaluateEgressPolicy } from "./egress-policy";
17
+ import {
18
+ EgressProvenanceError,
19
+ resolveEgressLineage,
20
+ } from "./egress-provenance";
21
+
22
+ export const EGRESS_DENIED_MESSAGE =
23
+ "Operation blocked by collection egress policy";
24
+
25
+ export class EgressDeniedError extends Error {
26
+ readonly code = "EGRESS_DENIED";
27
+ readonly decision: EgressDecision;
28
+
29
+ constructor(decision: EgressDecision) {
30
+ super(`${decision.code}: ${EGRESS_DENIED_MESSAGE}`);
31
+ this.name = "EgressDeniedError";
32
+ this.decision = decision;
33
+ this.stack = `${this.name}: ${this.message}`;
34
+ }
35
+
36
+ toJSON(): {
37
+ code: "EGRESS_DENIED";
38
+ message: string;
39
+ reason: EgressDecision["reason"];
40
+ audit: EgressDecision["audit"];
41
+ } {
42
+ return {
43
+ code: this.code,
44
+ message: EGRESS_DENIED_MESSAGE,
45
+ reason: this.decision.reason,
46
+ audit: this.decision.audit,
47
+ };
48
+ }
49
+ }
50
+
51
+ const collectionLineageInputs = (
52
+ collections: readonly Collection[]
53
+ ): readonly EgressLineageInput[] => {
54
+ try {
55
+ if (!Array.isArray(collections)) {
56
+ throw new EgressProvenanceError(
57
+ "INVALID_EGRESS_LINEAGE",
58
+ "Collection policy scope must be a readable dense bounded array"
59
+ );
60
+ }
61
+ const { length } = collections;
62
+ if (!Number.isSafeInteger(length) || length > 128) {
63
+ throw new EgressProvenanceError(
64
+ "INVALID_EGRESS_LINEAGE",
65
+ "Collection policy scope must be a readable dense bounded array"
66
+ );
67
+ }
68
+ const inputs: EgressLineageInput[] = [];
69
+ for (let index = 0; index < length; index += 1) {
70
+ if (!(index in collections)) {
71
+ throw new EgressProvenanceError(
72
+ "INVALID_EGRESS_LINEAGE",
73
+ "Collection policy scope must be a readable dense bounded array"
74
+ );
75
+ }
76
+ const collection: unknown = collections[index];
77
+ if (collection === null || typeof collection !== "object") {
78
+ throw new EgressProvenanceError(
79
+ "INVALID_EGRESS_LINEAGE",
80
+ "Collection policy scope contains an invalid collection"
81
+ );
82
+ }
83
+ const candidate = collection as Partial<Collection>;
84
+ const name = candidate.name;
85
+ const egressPolicy = candidate.egressPolicy;
86
+ const effective = resolveConfiguredEgressPolicy({ egressPolicy });
87
+ inputs.push({
88
+ collection: name as string,
89
+ policy: effective.policy,
90
+ source: effective.source,
91
+ });
92
+ }
93
+ return inputs;
94
+ } catch (error) {
95
+ if (error instanceof EgressProvenanceError) throw error;
96
+ throw new EgressProvenanceError(
97
+ "INVALID_EGRESS_LINEAGE",
98
+ "Collection policy scope could not be validated"
99
+ );
100
+ }
101
+ };
102
+
103
+ const resolveCollectionEgressLineage = (
104
+ collections: readonly Collection[],
105
+ names?: readonly string[]
106
+ ): EgressLineage =>
107
+ resolveEgressLineage(collectionLineageInputs(collections), names);
108
+
109
+ export const collectionEgressStates = (
110
+ collections: readonly Collection[],
111
+ names?: readonly string[]
112
+ ) => {
113
+ return resolveCollectionEgressLineage(collections, names).sources;
114
+ };
115
+
116
+ export interface EnforceCollectionEgressInput {
117
+ collections: readonly Collection[];
118
+ collectionNames?: readonly string[];
119
+ action: EgressAction;
120
+ destinationZone: EgressDestinationZone;
121
+ caller: EgressCallerContext;
122
+ contentClass: EgressContentClass;
123
+ }
124
+
125
+ export interface MixedCollectionEgressPlan {
126
+ mode: "complete" | "partial";
127
+ sourceLineage: EgressLineage;
128
+ allowedCollections: string[];
129
+ omittedCollections: Array<{
130
+ collection: string;
131
+ reason: EgressDecision["reason"];
132
+ }>;
133
+ disclosure: null | {
134
+ code: "EGRESS_PARTIAL_RESULT";
135
+ omittedCount: number;
136
+ omittedCollections: string[];
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Plan one mixed-source boundary. Denial is the default; partial emission
142
+ * requires an explicit caller opt-in and always discloses sorted omissions.
143
+ */
144
+ export const planCollectionEgress = (
145
+ input: EnforceCollectionEgressInput & {
146
+ partialResults?: "deny" | "explicit";
147
+ }
148
+ ): MixedCollectionEgressPlan => {
149
+ const sourceLineage = resolveCollectionEgressLineage(
150
+ input.collections,
151
+ input.collectionNames
152
+ );
153
+ const aggregate = evaluateEgressPolicy({
154
+ collections: sourceLineage.sources,
155
+ action: input.action,
156
+ destination: { zone: input.destinationZone },
157
+ caller: input.caller,
158
+ contentClass: input.contentClass,
159
+ });
160
+ if (aggregate.allowed) {
161
+ return {
162
+ mode: "complete",
163
+ sourceLineage,
164
+ allowedCollections: sourceLineage.sources.map(
165
+ ({ collection }) => collection
166
+ ),
167
+ omittedCollections: [],
168
+ disclosure: null,
169
+ };
170
+ }
171
+ if (input.partialResults !== "explicit") {
172
+ throw new EgressDeniedError(aggregate);
173
+ }
174
+
175
+ const allowedCollections: string[] = [];
176
+ const omittedCollections: MixedCollectionEgressPlan["omittedCollections"] =
177
+ [];
178
+ for (const source of sourceLineage.sources) {
179
+ const perCollection = evaluateEgressPolicy({
180
+ collections: [source],
181
+ action: input.action,
182
+ destination: { zone: input.destinationZone },
183
+ caller: input.caller,
184
+ contentClass: input.contentClass,
185
+ });
186
+ if (perCollection.allowed) allowedCollections.push(source.collection);
187
+ else {
188
+ omittedCollections.push({
189
+ collection: source.collection,
190
+ reason: perCollection.reason,
191
+ });
192
+ }
193
+ }
194
+ if (allowedCollections.length === 0) {
195
+ throw new EgressDeniedError(aggregate);
196
+ }
197
+ return {
198
+ mode: "partial",
199
+ sourceLineage,
200
+ allowedCollections,
201
+ omittedCollections,
202
+ disclosure: {
203
+ code: "EGRESS_PARTIAL_RESULT",
204
+ omittedCount: omittedCollections.length,
205
+ omittedCollections: omittedCollections.map(
206
+ ({ collection }) => collection
207
+ ),
208
+ },
209
+ };
210
+ };
211
+
212
+ export const enforceCollectionEgress = (
213
+ input: EnforceCollectionEgressInput
214
+ ): EgressDecision => {
215
+ const plan = planCollectionEgress(input);
216
+ const decision = evaluateEgressPolicy({
217
+ collections: plan.sourceLineage.sources,
218
+ action: input.action,
219
+ destination: { zone: input.destinationZone },
220
+ caller: input.caller,
221
+ contentClass: input.contentClass,
222
+ });
223
+ if (!decision.allowed) throw new EgressDeniedError(decision);
224
+ return decision;
225
+ };
226
+
227
+ /** Enforce and durably record the content-free decision before transfer. */
228
+ export const enforceCollectionEgressWithAudit = async (
229
+ input: EnforceCollectionEgressInput & { store: StorePort }
230
+ ): Promise<{ decision: EgressDecision; lineage: EgressLineage }> => {
231
+ const lineage = resolveCollectionEgressLineage(
232
+ input.collections,
233
+ input.collectionNames
234
+ );
235
+ let decision: EgressDecision;
236
+ let denied: EgressDeniedError | null = null;
237
+ try {
238
+ decision = enforceCollectionEgress(input);
239
+ } catch (error) {
240
+ if (!(error instanceof EgressDeniedError)) throw error;
241
+ decision = error.decision;
242
+ denied = error;
243
+ }
244
+ const recorded = await new EgressAuditService(input.store).record({
245
+ decision,
246
+ lineage,
247
+ contentClass: input.contentClass,
248
+ });
249
+ if (!recorded.ok) {
250
+ throw new Error(`Failed to record egress audit: ${recorded.error.code}`);
251
+ }
252
+ if (denied) throw denied;
253
+ return { decision, lineage };
254
+ };
255
+
256
+ export const maximumDestinationZoneForCollections = (
257
+ collections: readonly Collection[],
258
+ names?: readonly string[]
259
+ ): Exclude<EgressDestinationZone, "local_process"> => {
260
+ const states = collectionEgressStates(collections, names);
261
+ if (states.some(({ policy }) => policy === "local_only")) return "loopback";
262
+ if (states.some(({ policy }) => policy === "lan")) return "lan";
263
+ return "remote";
264
+ };