@gmickel/gno 1.28.0 → 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 (143) hide show
  1. package/README.md +46 -20
  2. package/assets/skill/SKILL.md +33 -0
  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 +1 -1
  10. package/spec/cli.md +41 -1
  11. package/spec/db/schema.sql +19 -0
  12. package/spec/mcp.md +66 -0
  13. package/spec/output-schemas/ask.schema.json +31 -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 +89 -2
  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/mcp-http-error.schema.json +113 -2
  22. package/spec/output-schemas/publish-artifact.schema.json +32 -0
  23. package/spec/output-schemas/record-import.schema.json +30 -0
  24. package/spec/output-schemas/retrieval-trace-common.schema.json +31 -0
  25. package/spec/output-schemas/retrieval-trace-export.schema.json +3 -0
  26. package/spec/output-schemas/retrieval-trace-qrels.schema.json +3 -0
  27. package/spec/output-schemas/retrieval-trace-summary.schema.json +4 -0
  28. package/spec/output-schemas/search-results.schema.json +30 -0
  29. package/src/app/context-runtime-contract.ts +16 -7
  30. package/src/cli/commands/ask.ts +7 -0
  31. package/src/cli/commands/collection/index.ts +5 -0
  32. package/src/cli/commands/collection/policy.ts +126 -0
  33. package/src/cli/commands/context-build.ts +5 -0
  34. package/src/cli/commands/daemon.ts +45 -3
  35. package/src/cli/commands/egress-audit.ts +68 -0
  36. package/src/cli/commands/embed.ts +2 -0
  37. package/src/cli/commands/query.ts +12 -0
  38. package/src/cli/commands/replay.ts +13 -3
  39. package/src/cli/commands/vsearch.ts +3 -1
  40. package/src/cli/program.ts +123 -0
  41. package/src/config/index.ts +9 -0
  42. package/src/config/types.ts +50 -0
  43. package/src/core/browser-clip.ts +16 -1
  44. package/src/core/collection-egress-policy-projection.ts +28 -0
  45. package/src/core/collection-egress-policy-service.ts +443 -0
  46. package/src/core/collection-egress-policy-validation.ts +242 -0
  47. package/src/core/config-mutation.ts +31 -19
  48. package/src/core/context-capsule-schema.ts +111 -1
  49. package/src/core/context-capsule-validation.ts +4 -4
  50. package/src/core/context-capsule-verification.ts +5 -1
  51. package/src/core/context-capsule.ts +177 -132
  52. package/src/core/context-evidence.ts +86 -14
  53. package/src/core/destination-classifier.ts +402 -0
  54. package/src/core/egress-audit.ts +239 -0
  55. package/src/core/egress-authorization.ts +50 -0
  56. package/src/core/egress-enforcement.ts +264 -0
  57. package/src/core/egress-policy.ts +440 -0
  58. package/src/core/egress-provenance.ts +336 -0
  59. package/src/core/job-manager.ts +37 -0
  60. package/src/core/network-boundary-inventory.ts +261 -0
  61. package/src/core/retrieval-qrels.ts +6 -0
  62. package/src/core/retrieval-replay.ts +18 -4
  63. package/src/core/retrieval-trace-export.ts +23 -4
  64. package/src/core/retrieval-trace-management-helpers.ts +1 -0
  65. package/src/core/retrieval-trace-management-types.ts +3 -0
  66. package/src/core/retrieval-trace-management.ts +9 -1
  67. package/src/core/retrieval-trace-session.ts +94 -0
  68. package/src/core/retrieval-trace.ts +22 -0
  69. package/src/ingestion/record-adapter.ts +12 -1
  70. package/src/ingestion/record-container.ts +38 -22
  71. package/src/ingestion/sync.ts +15 -0
  72. package/src/ingestion/types.ts +2 -0
  73. package/src/llm/errors.ts +10 -0
  74. package/src/llm/http-inference.ts +175 -0
  75. package/src/llm/http-policy.ts +537 -0
  76. package/src/llm/httpEmbedding.ts +47 -28
  77. package/src/llm/httpGeneration.ts +31 -18
  78. package/src/llm/httpRerank.ts +30 -18
  79. package/src/llm/index.ts +1 -0
  80. package/src/llm/nodeLlamaCpp/adapter.ts +55 -20
  81. package/src/llm/pinned-http-connection.ts +177 -0
  82. package/src/mcp/context.ts +53 -1
  83. package/src/mcp/http-egress.ts +220 -0
  84. package/src/mcp/http-security.ts +32 -21
  85. package/src/mcp/http-session.ts +13 -2
  86. package/src/mcp/http-transport.ts +96 -6
  87. package/src/mcp/sync-egress.ts +24 -0
  88. package/src/mcp/tools/add-collection.ts +4 -0
  89. package/src/mcp/tools/ask.ts +1 -1
  90. package/src/mcp/tools/context.ts +9 -2
  91. package/src/mcp/tools/egress.ts +247 -0
  92. package/src/mcp/tools/embed.ts +1 -0
  93. package/src/mcp/tools/index-cmd.ts +7 -0
  94. package/src/mcp/tools/index.ts +98 -0
  95. package/src/mcp/tools/query.ts +10 -0
  96. package/src/mcp/tools/remove-collection.ts +4 -0
  97. package/src/mcp/tools/sync.ts +6 -0
  98. package/src/mcp/tools/trace.ts +7 -1
  99. package/src/mcp/tools/vsearch.ts +1 -0
  100. package/src/pipeline/egress-lineage.ts +124 -0
  101. package/src/pipeline/hybrid.ts +14 -0
  102. package/src/pipeline/search.ts +12 -0
  103. package/src/pipeline/types.ts +3 -0
  104. package/src/pipeline/vsearch.ts +41 -20
  105. package/src/publish/artifact.ts +31 -3
  106. package/src/publish/export-service.ts +25 -0
  107. package/src/sdk/client.ts +119 -2
  108. package/src/sdk/embed.ts +1 -0
  109. package/src/sdk/types.ts +33 -0
  110. package/src/serve/clipper-capture.ts +5 -1
  111. package/src/serve/closed-json.ts +61 -0
  112. package/src/serve/config-sync.ts +4 -1
  113. package/src/serve/context.ts +1 -0
  114. package/src/serve/doc-events.ts +110 -39
  115. package/src/serve/public/components/CollectionEgressCheckPanel.tsx +411 -0
  116. package/src/serve/public/components/CollectionEgressPolicyEditor.tsx +78 -0
  117. package/src/serve/public/components/CollectionModelDialog.tsx +93 -9
  118. package/src/serve/public/components/EgressAuditPanel.tsx +278 -0
  119. package/src/serve/public/globals.built.css +1 -1
  120. package/src/serve/public/pages/Collections.tsx +3 -0
  121. package/src/serve/resident-request.ts +80 -3
  122. package/src/serve/resident-runtime.ts +63 -1
  123. package/src/serve/routes/api.ts +174 -0
  124. package/src/serve/routes/clipper.ts +64 -1
  125. package/src/serve/routes/mcp.ts +6 -0
  126. package/src/serve/routes/traces.ts +27 -4
  127. package/src/serve/server.ts +118 -7
  128. package/src/store/migrations/023-collection-egress-policy.ts +61 -0
  129. package/src/store/migrations/024-egress-derived-lineage.ts +121 -0
  130. package/src/store/migrations/025-collection-egress-policy-revision.ts +40 -0
  131. package/src/store/migrations/index.ts +6 -0
  132. package/src/store/retrieval-trace-codec.ts +15 -0
  133. package/src/store/sqlite/adapter.ts +170 -7
  134. package/src/store/sqlite/change-journal-store.ts +41 -2
  135. package/src/store/sqlite/egress-audit-store.ts +485 -0
  136. package/src/store/sqlite/retrieval-trace-management-store.ts +47 -6
  137. package/src/store/sqlite/retrieval-trace-retention.ts +2 -0
  138. package/src/store/sqlite/retrieval-trace-rows.ts +8 -1
  139. package/src/store/sqlite/retrieval-trace-store.ts +104 -5
  140. package/src/store/types.ts +126 -1
  141. package/browser-extension/artifacts/gno-browser-clipper-v1.28.0.zip +0 -0
  142. package/browser-extension/artifacts/gno-browser-clipper-v1.28.0.zip.sha256 +0 -1
  143. package/browser-extension/dist/chunk-vn5f663b.js +0 -50
@@ -0,0 +1,278 @@
1
+ import {
2
+ ChevronRightIcon,
3
+ Loader2Icon,
4
+ ReceiptTextIcon,
5
+ Trash2Icon,
6
+ } from "lucide-react";
7
+ import { useCallback, useEffect, useState } from "react";
8
+
9
+ import { apiFetch } from "../hooks/use-api";
10
+ import { Button } from "./ui/button";
11
+
12
+ interface AuditReceipt {
13
+ action: string;
14
+ auditId: string;
15
+ byteSize: number;
16
+ contentClass: string;
17
+ createdAtMs: number;
18
+ decision: "allow" | "deny";
19
+ destinationZone: string;
20
+ effectivePolicy: string;
21
+ reasonCode: string;
22
+ }
23
+
24
+ interface AuditPage {
25
+ nextCursor: string | null;
26
+ receipts: AuditReceipt[];
27
+ }
28
+
29
+ interface AuditStatus {
30
+ bytes: number;
31
+ receipts: number;
32
+ retention: {
33
+ maxAgeDays: number;
34
+ maxBytes: number;
35
+ maxReceipts: number;
36
+ };
37
+ }
38
+
39
+ interface CleanupResult {
40
+ auditId?: string;
41
+ checkpointedFrames: number;
42
+ deleted: number;
43
+ physicalCleanup: string;
44
+ remainingWalFrames: number;
45
+ }
46
+
47
+ export function EgressAuditPanel() {
48
+ const [receipts, setReceipts] = useState<AuditReceipt[]>([]);
49
+ const [nextCursor, setNextCursor] = useState<string | null>(null);
50
+ const [status, setStatus] = useState<AuditStatus | null>(null);
51
+ const [selected, setSelected] = useState<AuditReceipt | null>(null);
52
+ const [pendingDelete, setPendingDelete] = useState<string | null>(null);
53
+ const [purgeConfirmed, setPurgeConfirmed] = useState(false);
54
+ const [cleanup, setCleanup] = useState<CleanupResult | null>(null);
55
+ const [loading, setLoading] = useState(false);
56
+ const [error, setError] = useState<string | null>(null);
57
+
58
+ const loadStatus = useCallback(async () => {
59
+ const response = await apiFetch<AuditStatus>("/api/egress/audits/status");
60
+ if (response.data) setStatus(response.data);
61
+ else if (response.error) setError(response.error);
62
+ }, []);
63
+
64
+ const loadPage = useCallback(async (cursor?: string) => {
65
+ setLoading(true);
66
+ setError(null);
67
+ const suffix = cursor
68
+ ? `?limit=10&cursor=${encodeURIComponent(cursor)}`
69
+ : "?limit=10";
70
+ const response = await apiFetch<AuditPage>(`/api/egress/audits${suffix}`);
71
+ setLoading(false);
72
+ if (response.error || !response.data) {
73
+ setError(response.error ?? "Audit list failed");
74
+ return;
75
+ }
76
+ const page = response.data;
77
+ setReceipts((current) =>
78
+ cursor ? [...current, ...page.receipts] : page.receipts
79
+ );
80
+ setNextCursor(page.nextCursor);
81
+ }, []);
82
+
83
+ useEffect(() => {
84
+ void Promise.all([loadPage(), loadStatus()]);
85
+ }, [loadPage, loadStatus]);
86
+
87
+ const show = async (auditId: string) => {
88
+ setError(null);
89
+ const response = await apiFetch<{ receipt: AuditReceipt }>(
90
+ `/api/egress/audits/${encodeURIComponent(auditId)}`
91
+ );
92
+ if (response.data) setSelected(response.data.receipt);
93
+ else setError(response.error ?? "Audit receipt unavailable");
94
+ };
95
+
96
+ const remove = async (auditId: string) => {
97
+ setError(null);
98
+ const response = await apiFetch<CleanupResult>(
99
+ `/api/egress/audits/${encodeURIComponent(auditId)}`,
100
+ { method: "DELETE" }
101
+ );
102
+ setPendingDelete(null);
103
+ if (response.error || !response.data) {
104
+ setError(response.error ?? "Audit deletion failed");
105
+ return;
106
+ }
107
+ setCleanup(response.data);
108
+ setSelected((current) => (current?.auditId === auditId ? null : current));
109
+ setReceipts((current) =>
110
+ current.filter((receipt) => receipt.auditId !== auditId)
111
+ );
112
+ await loadStatus();
113
+ };
114
+
115
+ const purge = async () => {
116
+ setError(null);
117
+ const response = await apiFetch<CleanupResult>("/api/egress/audits", {
118
+ method: "DELETE",
119
+ });
120
+ setPurgeConfirmed(false);
121
+ if (response.error || !response.data) {
122
+ setError(response.error ?? "Audit purge failed");
123
+ return;
124
+ }
125
+ setCleanup(response.data);
126
+ setReceipts([]);
127
+ setNextCursor(null);
128
+ setSelected(null);
129
+ await loadStatus();
130
+ };
131
+
132
+ return (
133
+ <section
134
+ aria-labelledby="egress-audit-title"
135
+ className="space-y-3 border-border/15 border-t px-6 py-5"
136
+ >
137
+ <div className="flex items-start justify-between gap-4">
138
+ <div>
139
+ <h3
140
+ className="flex items-center gap-2 font-medium text-[13px]"
141
+ id="egress-audit-title"
142
+ >
143
+ <ReceiptTextIcon className="size-3.5 text-secondary/70" />
144
+ Local audit receipts
145
+ </h3>
146
+ <p className="mt-1 text-muted-foreground/50 text-xs">
147
+ Content-free decisions; newest first; retained locally.
148
+ </p>
149
+ </div>
150
+ <p className="font-mono text-[10px] text-muted-foreground/50">
151
+ {status
152
+ ? `${status.receipts} receipts · ${status.bytes} bytes`
153
+ : "loading status"}
154
+ </p>
155
+ </div>
156
+
157
+ {error ? (
158
+ <p className="text-destructive text-xs" role="alert">
159
+ {error}
160
+ </p>
161
+ ) : null}
162
+
163
+ <div className="max-h-44 overflow-y-auto rounded-md border border-border/20">
164
+ {receipts.length === 0 && !loading ? (
165
+ <p className="p-3 text-muted-foreground/50 text-xs">
166
+ No audit receipts yet.
167
+ </p>
168
+ ) : null}
169
+ {receipts.map((receipt) => (
170
+ <div
171
+ className="flex items-center gap-2 border-border/15 border-b px-3 py-2 last:border-0"
172
+ key={receipt.auditId}
173
+ >
174
+ <button
175
+ className="min-w-0 flex-1 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-secondary"
176
+ onClick={() => void show(receipt.auditId)}
177
+ type="button"
178
+ >
179
+ <span className="block truncate font-mono text-[10px]">
180
+ {receipt.decision} · {receipt.reasonCode}
181
+ </span>
182
+ <span className="block text-[10px] text-muted-foreground/45">
183
+ {receipt.action} / {receipt.destinationZone} /{" "}
184
+ {receipt.contentClass}
185
+ </span>
186
+ </button>
187
+ {pendingDelete === receipt.auditId ? (
188
+ <div className="flex gap-1">
189
+ <Button
190
+ onClick={() => void remove(receipt.auditId)}
191
+ size="sm"
192
+ type="button"
193
+ variant="destructive"
194
+ >
195
+ Confirm
196
+ </Button>
197
+ <Button
198
+ onClick={() => setPendingDelete(null)}
199
+ size="sm"
200
+ type="button"
201
+ variant="ghost"
202
+ >
203
+ Cancel
204
+ </Button>
205
+ </div>
206
+ ) : (
207
+ <Button
208
+ aria-label="Delete audit receipt"
209
+ onClick={() => setPendingDelete(receipt.auditId)}
210
+ size="icon-sm"
211
+ type="button"
212
+ variant="ghost"
213
+ >
214
+ <Trash2Icon className="size-3" />
215
+ </Button>
216
+ )}
217
+ </div>
218
+ ))}
219
+ </div>
220
+
221
+ {nextCursor ? (
222
+ <Button
223
+ disabled={loading}
224
+ onClick={() => void loadPage(nextCursor)}
225
+ size="sm"
226
+ type="button"
227
+ variant="outline"
228
+ >
229
+ {loading ? <Loader2Icon className="size-3 animate-spin" /> : null}
230
+ Load older
231
+ <ChevronRightIcon className="size-3" />
232
+ </Button>
233
+ ) : null}
234
+
235
+ {selected ? (
236
+ <output className="block rounded-md border border-border/20 bg-muted/10 p-3 font-mono text-[10px]">
237
+ <span className="block">{selected.auditId}</span>
238
+ <span className="block text-muted-foreground/60">
239
+ {selected.effectivePolicy} · {selected.reasonCode} ·{" "}
240
+ {selected.byteSize} bytes
241
+ </span>
242
+ </output>
243
+ ) : null}
244
+
245
+ {cleanup ? (
246
+ <output
247
+ aria-live="polite"
248
+ className="block text-[10px] text-muted-foreground/60"
249
+ >
250
+ Deleted {cleanup.deleted}; cleanup {cleanup.physicalCleanup};
251
+ checkpointed {cleanup.checkpointedFrames}; WAL remaining{" "}
252
+ {cleanup.remainingWalFrames}.
253
+ </output>
254
+ ) : null}
255
+
256
+ <div className="flex flex-wrap items-center gap-3 border-border/15 border-t pt-3">
257
+ <label className="flex items-center gap-2 text-xs">
258
+ <input
259
+ checked={purgeConfirmed}
260
+ onChange={(event) => setPurgeConfirmed(event.target.checked)}
261
+ type="checkbox"
262
+ />
263
+ Confirm purge of all local audit receipts
264
+ </label>
265
+ <Button
266
+ className="ml-auto"
267
+ disabled={!purgeConfirmed}
268
+ onClick={() => void purge()}
269
+ size="sm"
270
+ type="button"
271
+ variant="destructive"
272
+ >
273
+ Purge audits
274
+ </Button>
275
+ </div>
276
+ </section>
277
+ );
278
+ }