@gmickel/gno 1.32.0 → 1.34.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 (54) hide show
  1. package/README.md +17 -3
  2. package/assets/skill/SKILL.md +30 -0
  3. package/assets/skill/cli-reference.md +10 -2
  4. package/browser-extension/artifacts/{gno-browser-clipper-v1.32.0.zip → gno-browser-clipper-v1.34.0.zip} +0 -0
  5. package/browser-extension/artifacts/gno-browser-clipper-v1.34.0.zip.sha256 +1 -0
  6. package/browser-extension/dist/manifest.json +1 -1
  7. package/package.json +5 -1
  8. package/spec/cli.md +60 -1
  9. package/spec/mcp.md +21 -0
  10. package/spec/output-schemas/audit-report.schema.json +284 -0
  11. package/spec/output-schemas/publish-artifact.schema.json +76 -1
  12. package/src/cli/commands/audit.ts +231 -0
  13. package/src/cli/commands/publish.ts +43 -7
  14. package/src/cli/errors.ts +9 -2
  15. package/src/cli/program.ts +112 -0
  16. package/src/core/audit-contract.ts +296 -0
  17. package/src/core/audit-freshness.ts +233 -0
  18. package/src/core/audit-links.ts +222 -0
  19. package/src/core/audit-provenance.ts +154 -0
  20. package/src/core/audit-report.ts +318 -0
  21. package/src/core/audit-workspace.ts +678 -0
  22. package/src/core/audit.ts +569 -0
  23. package/src/core/capture.ts +196 -3
  24. package/src/core/document-capabilities.ts +9 -8
  25. package/src/core/record-metadata.ts +33 -0
  26. package/src/ingestion/strip.ts +152 -26
  27. package/src/mcp/http-egress.ts +8 -0
  28. package/src/mcp/tools/audit.ts +97 -0
  29. package/src/mcp/tools/index.ts +13 -0
  30. package/src/publish/artifact-asset-codec.ts +75 -0
  31. package/src/publish/artifact-asset-contract.ts +152 -0
  32. package/src/publish/artifact-asset-parse.ts +401 -0
  33. package/src/publish/artifact-asset-sniff.ts +108 -0
  34. package/src/publish/artifact-asset-validate.ts +209 -0
  35. package/src/publish/artifact-assets.ts +58 -0
  36. package/src/publish/artifact-validation.ts +32 -6
  37. package/src/publish/artifact.ts +50 -3
  38. package/src/publish/attachment-bundle.ts +145 -0
  39. package/src/publish/attachment-discover.ts +203 -0
  40. package/src/publish/attachment-load.ts +133 -0
  41. package/src/publish/attachment-obsidian.ts +45 -0
  42. package/src/publish/attachment-path.ts +334 -0
  43. package/src/publish/attachment-raster.ts +852 -0
  44. package/src/publish/attachment-resolver.ts +280 -0
  45. package/src/publish/attachment-types.ts +54 -0
  46. package/src/publish/encrypted-export.ts +121 -44
  47. package/src/publish/export-attachments.ts +224 -0
  48. package/src/publish/export-service.ts +142 -80
  49. package/src/publish/obsidian-sanitize.ts +121 -13
  50. package/src/serve/routes/api.ts +2 -1
  51. package/src/store/sqlite/adapter.ts +82 -0
  52. package/src/store/sqlite/graph-link-bulk-resolver.ts +191 -0
  53. package/src/store/sqlite/graph-link-resolver.ts +241 -2
  54. package/browser-extension/artifacts/gno-browser-clipper-v1.32.0.zip.sha256 +0 -1
package/README.md CHANGED
@@ -117,7 +117,7 @@ gno daemon --detach # headless indexing + resident MCP gateway
117
117
 
118
118
  <!-- public-truth:current-version -->
119
119
 
120
- > Current release: **v1.32.0** — see [CHANGELOG.md](./CHANGELOG.md)
120
+ > Current release: **v1.34.0** — see [CHANGELOG.md](./CHANGELOG.md)
121
121
 
122
122
  <!-- /public-truth -->
123
123
 
@@ -174,6 +174,10 @@ gno daemon --detach # headless indexing + resident MCP gateway
174
174
  `local_only`, `lan`, or `remote` boundary that follows mixed and derived
175
175
  evidence through resident serving, inference, publishing, exports, Capsules,
176
176
  and traces. Authentication never overrides policy.
177
+ - **Read-only integrity audits**: `gno audit` and MCP `gno_audit` inspect local
178
+ links, declared provenance, and source/index freshness offline. Stable,
179
+ bounded findings distinguish complete, partial, unavailable, and changing
180
+ evidence without repairing or persisting anything.
177
181
  - **Schema-lite content types**: optional `contentTypes` rules map configured
178
182
  frontmatter `type` values or path prefixes to canonical `contentType` metadata
179
183
  in JSON search/query results and can apply one bounded, explainable
@@ -773,7 +777,7 @@ GNO is local-first, but sometimes you want a URL to send someone. [**gno.sh**](h
773
777
 
774
778
  ![gno.sh publish reader](./assets/screenshots/publish-reader.jpg)
775
779
 
776
- The workflow is deliberately explicit: **export locally → upload artifact → share URL**. Private and `publish: false` notes stay on your machine. Exported artifacts omit local collection paths and source URIs.
780
+ The workflow is deliberately explicit: **export locally → upload artifact → share URL**. Private and `publish: false` notes stay on your machine. Exported artifacts omit local collection paths and source URIs. Local PNG/JPEG/GIF/WebP/AVIF images (Markdown and Obsidian embeds) are bundled into the artifact with SHA-256 dedup, `gno-asset:` sentinels, and an exact 100 MiB serialized ceiling; external HTTPS images stay as URLs. Encrypted shares keep image bytes inside ciphertext only. Invite-only note text publishes today, but invite-only image delivery on gno.sh is not supported yet.
777
781
 
778
782
  ```bash
779
783
  # Export a single note
@@ -817,6 +821,15 @@ agent capabilities or manifests. Encrypted exports remain ciphertext-only.
817
821
  Reader metadata drops embedded local path or GNO/file URI tokens; canonical
818
822
  and image fields accept only uncredentialed public HTTP(S) targets.
819
823
 
824
+ Resolved local PNG, JPEG, GIF, WebP, and AVIF references are bundled,
825
+ content-addressed, and deduplicated; external public HTTPS images remain
826
+ external. The exact serialized artifact is capped at 100 MiB. Public images
827
+ use immutable snapshot/generation URLs, secret-link images are authorized on
828
+ every request, and encrypted image bytes exist only inside ciphertext before
829
+ the browser creates scoped Blob URLs. Invite-only bundled-image delivery is
830
+ currently fail-closed; use an asset-free invite, secret link, or encrypted
831
+ share when local images are required.
832
+
820
833
  Republishing a public, secret-link, or invite-only artifact updates the same URL. Encrypted shares should be replaced from a fresh local export so the server never needs your plaintext.
821
834
 
822
835
  Encrypted source-backed publish on `gno.sh` is intentionally disabled. For encrypted shares, use:
@@ -936,7 +949,8 @@ graph TD
936
949
  | **Local LLM** | AI answers via llama.cpp, no API keys |
937
950
  | **Remote Inference** | Optional HTTP endpoints for embedding, reranking, expansion, and generation |
938
951
  | **Privacy First** | Fail-closed per-collection egress policy; no telemetry; explicit network use |
939
- | **MCP Server** | 10 automatic client targets; 25 read-only tools, 40 with writes enabled |
952
+ | **MCP Server** | 10 automatic client targets; 32 read-only tools, 50 with writes enabled |
953
+ | **Integrity Audits** | Offline link, declared-provenance, and freshness reports with stable IDs |
940
954
  | **Knowledge Delta** | Bounded metadata history, structural diffs, and dependency impact paths |
941
955
  | **Context Capsules** | Deterministic evidence bundles plus saved-file freshness reverification |
942
956
  | **Verified Ask** | Claim-by-claim evidence checks with explicit abstention |
@@ -92,6 +92,17 @@ Recipe rules:
92
92
  | **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents |
93
93
  | **Admin** | `status`, `doctor`, `cleanup`, `reset`, `vec`, `completion` | Maintenance and diagnostics |
94
94
 
95
+ ### Publishing with local images
96
+
97
+ `gno publish export` bundles resolved local PNG, JPEG, GIF, WebP, and AVIF
98
+ references, deduplicates identical bytes, preserves public HTTPS images, and
99
+ enforces the 100 MiB exact serialized artifact limit. Review `assetSummary`
100
+ in `--json` output for unresolved or unsupported references. Public and
101
+ secret-link readers serve authorized hosted URLs; encrypted exports keep image
102
+ bytes inside ciphertext and create scoped Blob URLs only after browser
103
+ decryption. Hosted invite-only bundled-image delivery is currently
104
+ fail-closed, so use an asset-free invite, secret link, or encrypted share.
105
+
95
106
  ## Search Modes
96
107
 
97
108
  | Command | Speed | Best For |
@@ -302,6 +313,23 @@ at the remote service. For gno.sh, supported private links can be revoked or
302
313
  expired in Studio; public-space deletion is not yet self-service, so request
303
314
  takedown. Encrypted gno.sh shares are client-encrypted and never server-decrypted.
304
315
 
316
+ ## Read-Only Knowledge Integrity Audits
317
+
318
+ Use `gno audit [links|provenance|freshness|all] --json` or read-only MCP
319
+ `gno_audit` only when the user asks what needs attention in a workspace. These
320
+ offline audits inspect parsed local links, explicitly declared capture/logical-
321
+ record provenance, and observable source/index freshness. They never repair,
322
+ rewrite, persist findings, judge factual truth, or replace retrieval.
323
+
324
+ Treat exit `4` as a complete report with findings. Exit `5` or report status
325
+ `partial`/`changed_during_audit` means evidence is unavailable, inconclusive,
326
+ cancelled, truncated, or repeatedly changed—never healthy. Preserve stable
327
+ finding IDs and exact totals when summarizing bounded results. Age is only a
328
+ review signal when `maxAgeDays`/`--max-age-days` is explicitly supplied. Apply
329
+ collection/path/tag scope and orphan roots/ignore prefixes only from the user's
330
+ request. `gno egress-audit` is separate: it manages content-free transport-
331
+ policy receipts.
332
+
305
333
  ## MCP Retrieval Strategy
306
334
 
307
335
  For a long-lived client that supports Streamable HTTP, start one resident owner
@@ -366,6 +394,8 @@ Use narrower tools when the request tells you to:
366
394
  - `gno_search`: exact phrase, filename, identifier, stack trace, error text
367
395
  - `gno_vsearch`: conceptual similarity when exact wording differs
368
396
  - `gno_status`: stale results, missing embeddings, vector unavailable
397
+ - `gno_audit`: explicit offline workspace-integrity review; report findings and
398
+ partial evidence, never mutate or imply repairs
369
399
  - `gno_graph`: graph report/stats, hubs, isolates, unresolved links, edge confidence/audit, communities, unfamiliar corpus overview
370
400
  - `gno_graph_query`: bounded typed-edge traversal from a known document
371
401
  - `gno_graph_neighbors`: relationship/corpus-navigation questions around a known document
@@ -887,11 +887,19 @@ export pipeline runs a sanitizer over each note's markdown. It:
887
887
  `_internal/` convention is treated as never-publish)
888
888
  - converts `[[Target|Alias]]` to the alias text, and `[[Target]]` to the
889
889
  tail segment of the target
890
- - drops `![[image.png]]` embeds (attachments are not bundled yet) with a
891
- warning so the author can migrate to `![alt](url)` or wait for bundling
890
+ - resolves local `![[image.png]]` / Markdown image refs for PNG/JPEG/GIF/WebP/
891
+ AVIF (AVIF must be AV1-decodable at producer ingress) into content-addressed
892
+ `gno-asset:<sha256>` sentinels (deduped; exact 100 MiB serialized ceiling;
893
+ ciphertext field bounds align to that envelope); preserves external HTTPS
894
+ images; skips fenced code (backtick and tilde); drops unsupported/missing/
895
+ unsafe refs with diagnostics
892
896
  - refuses to export a note whose frontmatter contains `publish: false`
893
897
  (single-note export errors; collection export silently skips)
894
898
 
899
+ Successful exports include `assetSummary` in `--json`. Encrypted visibility
900
+ keeps raster bytes inside ciphertext only. Hosted invite-only image delivery
901
+ is currently fail-closed on gno.sh.
902
+
895
903
  Every sanitizer decision surfaces in the CLI output as a "Preprocessor
896
904
  notes" section, on the `--json` response under `warnings`, and on
897
905
  `--preview` as a structured report — so nothing is silently lost.
@@ -0,0 +1 @@
1
+ 0acc125d848721bdced540fe49412ef8c83df5d4ff3ba086076c46ed9d441998 gno-browser-clipper-v1.34.0.zip
@@ -21,5 +21,5 @@
21
21
  "content_security_policy": {
22
22
  "extension_pages": "script-src 'self'; object-src 'none'; connect-src http://127.0.0.1:*"
23
23
  },
24
- "version": "1.32.0"
24
+ "version": "1.34.0"
25
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "1.32.0",
3
+ "version": "1.34.0",
4
4
  "description": "Local semantic search for your documents. Index Markdown, PDF, and Office files with hybrid BM25 + vector search.",
5
5
  "keywords": [
6
6
  "embeddings",
@@ -178,6 +178,9 @@
178
178
  "jsonc-parser": "3.3.1",
179
179
  "lucide-react": "1.28.0",
180
180
  "markitdown-ts": "0.0.10",
181
+ "mdast-util-from-markdown": "2.0.3",
182
+ "mdast-util-gfm": "3.1.0",
183
+ "micromark-extension-gfm": "3.0.0",
181
184
  "minimatch": "10.2.6",
182
185
  "nanoid": "6.0.0",
183
186
  "node-llama-cpp": "3.19.1",
@@ -190,6 +193,7 @@
190
193
  "react-markdown": "10.1.0",
191
194
  "rehype-sanitize": "6.0.0",
192
195
  "remark-gfm": "4.0.1",
196
+ "sharp": "0.35.3",
193
197
  "shiki": "4.3.1",
194
198
  "sqlite-vec": "0.1.9",
195
199
  "streamdown": "2.5.0",
package/spec/cli.md CHANGED
@@ -692,6 +692,50 @@ projection.
692
692
  content-free decision, lineage, partial disclosure, audit metadata, and
693
693
  remediation contract.
694
694
 
695
+ ### gno audit
696
+
697
+ Read-only, offline knowledge-integrity audits. This command is distinct from
698
+ `gno egress-audit`: it examines workspace links, declared provenance
699
+ requirements, and source/index freshness without persisting findings or
700
+ modifying notes, configuration, index rows, graph edges, or daemon state.
701
+
702
+ ```bash
703
+ gno audit [links|provenance|freshness|all] [--collection <name>...] \
704
+ [--path <prefix>...] [--tag <tag>...] [--max-findings <n>] \
705
+ [--max-age-days <days>] [--orphan-root <uri>...] \
706
+ [--orphan-ignore-prefix <prefix>...] [--no-progress] \
707
+ [--json] [--output <path>]
708
+ ```
709
+
710
+ The default category is `all`; `--max-findings` defaults to 100 and is bounded
711
+ to 1–1000. Truncation limits returned findings but preserves exact totals.
712
+ `--output` writes only the requested report artifact with local file
713
+ permissions. Human output renders the same report represented by
714
+ `audit-report.schema.json`.
715
+ When attached to a terminal, human mode reports snapshot/rule progress on
716
+ stderr; `--no-progress`, `--quiet`, and JSON mode suppress it. `Ctrl-C` returns
717
+ the bounded report gathered so far with partial status and exit 5. Freshness
718
+ age is reported only when `--max-age-days` supplies an explicit policy.
719
+
720
+ Rule statuses are `pass`, `fail`, `skip`, `unavailable`, and `inconclusive`.
721
+ Report statuses are `complete`, `partial`, `changed_during_audit`, and `failed`.
722
+ A skipped, unavailable, inconclusive, or changing check is never rendered as
723
+ healthy.
724
+
725
+ **Exit Codes:**
726
+
727
+ - `0` — complete and clean
728
+ - `1` — invalid input
729
+ - `2` — runtime failure
730
+ - `4` — complete report with findings
731
+ - `5` — partial, inconclusive, unavailable, or changed-during-audit evidence
732
+
733
+ The JSON contract is versioned as `gno://schemas/audit-report@1.0`. Finding IDs
734
+ are stable SHA-256 identities derived from rule, normalized subject/location,
735
+ and load-bearing evidence. Wall-clock timing and traversal order do not affect
736
+ identity. A source/index fingerprint change causes one bounded retry and then
737
+ `changed_during_audit`; it can never produce a clean exit.
738
+
695
739
  ### gno egress-audit
696
740
 
697
741
  Manage local content-free policy decision receipts:
@@ -1949,6 +1993,19 @@ tokens MUST be filtered. Canonical and image metadata MUST contain
1949
1993
  uncredentialed public HTTP(S) targets; local hostnames and literal loopback,
1950
1994
  private, or link-local addresses MUST be filtered.
1951
1995
 
1996
+ When local raster attachments are bundled, the V1 artifact MAY include
1997
+ `assets[]` and `requiredCapabilities: ["bundled-raster-assets@1"]`. Export
1998
+ success payloads (CLI `--json` and `POST /api/publish/export`) MUST include a
1999
+ deterministic `assetSummary` with asset/ref counts, raw/encoded/final UTF-8
2000
+ upload bytes, dedup savings, external image count, and unresolved/unsupported
2001
+ diagnostics. Exact final serialized upload bytes MUST be enforced against the
2002
+ 100 MiB ceiling before returning. Encrypted V2 ciphertext string bounds MUST
2003
+ align to that same 100 MiB final-envelope budget and MUST NOT replace exact
2004
+ final serialized measurement as the authoritative upload gate. Producer
2005
+ ingress MUST require AV1-decodable AVIF payloads (structural BMFF alone is
2006
+ insufficient). Asset-free exports omit `assets` /
2007
+ `requiredCapabilities` and report zero asset counts.
2008
+
1952
2009
  Secret-link and invite-only V1 spaces MUST NOT contain a manifest or agent
1953
2010
  capability field. Encrypted V2 spaces MUST contain only ciphertext parameters,
1954
2011
  the opaque secret token, route slug, source type, and encrypted visibility; no
@@ -1956,7 +2013,9 @@ plaintext manifest or evidence may appear outside the ciphertext. V2 builders
1956
2013
  MUST emit a closed projection, validate payload strings as non-empty bounded
1957
2014
  base64, require a positive safe-integer KDF iteration count, and bound the
1958
2015
  non-blank opaque token. Caller-supplied extension fields MUST NOT enter the
1959
- artifact.
2016
+ artifact. Encrypted export MUST place bundled assets only inside the encrypted
2017
+ client payload. The outer V2 envelope MUST contain neither plaintext note
2018
+ content, asset descriptors, source references, nor raster bytes.
1960
2019
 
1961
2020
  ---
1962
2021
 
package/spec/mcp.md CHANGED
@@ -152,6 +152,27 @@ Collection names are case-insensitive on input and normalized to lowercase in re
152
152
 
153
153
  ## Tools
154
154
 
155
+ ### Knowledge integrity audit contract
156
+
157
+ `gno_audit` is a read-only, offline tool that returns the same
158
+ `gno://schemas/audit-report@1.0` report as `gno audit`. Its closed input accepts
159
+ `category` (`links`, `provenance`, `freshness`, or `all`), collection/path/tag
160
+ filters, and `maxFindings` (1–1000). `maxAgeDays`, `orphanRoots`, and
161
+ `orphanIgnorePrefixes` are optional explicit policy inputs. Request
162
+ cancellation returns a partial report rather than a false clean result. The
163
+ tool is annotated with
164
+ `readOnlyHint: true`; the implementation must additionally prove that it never
165
+ modifies source files, config, index rows, graph edges, daemon state, or a
166
+ persisted audit baseline.
167
+
168
+ Rules report `pass`, `fail`, `skip`, `unavailable`, or `inconclusive`; reports
169
+ are `complete`, `partial`, `changed_during_audit`, or `failed`. Unavailable or
170
+ changing evidence never appears healthy. Stable finding IDs are derived from
171
+ rule, normalized subject/location, and evidence fingerprint. Responses are
172
+ canonically ordered and bounded while retaining exact pre-truncation totals.
173
+ This knowledge audit is distinct from the content-free `gno_egress_audit_*`
174
+ receipt-management tools.
175
+
155
176
  ### Agent Retrieval Playbook
156
177
 
157
178
  - Prefer `gno_context` when the agent needs a complete, bounded evidence handoff
@@ -0,0 +1,284 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "gno://schemas/audit-report@1.0",
4
+ "title": "GNO Knowledge Integrity Audit Report",
5
+ "description": "Deterministic read-only audit report for links, provenance, and freshness. Not egress-audit receipts.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schemaVersion",
10
+ "ruleSetVersion",
11
+ "status",
12
+ "scope",
13
+ "capabilities",
14
+ "fingerprints",
15
+ "versions",
16
+ "startedAt",
17
+ "completedAt",
18
+ "durationMs",
19
+ "rules",
20
+ "findings",
21
+ "counts",
22
+ "truncation",
23
+ "timing"
24
+ ],
25
+ "properties": {
26
+ "schemaVersion": { "const": "1.0" },
27
+ "ruleSetVersion": { "const": "1.0" },
28
+ "status": {
29
+ "enum": ["complete", "partial", "changed_during_audit", "failed"]
30
+ },
31
+ "scope": { "$ref": "#/definitions/scope" },
32
+ "capabilities": { "$ref": "#/definitions/capabilities" },
33
+ "fingerprints": { "$ref": "#/definitions/fingerprints" },
34
+ "versions": { "$ref": "#/definitions/versions" },
35
+ "startedAt": { "type": "string", "format": "date-time" },
36
+ "completedAt": { "type": "string", "format": "date-time" },
37
+ "durationMs": { "type": "integer", "minimum": 0 },
38
+ "rules": {
39
+ "type": "array",
40
+ "maxItems": 256,
41
+ "items": { "$ref": "#/definitions/ruleResult" }
42
+ },
43
+ "findings": {
44
+ "type": "array",
45
+ "maxItems": 1000,
46
+ "items": { "$ref": "#/definitions/finding" }
47
+ },
48
+ "counts": { "$ref": "#/definitions/counts" },
49
+ "truncation": { "$ref": "#/definitions/truncation" },
50
+ "timing": { "$ref": "#/definitions/timing" }
51
+ },
52
+ "definitions": {
53
+ "sha256": {
54
+ "type": "string",
55
+ "pattern": "^[a-f0-9]{64}$"
56
+ },
57
+ "category": {
58
+ "enum": ["links", "provenance", "freshness"]
59
+ },
60
+ "ruleStatus": {
61
+ "enum": ["pass", "fail", "skip", "unavailable", "inconclusive"]
62
+ },
63
+ "severity": {
64
+ "enum": ["error", "warning", "info"]
65
+ },
66
+ "scope": {
67
+ "type": "object",
68
+ "additionalProperties": false,
69
+ "required": ["categories", "collections", "paths", "tags", "indexName"],
70
+ "properties": {
71
+ "categories": {
72
+ "type": "array",
73
+ "minItems": 1,
74
+ "maxItems": 3,
75
+ "items": { "$ref": "#/definitions/category" },
76
+ "uniqueItems": true
77
+ },
78
+ "collections": {
79
+ "type": "array",
80
+ "maxItems": 256,
81
+ "items": { "type": "string", "minLength": 1, "maxLength": 256 }
82
+ },
83
+ "paths": {
84
+ "type": "array",
85
+ "maxItems": 256,
86
+ "items": { "type": "string", "minLength": 1, "maxLength": 2048 }
87
+ },
88
+ "tags": {
89
+ "type": "array",
90
+ "maxItems": 256,
91
+ "items": { "type": "string", "minLength": 1, "maxLength": 256 }
92
+ },
93
+ "indexName": { "type": "string", "minLength": 1, "maxLength": 64 }
94
+ }
95
+ },
96
+ "capabilities": {
97
+ "type": "object",
98
+ "additionalProperties": false,
99
+ "required": [
100
+ "indexReadable",
101
+ "sourcesReadable",
102
+ "linksGraphAvailable",
103
+ "provenanceSchemaAvailable",
104
+ "offline",
105
+ "llmDisabled"
106
+ ],
107
+ "properties": {
108
+ "indexReadable": { "type": "boolean" },
109
+ "sourcesReadable": { "type": "boolean" },
110
+ "linksGraphAvailable": { "type": "boolean" },
111
+ "provenanceSchemaAvailable": { "type": "boolean" },
112
+ "offline": { "const": true },
113
+ "llmDisabled": { "const": true }
114
+ }
115
+ },
116
+ "fingerprints": {
117
+ "type": "object",
118
+ "additionalProperties": false,
119
+ "required": ["config", "source", "index", "rules"],
120
+ "properties": {
121
+ "config": { "type": "string", "minLength": 0, "maxLength": 128 },
122
+ "source": { "type": "string", "minLength": 0, "maxLength": 128 },
123
+ "index": { "type": "string", "minLength": 0, "maxLength": 128 },
124
+ "rules": { "type": "string", "minLength": 0, "maxLength": 128 }
125
+ }
126
+ },
127
+ "versions": {
128
+ "type": "object",
129
+ "additionalProperties": false,
130
+ "required": ["gno", "schema", "ruleSet"],
131
+ "properties": {
132
+ "gno": { "type": "string", "minLength": 1, "maxLength": 64 },
133
+ "schema": { "const": "1.0" },
134
+ "ruleSet": { "const": "1.0" }
135
+ }
136
+ },
137
+ "evidence": {
138
+ "type": "object",
139
+ "additionalProperties": false,
140
+ "required": ["kind", "summary"],
141
+ "properties": {
142
+ "kind": { "type": "string", "minLength": 1, "maxLength": 128 },
143
+ "summary": { "type": "string", "minLength": 1, "maxLength": 512 },
144
+ "uri": { "type": "string", "minLength": 1, "maxLength": 2048 },
145
+ "path": { "type": "string", "minLength": 1, "maxLength": 2048 },
146
+ "detail": { "type": "string", "minLength": 1, "maxLength": 512 }
147
+ }
148
+ },
149
+ "finding": {
150
+ "type": "object",
151
+ "additionalProperties": false,
152
+ "required": [
153
+ "id",
154
+ "ruleId",
155
+ "category",
156
+ "severity",
157
+ "subject",
158
+ "location",
159
+ "message",
160
+ "evidence",
161
+ "guidance",
162
+ "evidenceFingerprint"
163
+ ],
164
+ "properties": {
165
+ "id": { "$ref": "#/definitions/sha256" },
166
+ "ruleId": { "type": "string", "minLength": 1, "maxLength": 128 },
167
+ "category": { "$ref": "#/definitions/category" },
168
+ "severity": { "$ref": "#/definitions/severity" },
169
+ "subject": { "type": "string", "minLength": 1, "maxLength": 2048 },
170
+ "location": { "type": ["string", "null"], "maxLength": 2048 },
171
+ "message": { "type": "string", "minLength": 1, "maxLength": 512 },
172
+ "evidence": {
173
+ "type": "array",
174
+ "maxItems": 8,
175
+ "items": { "$ref": "#/definitions/evidence" }
176
+ },
177
+ "guidance": {
178
+ "type": "array",
179
+ "maxItems": 4,
180
+ "items": { "type": "string", "minLength": 1, "maxLength": 256 }
181
+ },
182
+ "evidenceFingerprint": { "$ref": "#/definitions/sha256" }
183
+ }
184
+ },
185
+ "ruleResult": {
186
+ "type": "object",
187
+ "additionalProperties": false,
188
+ "required": [
189
+ "ruleId",
190
+ "category",
191
+ "status",
192
+ "message",
193
+ "findings",
194
+ "findingCount",
195
+ "examinedCount",
196
+ "durationMs",
197
+ "skipReason"
198
+ ],
199
+ "properties": {
200
+ "ruleId": { "type": "string", "minLength": 1, "maxLength": 128 },
201
+ "category": { "$ref": "#/definitions/category" },
202
+ "status": { "$ref": "#/definitions/ruleStatus" },
203
+ "message": { "type": "string", "minLength": 1, "maxLength": 512 },
204
+ "findings": {
205
+ "type": "array",
206
+ "maxItems": 1000,
207
+ "items": { "$ref": "#/definitions/finding" }
208
+ },
209
+ "findingCount": { "type": "integer", "minimum": 0 },
210
+ "examinedCount": { "type": "integer", "minimum": 0 },
211
+ "durationMs": { "type": "integer", "minimum": 0 },
212
+ "skipReason": { "type": ["string", "null"], "maxLength": 512 }
213
+ }
214
+ },
215
+ "counts": {
216
+ "type": "object",
217
+ "additionalProperties": false,
218
+ "required": ["rules", "findings", "examined"],
219
+ "properties": {
220
+ "rules": {
221
+ "type": "object",
222
+ "additionalProperties": false,
223
+ "required": [
224
+ "pass",
225
+ "fail",
226
+ "skip",
227
+ "unavailable",
228
+ "inconclusive",
229
+ "total"
230
+ ],
231
+ "properties": {
232
+ "pass": { "type": "integer", "minimum": 0 },
233
+ "fail": { "type": "integer", "minimum": 0 },
234
+ "skip": { "type": "integer", "minimum": 0 },
235
+ "unavailable": { "type": "integer", "minimum": 0 },
236
+ "inconclusive": { "type": "integer", "minimum": 0 },
237
+ "total": { "type": "integer", "minimum": 0 }
238
+ }
239
+ },
240
+ "findings": {
241
+ "type": "object",
242
+ "additionalProperties": false,
243
+ "required": ["total", "returned", "truncated"],
244
+ "properties": {
245
+ "total": { "type": "integer", "minimum": 0 },
246
+ "returned": { "type": "integer", "minimum": 0, "maximum": 1000 },
247
+ "truncated": { "type": "boolean" }
248
+ }
249
+ },
250
+ "examined": {
251
+ "type": "object",
252
+ "additionalProperties": false,
253
+ "required": ["documents"],
254
+ "properties": {
255
+ "documents": { "type": "integer", "minimum": 0 }
256
+ }
257
+ }
258
+ }
259
+ },
260
+ "truncation": {
261
+ "type": "object",
262
+ "additionalProperties": false,
263
+ "required": ["findingsTruncated", "maxFindings"],
264
+ "properties": {
265
+ "findingsTruncated": { "type": "boolean" },
266
+ "maxFindings": {
267
+ "type": "integer",
268
+ "minimum": 1,
269
+ "maximum": 1000
270
+ }
271
+ }
272
+ },
273
+ "timing": {
274
+ "type": "object",
275
+ "additionalProperties": false,
276
+ "required": ["snapshotMs", "rulesMs", "totalMs"],
277
+ "properties": {
278
+ "snapshotMs": { "type": "integer", "minimum": 0 },
279
+ "rulesMs": { "type": "integer", "minimum": 0 },
280
+ "totalMs": { "type": "integer", "minimum": 0 }
281
+ }
282
+ }
283
+ }
284
+ }
@@ -16,6 +16,10 @@
16
16
  "egressLineage": { "$ref": "#/definitions/egressLineage" },
17
17
  "source": { "$ref": "#/definitions/slug" },
18
18
  "exportedAt": { "type": "string", "format": "date-time" },
19
+ "requiredCapabilities": {
20
+ "$ref": "#/definitions/requiredCapabilities"
21
+ },
22
+ "assets": { "$ref": "#/definitions/assets" },
19
23
  "spaces": {
20
24
  "type": "array",
21
25
  "minItems": 1,
@@ -37,6 +41,9 @@
37
41
  "egressLineage": { "$ref": "#/definitions/egressLineage" },
38
42
  "source": { "$ref": "#/definitions/slug" },
39
43
  "exportedAt": { "type": "string", "format": "date-time" },
44
+ "requiredCapabilities": {
45
+ "$ref": "#/definitions/requiredCapabilities"
46
+ },
40
47
  "spaces": {
41
48
  "type": "array",
42
49
  "minItems": 1,
@@ -44,6 +51,74 @@
44
51
  }
45
52
  }
46
53
  },
54
+ "requiredCapabilities": {
55
+ "type": "array",
56
+ "uniqueItems": true,
57
+ "items": {
58
+ "type": "string",
59
+ "minLength": 1,
60
+ "maxLength": 128
61
+ }
62
+ },
63
+ "assets": {
64
+ "type": "array",
65
+ "items": { "$ref": "#/definitions/artifactAsset" }
66
+ },
67
+ "artifactAsset": {
68
+ "type": "object",
69
+ "additionalProperties": false,
70
+ "required": [
71
+ "id",
72
+ "mediaType",
73
+ "byteLength",
74
+ "sha256",
75
+ "width",
76
+ "height",
77
+ "encoding",
78
+ "data",
79
+ "references"
80
+ ],
81
+ "properties": {
82
+ "id": { "$ref": "#/definitions/hash" },
83
+ "mediaType": {
84
+ "enum": [
85
+ "image/png",
86
+ "image/jpeg",
87
+ "image/gif",
88
+ "image/webp",
89
+ "image/avif"
90
+ ]
91
+ },
92
+ "byteLength": { "type": "integer", "minimum": 1, "maximum": 104857600 },
93
+ "sha256": { "$ref": "#/definitions/hash" },
94
+ "width": { "type": "integer", "minimum": 1, "maximum": 16384 },
95
+ "height": { "type": "integer", "minimum": 1, "maximum": 16384 },
96
+ "encoding": { "const": "base64" },
97
+ "data": {
98
+ "type": "string",
99
+ "minLength": 1,
100
+ "maxLength": 139810134,
101
+ "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
102
+ },
103
+ "references": {
104
+ "type": "array",
105
+ "minItems": 1,
106
+ "items": {
107
+ "type": "object",
108
+ "additionalProperties": false,
109
+ "required": ["noteSlug", "sourceRef"],
110
+ "properties": {
111
+ "noteSlug": { "$ref": "#/definitions/slug" },
112
+ "sourceRef": {
113
+ "type": "string",
114
+ "minLength": 1,
115
+ "maxLength": 1024
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ },
47
122
  "slug": {
48
123
  "type": "string",
49
124
  "pattern": "^[a-z0-9](?:[a-z0-9-]{0,78}[a-z0-9])?$",
@@ -280,7 +355,7 @@
280
355
  "ciphertext": {
281
356
  "type": "string",
282
357
  "minLength": 1,
283
- "maxLength": 67108864,
358
+ "maxLength": 104857600,
284
359
  "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
285
360
  },
286
361
  "iterations": {